mirror of
https://github.com/bolucat/Archive.git
synced 2026-04-22 16:07:49 +08:00
Update On Thu Nov 6 19:42:18 CET 2025
This commit is contained in:
@@ -1173,3 +1173,4 @@ Update On Sun Nov 2 19:34:13 CET 2025
|
||||
Update On Mon Nov 3 19:37:13 CET 2025
|
||||
Update On Tue Nov 4 19:40:23 CET 2025
|
||||
Update On Wed Nov 5 19:38:37 CET 2025
|
||||
Update On Thu Nov 6 19:42:10 CET 2025
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
N "github.com/metacubex/mihomo/common/net"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
)
|
||||
|
||||
type Fallback struct {
|
||||
@@ -150,7 +150,7 @@ func (f *Fallback) ForceSet(name string) {
|
||||
f.selected = name
|
||||
}
|
||||
|
||||
func NewFallback(option *GroupCommonOption, providers []provider.ProxyProvider) *Fallback {
|
||||
func NewFallback(option *GroupCommonOption, providers []P.ProxyProvider) *Fallback {
|
||||
return &Fallback{
|
||||
GroupBase: NewGroupBase(GroupBaseOption{
|
||||
Name: option.Name,
|
||||
|
||||
@@ -12,8 +12,7 @@ import (
|
||||
"github.com/metacubex/mihomo/common/atomic"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
"github.com/metacubex/mihomo/tunnel"
|
||||
|
||||
@@ -26,7 +25,7 @@ type GroupBase struct {
|
||||
filterRegs []*regexp2.Regexp
|
||||
excludeFilterRegs []*regexp2.Regexp
|
||||
excludeTypeArray []string
|
||||
providers []provider.ProxyProvider
|
||||
providers []P.ProxyProvider
|
||||
failedTestMux sync.Mutex
|
||||
failedTimes int
|
||||
failedTime time.Time
|
||||
@@ -48,7 +47,7 @@ type GroupBaseOption struct {
|
||||
ExcludeType string
|
||||
TestTimeout int
|
||||
MaxFailedTimes int
|
||||
Providers []provider.ProxyProvider
|
||||
Providers []P.ProxyProvider
|
||||
}
|
||||
|
||||
func NewGroupBase(opt GroupBaseOption) *GroupBase {
|
||||
@@ -125,7 +124,7 @@ func (gb *GroupBase) GetProxies(touch bool) []C.Proxy {
|
||||
}
|
||||
} else {
|
||||
for _, pd := range gb.providers {
|
||||
if pd.VehicleType() == types.Compatible { // compatible provider unneeded filter
|
||||
if pd.VehicleType() == P.Compatible { // compatible provider unneeded filter
|
||||
proxies = append(proxies, pd.Proxies()...)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
N "github.com/metacubex/mihomo/common/net"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
|
||||
"golang.org/x/net/publicsuffix"
|
||||
)
|
||||
@@ -239,7 +239,7 @@ func (lb *LoadBalance) MarshalJSON() ([]byte, error) {
|
||||
})
|
||||
}
|
||||
|
||||
func NewLoadBalance(option *GroupCommonOption, providers []provider.ProxyProvider, strategy string) (lb *LoadBalance, err error) {
|
||||
func NewLoadBalance(option *GroupCommonOption, providers []P.ProxyProvider, strategy string) (lb *LoadBalance, err error) {
|
||||
var strategyFn strategyFn
|
||||
switch strategy {
|
||||
case "consistent-hashing":
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/metacubex/mihomo/common/structure"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
)
|
||||
|
||||
@@ -48,7 +48,7 @@ type GroupCommonOption struct {
|
||||
RoutingMark int `group:"routing-mark,omitempty"`
|
||||
}
|
||||
|
||||
func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, providersMap map[string]types.ProxyProvider, AllProxies []string, AllProviders []string) (C.ProxyAdapter, error) {
|
||||
func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, providersMap map[string]P.ProxyProvider, AllProxies []string, AllProviders []string) (C.ProxyAdapter, error) {
|
||||
decoder := structure.NewDecoder(structure.Option{TagName: "group", WeaklyTypedInput: true})
|
||||
|
||||
groupOption := &GroupCommonOption{
|
||||
@@ -71,7 +71,7 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide
|
||||
|
||||
groupName := groupOption.Name
|
||||
|
||||
providers := []types.ProxyProvider{}
|
||||
providers := []P.ProxyProvider{}
|
||||
|
||||
if groupOption.IncludeAll {
|
||||
groupOption.IncludeAllProviders = true
|
||||
@@ -169,7 +169,7 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide
|
||||
return nil, fmt.Errorf("%s: %w", groupName, err)
|
||||
}
|
||||
|
||||
providers = append([]types.ProxyProvider{pd}, providers...)
|
||||
providers = append([]P.ProxyProvider{pd}, providers...)
|
||||
providersMap[groupName] = pd
|
||||
}
|
||||
|
||||
@@ -206,15 +206,15 @@ func getProxies(mapping map[string]C.Proxy, list []string) ([]C.Proxy, error) {
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
func getProviders(mapping map[string]types.ProxyProvider, list []string) ([]types.ProxyProvider, error) {
|
||||
var ps []types.ProxyProvider
|
||||
func getProviders(mapping map[string]P.ProxyProvider, list []string) ([]P.ProxyProvider, error) {
|
||||
var ps []P.ProxyProvider
|
||||
for _, name := range list {
|
||||
p, ok := mapping[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("'%s' not found", name)
|
||||
}
|
||||
|
||||
if p.VehicleType() == types.Compatible {
|
||||
if p.VehicleType() == P.Compatible {
|
||||
return nil, fmt.Errorf("proxy group %s can't contains in `use`", name)
|
||||
}
|
||||
ps = append(ps, p)
|
||||
@@ -222,7 +222,7 @@ func getProviders(mapping map[string]types.ProxyProvider, list []string) ([]type
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
func addTestUrlToProviders(providers []types.ProxyProvider, url string, expectedStatus utils.IntRanges[uint16], filter string, interval uint) {
|
||||
func addTestUrlToProviders(providers []P.ProxyProvider, url string, expectedStatus utils.IntRanges[uint16], filter string, interval uint) {
|
||||
if len(providers) == 0 || len(url) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,22 +4,22 @@ package outboundgroup
|
||||
|
||||
import (
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
)
|
||||
|
||||
type ProxyGroup interface {
|
||||
C.ProxyAdapter
|
||||
|
||||
Providers() []provider.ProxyProvider
|
||||
Providers() []P.ProxyProvider
|
||||
Proxies() []C.Proxy
|
||||
Now() string
|
||||
}
|
||||
|
||||
func (f *Fallback) Providers() []provider.ProxyProvider {
|
||||
func (f *Fallback) Providers() []P.ProxyProvider {
|
||||
return f.providers
|
||||
}
|
||||
|
||||
func (lb *LoadBalance) Providers() []provider.ProxyProvider {
|
||||
func (lb *LoadBalance) Providers() []P.ProxyProvider {
|
||||
return lb.providers
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func (lb *LoadBalance) Now() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *Relay) Providers() []provider.ProxyProvider {
|
||||
func (r *Relay) Providers() []P.ProxyProvider {
|
||||
return r.providers
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func (r *Relay) Now() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *Selector) Providers() []provider.ProxyProvider {
|
||||
func (s *Selector) Providers() []P.ProxyProvider {
|
||||
return s.providers
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func (s *Selector) Proxies() []C.Proxy {
|
||||
return s.GetProxies(false)
|
||||
}
|
||||
|
||||
func (u *URLTest) Providers() []provider.ProxyProvider {
|
||||
func (u *URLTest) Providers() []P.ProxyProvider {
|
||||
return u.providers
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/dialer"
|
||||
"github.com/metacubex/mihomo/component/proxydialer"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
)
|
||||
|
||||
@@ -149,7 +149,7 @@ func (r *Relay) Addr() string {
|
||||
return proxies[len(proxies)-1].Addr()
|
||||
}
|
||||
|
||||
func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *Relay {
|
||||
func NewRelay(option *GroupCommonOption, providers []P.ProxyProvider) *Relay {
|
||||
log.Warnln("The group [%s] with relay type is deprecated, please using dialer-proxy instead", option.Name)
|
||||
return &Relay{
|
||||
GroupBase: NewGroupBase(GroupBaseOption{
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"errors"
|
||||
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
)
|
||||
|
||||
type Selector struct {
|
||||
@@ -108,7 +108,7 @@ func (s *Selector) selectedProxy(touch bool) C.Proxy {
|
||||
return proxies[0]
|
||||
}
|
||||
|
||||
func NewSelector(option *GroupCommonOption, providers []provider.ProxyProvider) *Selector {
|
||||
func NewSelector(option *GroupCommonOption, providers []P.ProxyProvider) *Selector {
|
||||
return &Selector{
|
||||
GroupBase: NewGroupBase(GroupBaseOption{
|
||||
Name: option.Name,
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/metacubex/mihomo/common/singledo"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
)
|
||||
|
||||
type urlTestOption func(*URLTest)
|
||||
@@ -202,7 +202,7 @@ func parseURLTestOption(config map[string]any) []urlTestOption {
|
||||
return opts
|
||||
}
|
||||
|
||||
func NewURLTest(option *GroupCommonOption, providers []provider.ProxyProvider, options ...urlTestOption) *URLTest {
|
||||
func NewURLTest(option *GroupCommonOption, providers []P.ProxyProvider, options ...urlTestOption) *URLTest {
|
||||
urlTest := &URLTest{
|
||||
GroupBase: NewGroupBase(GroupBaseOption{
|
||||
Name: option.Name,
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
|
||||
"github.com/dlclark/regexp2"
|
||||
)
|
||||
@@ -73,7 +73,7 @@ type proxyProviderSchema struct {
|
||||
Header map[string][]string `provider:"header,omitempty"`
|
||||
}
|
||||
|
||||
func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvider, error) {
|
||||
func ParseProxyProvider(name string, mapping map[string]any) (P.ProxyProvider, error) {
|
||||
decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true})
|
||||
|
||||
schema := &proxyProviderSchema{
|
||||
@@ -104,7 +104,7 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var vehicle types.Vehicle
|
||||
var vehicle P.Vehicle
|
||||
switch schema.Type {
|
||||
case "file":
|
||||
path := C.Path.Resolve(schema.Path)
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/profile/cachefile"
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/tunnel/statistic"
|
||||
|
||||
"github.com/dlclark/regexp2"
|
||||
@@ -68,8 +68,8 @@ func (bp *baseProvider) HealthCheck() {
|
||||
bp.healthCheck.check()
|
||||
}
|
||||
|
||||
func (bp *baseProvider) Type() types.ProviderType {
|
||||
return types.Proxy
|
||||
func (bp *baseProvider) Type() P.ProviderType {
|
||||
return P.Proxy
|
||||
}
|
||||
|
||||
func (bp *baseProvider) Proxies() []C.Proxy {
|
||||
@@ -171,7 +171,7 @@ func (pp *proxySetProvider) Close() error {
|
||||
return pp.Fetcher.Close()
|
||||
}
|
||||
|
||||
func NewProxySetProvider(name string, interval time.Duration, payload []map[string]any, parser resource.Parser[[]C.Proxy], vehicle types.Vehicle, hc *HealthCheck) (*ProxySetProvider, error) {
|
||||
func NewProxySetProvider(name string, interval time.Duration, payload []map[string]any, parser resource.Parser[[]C.Proxy], vehicle P.Vehicle, hc *HealthCheck) (*ProxySetProvider, error) {
|
||||
pd := &proxySetProvider{
|
||||
baseProvider: baseProvider{
|
||||
name: name,
|
||||
@@ -238,8 +238,8 @@ func (ip *inlineProvider) MarshalJSON() ([]byte, error) {
|
||||
})
|
||||
}
|
||||
|
||||
func (ip *inlineProvider) VehicleType() types.VehicleType {
|
||||
return types.Inline
|
||||
func (ip *inlineProvider) VehicleType() P.VehicleType {
|
||||
return P.Inline
|
||||
}
|
||||
|
||||
func (ip *inlineProvider) Update() error {
|
||||
@@ -303,8 +303,8 @@ func (cp *compatibleProvider) Update() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cp *compatibleProvider) VehicleType() types.VehicleType {
|
||||
return types.Compatible
|
||||
func (cp *compatibleProvider) VehicleType() P.VehicleType {
|
||||
return P.Compatible
|
||||
}
|
||||
|
||||
func NewCompatibleProvider(name string, proxies []C.Proxy, hc *HealthCheck) (*CompatibleProvider, error) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
"github.com/metacubex/mihomo/component/slowdown"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
|
||||
"github.com/metacubex/fswatch"
|
||||
@@ -22,7 +22,7 @@ type Fetcher[V any] struct {
|
||||
ctxCancel context.CancelFunc
|
||||
resourceType string
|
||||
name string
|
||||
vehicle types.Vehicle
|
||||
vehicle P.Vehicle
|
||||
updatedAt time.Time
|
||||
hash utils.HashType
|
||||
parser Parser[V]
|
||||
@@ -37,11 +37,11 @@ func (f *Fetcher[V]) Name() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
func (f *Fetcher[V]) Vehicle() types.Vehicle {
|
||||
func (f *Fetcher[V]) Vehicle() P.Vehicle {
|
||||
return f.vehicle
|
||||
}
|
||||
|
||||
func (f *Fetcher[V]) VehicleType() types.VehicleType {
|
||||
func (f *Fetcher[V]) VehicleType() P.VehicleType {
|
||||
return f.vehicle.Type()
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ func (f *Fetcher[V]) Update() (V, bool, error) {
|
||||
f.backoff.AddAttempt() // add a failed attempt to backoff
|
||||
return lo.Empty[V](), false, err
|
||||
}
|
||||
return f.loadBuf(buf, hash, f.vehicle.Type() != types.File)
|
||||
return f.loadBuf(buf, hash, f.vehicle.Type() != P.File)
|
||||
}
|
||||
|
||||
func (f *Fetcher[V]) SideUpdate(buf []byte) (V, bool, error) {
|
||||
@@ -180,7 +180,7 @@ func (f *Fetcher[V]) pullLoop(forceUpdate bool) {
|
||||
|
||||
func (f *Fetcher[V]) startPullLoop(forceUpdate bool) (err error) {
|
||||
// pull contents automatically
|
||||
if f.vehicle.Type() == types.File {
|
||||
if f.vehicle.Type() == P.File {
|
||||
f.watcher, err = fswatch.NewWatcher(fswatch.Options{
|
||||
Path: []string{f.vehicle.Path()},
|
||||
Callback: f.updateCallback,
|
||||
@@ -218,7 +218,7 @@ func (f *Fetcher[V]) updateWithLog() {
|
||||
return
|
||||
}
|
||||
|
||||
func NewFetcher[V any](name string, interval time.Duration, vehicle types.Vehicle, parser Parser[V], onUpdate func(V)) *Fetcher[V] {
|
||||
func NewFetcher[V any](name string, interval time.Duration, vehicle P.Vehicle, parser Parser[V], onUpdate func(V)) *Fetcher[V] {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
minBackoff := 10 * time.Second
|
||||
if interval < minBackoff {
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
mihomoHttp "github.com/metacubex/mihomo/component/http"
|
||||
"github.com/metacubex/mihomo/component/profile/cachefile"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -50,8 +50,8 @@ type FileVehicle struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func (f *FileVehicle) Type() types.VehicleType {
|
||||
return types.File
|
||||
func (f *FileVehicle) Type() P.VehicleType {
|
||||
return P.File
|
||||
}
|
||||
|
||||
func (f *FileVehicle) Path() string {
|
||||
@@ -91,15 +91,15 @@ type HTTPVehicle struct {
|
||||
timeout time.Duration
|
||||
sizeLimit int64
|
||||
inRead func(response *http.Response)
|
||||
provider types.ProxyProvider
|
||||
provider P.ProxyProvider
|
||||
}
|
||||
|
||||
func (h *HTTPVehicle) Url() string {
|
||||
return h.url
|
||||
}
|
||||
|
||||
func (h *HTTPVehicle) Type() types.VehicleType {
|
||||
return types.HTTP
|
||||
func (h *HTTPVehicle) Type() P.VehicleType {
|
||||
return P.HTTP
|
||||
}
|
||||
|
||||
func (h *HTTPVehicle) Path() string {
|
||||
|
||||
+97
-96
@@ -20,15 +20,15 @@ import (
|
||||
"github.com/metacubex/mihomo/component/cidr"
|
||||
"github.com/metacubex/mihomo/component/fakeip"
|
||||
"github.com/metacubex/mihomo/component/geodata"
|
||||
P "github.com/metacubex/mihomo/component/process"
|
||||
"github.com/metacubex/mihomo/component/process"
|
||||
"github.com/metacubex/mihomo/component/resolver"
|
||||
"github.com/metacubex/mihomo/component/sniffer"
|
||||
"github.com/metacubex/mihomo/component/trie"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
providerTypes "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
snifferTypes "github.com/metacubex/mihomo/constant/sniffer"
|
||||
"github.com/metacubex/mihomo/dns"
|
||||
L "github.com/metacubex/mihomo/listener"
|
||||
"github.com/metacubex/mihomo/listener"
|
||||
LC "github.com/metacubex/mihomo/listener/config"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
R "github.com/metacubex/mihomo/rules"
|
||||
@@ -44,27 +44,27 @@ import (
|
||||
// General config
|
||||
type General struct {
|
||||
Inbound
|
||||
Mode T.TunnelMode `json:"mode"`
|
||||
UnifiedDelay bool `json:"unified-delay"`
|
||||
LogLevel log.LogLevel `json:"log-level"`
|
||||
IPv6 bool `json:"ipv6"`
|
||||
Interface string `json:"interface-name"`
|
||||
RoutingMark int `json:"routing-mark"`
|
||||
GeoXUrl GeoXUrl `json:"geox-url"`
|
||||
GeoAutoUpdate bool `json:"geo-auto-update"`
|
||||
GeoUpdateInterval int `json:"geo-update-interval"`
|
||||
GeodataMode bool `json:"geodata-mode"`
|
||||
GeodataLoader string `json:"geodata-loader"`
|
||||
GeositeMatcher string `json:"geosite-matcher"`
|
||||
TCPConcurrent bool `json:"tcp-concurrent"`
|
||||
FindProcessMode P.FindProcessMode `json:"find-process-mode"`
|
||||
Sniffing bool `json:"sniffing"`
|
||||
GlobalClientFingerprint string `json:"global-client-fingerprint"`
|
||||
GlobalUA string `json:"global-ua"`
|
||||
ETagSupport bool `json:"etag-support"`
|
||||
KeepAliveIdle int `json:"keep-alive-idle"`
|
||||
KeepAliveInterval int `json:"keep-alive-interval"`
|
||||
DisableKeepAlive bool `json:"disable-keep-alive"`
|
||||
Mode T.TunnelMode `json:"mode"`
|
||||
UnifiedDelay bool `json:"unified-delay"`
|
||||
LogLevel log.LogLevel `json:"log-level"`
|
||||
IPv6 bool `json:"ipv6"`
|
||||
Interface string `json:"interface-name"`
|
||||
RoutingMark int `json:"routing-mark"`
|
||||
GeoXUrl GeoXUrl `json:"geox-url"`
|
||||
GeoAutoUpdate bool `json:"geo-auto-update"`
|
||||
GeoUpdateInterval int `json:"geo-update-interval"`
|
||||
GeodataMode bool `json:"geodata-mode"`
|
||||
GeodataLoader string `json:"geodata-loader"`
|
||||
GeositeMatcher string `json:"geosite-matcher"`
|
||||
TCPConcurrent bool `json:"tcp-concurrent"`
|
||||
FindProcessMode process.FindProcessMode `json:"find-process-mode"`
|
||||
Sniffing bool `json:"sniffing"`
|
||||
GlobalClientFingerprint string `json:"global-client-fingerprint"`
|
||||
GlobalUA string `json:"global-ua"`
|
||||
ETagSupport bool `json:"etag-support"`
|
||||
KeepAliveIdle int `json:"keep-alive-idle"`
|
||||
KeepAliveInterval int `json:"keep-alive-interval"`
|
||||
DisableKeepAlive bool `json:"disable-keep-alive"`
|
||||
}
|
||||
|
||||
// Inbound config
|
||||
@@ -199,8 +199,8 @@ type Config struct {
|
||||
Users []auth.AuthUser
|
||||
Proxies map[string]C.Proxy
|
||||
Listeners map[string]C.InboundListener
|
||||
Providers map[string]providerTypes.ProxyProvider
|
||||
RuleProviders map[string]providerTypes.RuleProvider
|
||||
Providers map[string]P.ProxyProvider
|
||||
RuleProviders map[string]P.RuleProvider
|
||||
Tunnels []LC.Tunnel
|
||||
Sniffer *sniffer.Config
|
||||
TLS *TLS
|
||||
@@ -382,51 +382,51 @@ type RawTLS struct {
|
||||
}
|
||||
|
||||
type RawConfig struct {
|
||||
Port int `yaml:"port" json:"port"`
|
||||
SocksPort int `yaml:"socks-port" json:"socks-port"`
|
||||
RedirPort int `yaml:"redir-port" json:"redir-port"`
|
||||
TProxyPort int `yaml:"tproxy-port" json:"tproxy-port"`
|
||||
MixedPort int `yaml:"mixed-port" json:"mixed-port"`
|
||||
ShadowSocksConfig string `yaml:"ss-config" json:"ss-config"`
|
||||
VmessConfig string `yaml:"vmess-config" json:"vmess-config"`
|
||||
InboundTfo bool `yaml:"inbound-tfo" json:"inbound-tfo"`
|
||||
InboundMPTCP bool `yaml:"inbound-mptcp" json:"inbound-mptcp"`
|
||||
Authentication []string `yaml:"authentication" json:"authentication"`
|
||||
SkipAuthPrefixes []netip.Prefix `yaml:"skip-auth-prefixes" json:"skip-auth-prefixes"`
|
||||
LanAllowedIPs []netip.Prefix `yaml:"lan-allowed-ips" json:"lan-allowed-ips"`
|
||||
LanDisAllowedIPs []netip.Prefix `yaml:"lan-disallowed-ips" json:"lan-disallowed-ips"`
|
||||
AllowLan bool `yaml:"allow-lan" json:"allow-lan"`
|
||||
BindAddress string `yaml:"bind-address" json:"bind-address"`
|
||||
Mode T.TunnelMode `yaml:"mode" json:"mode"`
|
||||
UnifiedDelay bool `yaml:"unified-delay" json:"unified-delay"`
|
||||
LogLevel log.LogLevel `yaml:"log-level" json:"log-level"`
|
||||
IPv6 bool `yaml:"ipv6" json:"ipv6"`
|
||||
ExternalController string `yaml:"external-controller" json:"external-controller"`
|
||||
ExternalControllerPipe string `yaml:"external-controller-pipe" json:"external-controller-pipe"`
|
||||
ExternalControllerUnix string `yaml:"external-controller-unix" json:"external-controller-unix"`
|
||||
ExternalControllerTLS string `yaml:"external-controller-tls" json:"external-controller-tls"`
|
||||
ExternalControllerCors RawCors `yaml:"external-controller-cors" json:"external-controller-cors"`
|
||||
ExternalUI string `yaml:"external-ui" json:"external-ui"`
|
||||
ExternalUIURL string `yaml:"external-ui-url" json:"external-ui-url"`
|
||||
ExternalUIName string `yaml:"external-ui-name" json:"external-ui-name"`
|
||||
ExternalDohServer string `yaml:"external-doh-server" json:"external-doh-server"`
|
||||
Secret string `yaml:"secret" json:"secret"`
|
||||
Interface string `yaml:"interface-name" json:"interface-name"`
|
||||
RoutingMark int `yaml:"routing-mark" json:"routing-mark"`
|
||||
Tunnels []LC.Tunnel `yaml:"tunnels" json:"tunnels"`
|
||||
GeoAutoUpdate bool `yaml:"geo-auto-update" json:"geo-auto-update"`
|
||||
GeoUpdateInterval int `yaml:"geo-update-interval" json:"geo-update-interval"`
|
||||
GeodataMode bool `yaml:"geodata-mode" json:"geodata-mode"`
|
||||
GeodataLoader string `yaml:"geodata-loader" json:"geodata-loader"`
|
||||
GeositeMatcher string `yaml:"geosite-matcher" json:"geosite-matcher"`
|
||||
TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"`
|
||||
FindProcessMode P.FindProcessMode `yaml:"find-process-mode" json:"find-process-mode"`
|
||||
GlobalClientFingerprint string `yaml:"global-client-fingerprint" json:"global-client-fingerprint"`
|
||||
GlobalUA string `yaml:"global-ua" json:"global-ua"`
|
||||
ETagSupport bool `yaml:"etag-support" json:"etag-support"`
|
||||
KeepAliveIdle int `yaml:"keep-alive-idle" json:"keep-alive-idle"`
|
||||
KeepAliveInterval int `yaml:"keep-alive-interval" json:"keep-alive-interval"`
|
||||
DisableKeepAlive bool `yaml:"disable-keep-alive" json:"disable-keep-alive"`
|
||||
Port int `yaml:"port" json:"port"`
|
||||
SocksPort int `yaml:"socks-port" json:"socks-port"`
|
||||
RedirPort int `yaml:"redir-port" json:"redir-port"`
|
||||
TProxyPort int `yaml:"tproxy-port" json:"tproxy-port"`
|
||||
MixedPort int `yaml:"mixed-port" json:"mixed-port"`
|
||||
ShadowSocksConfig string `yaml:"ss-config" json:"ss-config"`
|
||||
VmessConfig string `yaml:"vmess-config" json:"vmess-config"`
|
||||
InboundTfo bool `yaml:"inbound-tfo" json:"inbound-tfo"`
|
||||
InboundMPTCP bool `yaml:"inbound-mptcp" json:"inbound-mptcp"`
|
||||
Authentication []string `yaml:"authentication" json:"authentication"`
|
||||
SkipAuthPrefixes []netip.Prefix `yaml:"skip-auth-prefixes" json:"skip-auth-prefixes"`
|
||||
LanAllowedIPs []netip.Prefix `yaml:"lan-allowed-ips" json:"lan-allowed-ips"`
|
||||
LanDisAllowedIPs []netip.Prefix `yaml:"lan-disallowed-ips" json:"lan-disallowed-ips"`
|
||||
AllowLan bool `yaml:"allow-lan" json:"allow-lan"`
|
||||
BindAddress string `yaml:"bind-address" json:"bind-address"`
|
||||
Mode T.TunnelMode `yaml:"mode" json:"mode"`
|
||||
UnifiedDelay bool `yaml:"unified-delay" json:"unified-delay"`
|
||||
LogLevel log.LogLevel `yaml:"log-level" json:"log-level"`
|
||||
IPv6 bool `yaml:"ipv6" json:"ipv6"`
|
||||
ExternalController string `yaml:"external-controller" json:"external-controller"`
|
||||
ExternalControllerPipe string `yaml:"external-controller-pipe" json:"external-controller-pipe"`
|
||||
ExternalControllerUnix string `yaml:"external-controller-unix" json:"external-controller-unix"`
|
||||
ExternalControllerTLS string `yaml:"external-controller-tls" json:"external-controller-tls"`
|
||||
ExternalControllerCors RawCors `yaml:"external-controller-cors" json:"external-controller-cors"`
|
||||
ExternalUI string `yaml:"external-ui" json:"external-ui"`
|
||||
ExternalUIURL string `yaml:"external-ui-url" json:"external-ui-url"`
|
||||
ExternalUIName string `yaml:"external-ui-name" json:"external-ui-name"`
|
||||
ExternalDohServer string `yaml:"external-doh-server" json:"external-doh-server"`
|
||||
Secret string `yaml:"secret" json:"secret"`
|
||||
Interface string `yaml:"interface-name" json:"interface-name"`
|
||||
RoutingMark int `yaml:"routing-mark" json:"routing-mark"`
|
||||
Tunnels []LC.Tunnel `yaml:"tunnels" json:"tunnels"`
|
||||
GeoAutoUpdate bool `yaml:"geo-auto-update" json:"geo-auto-update"`
|
||||
GeoUpdateInterval int `yaml:"geo-update-interval" json:"geo-update-interval"`
|
||||
GeodataMode bool `yaml:"geodata-mode" json:"geodata-mode"`
|
||||
GeodataLoader string `yaml:"geodata-loader" json:"geodata-loader"`
|
||||
GeositeMatcher string `yaml:"geosite-matcher" json:"geosite-matcher"`
|
||||
TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"`
|
||||
FindProcessMode process.FindProcessMode `yaml:"find-process-mode" json:"find-process-mode"`
|
||||
GlobalClientFingerprint string `yaml:"global-client-fingerprint" json:"global-client-fingerprint"`
|
||||
GlobalUA string `yaml:"global-ua" json:"global-ua"`
|
||||
ETagSupport bool `yaml:"etag-support" json:"etag-support"`
|
||||
KeepAliveIdle int `yaml:"keep-alive-idle" json:"keep-alive-idle"`
|
||||
KeepAliveInterval int `yaml:"keep-alive-interval" json:"keep-alive-interval"`
|
||||
DisableKeepAlive bool `yaml:"disable-keep-alive" json:"disable-keep-alive"`
|
||||
|
||||
ProxyProvider map[string]map[string]any `yaml:"proxy-providers" json:"proxy-providers"`
|
||||
RuleProvider map[string]map[string]any `yaml:"rule-providers" json:"rule-providers"`
|
||||
@@ -479,7 +479,7 @@ func DefaultRawConfig() *RawConfig {
|
||||
Proxy: []map[string]any{},
|
||||
ProxyGroup: []map[string]any{},
|
||||
TCPConcurrent: false,
|
||||
FindProcessMode: P.FindProcessStrict,
|
||||
FindProcessMode: process.FindProcessStrict,
|
||||
GlobalUA: "clash.meta/" + C.Version,
|
||||
ETagSupport: true,
|
||||
DNS: RawDNS{
|
||||
@@ -653,11 +653,11 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
|
||||
config.Proxies = proxies
|
||||
config.Providers = providers
|
||||
|
||||
listener, err := parseListeners(rawCfg)
|
||||
listeners, err := parseListeners(rawCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Listeners = listener
|
||||
config.Listeners = listeners
|
||||
|
||||
log.Infoln("Geodata Loader mode: %s", geodata.LoaderName())
|
||||
log.Infoln("Geosite Matcher implementation: %s", geodata.SiteMatcherName())
|
||||
@@ -845,9 +845,9 @@ func parseTLS(cfg *RawConfig) (*TLS, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[string]providerTypes.ProxyProvider, err error) {
|
||||
func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[string]P.ProxyProvider, err error) {
|
||||
proxies = make(map[string]C.Proxy)
|
||||
providersMap = make(map[string]providerTypes.ProxyProvider)
|
||||
providersMap = make(map[string]P.ProxyProvider)
|
||||
proxiesConfig := cfg.Proxy
|
||||
groupsConfig := cfg.ProxyGroup
|
||||
providersConfig := cfg.ProxyProvider
|
||||
@@ -947,7 +947,7 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[
|
||||
&outboundgroup.GroupCommonOption{
|
||||
Name: "GLOBAL",
|
||||
},
|
||||
[]providerTypes.ProxyProvider{pd},
|
||||
[]P.ProxyProvider{pd},
|
||||
)
|
||||
proxies["GLOBAL"] = adapter.NewProxy(global)
|
||||
}
|
||||
@@ -957,24 +957,25 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[
|
||||
func parseListeners(cfg *RawConfig) (listeners map[string]C.InboundListener, err error) {
|
||||
listeners = make(map[string]C.InboundListener)
|
||||
for index, mapping := range cfg.Listeners {
|
||||
listener, err := L.ParseListener(mapping)
|
||||
inboundListener, err := listener.ParseListener(mapping)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("proxy %d: %w", index, err)
|
||||
}
|
||||
|
||||
if _, exist := mapping[listener.Name()]; exist {
|
||||
return nil, fmt.Errorf("listener %s is the duplicate name", listener.Name())
|
||||
name := inboundListener.Name()
|
||||
if _, exist := mapping[name]; exist {
|
||||
return nil, fmt.Errorf("listener %s is the duplicate name", name)
|
||||
}
|
||||
|
||||
listeners[listener.Name()] = listener
|
||||
listeners[name] = inboundListener
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseRuleProviders(cfg *RawConfig) (ruleProviders map[string]providerTypes.RuleProvider, err error) {
|
||||
func parseRuleProviders(cfg *RawConfig) (ruleProviders map[string]P.RuleProvider, err error) {
|
||||
RP.SetTunnel(T.Tunnel)
|
||||
ruleProviders = map[string]providerTypes.RuleProvider{}
|
||||
ruleProviders = map[string]P.RuleProvider{}
|
||||
// parse rule provider
|
||||
for name, mapping := range cfg.RuleProvider {
|
||||
rp, err := RP.ParseRuleProvider(name, mapping, R.ParseRule)
|
||||
@@ -987,7 +988,7 @@ func parseRuleProviders(cfg *RawConfig) (ruleProviders map[string]providerTypes.
|
||||
return
|
||||
}
|
||||
|
||||
func parseSubRules(cfg *RawConfig, proxies map[string]C.Proxy, ruleProviders map[string]providerTypes.RuleProvider) (subRules map[string][]C.Rule, err error) {
|
||||
func parseSubRules(cfg *RawConfig, proxies map[string]C.Proxy, ruleProviders map[string]P.RuleProvider) (subRules map[string][]C.Rule, err error) {
|
||||
subRules = map[string][]C.Rule{}
|
||||
for name := range cfg.SubRules {
|
||||
subRules[name] = make([]C.Rule, 0)
|
||||
@@ -1050,7 +1051,7 @@ func verifySubRuleCircularReferences(n string, subRules map[string][]C.Rule, arr
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseRules(rulesConfig []string, proxies map[string]C.Proxy, ruleProviders map[string]providerTypes.RuleProvider, subRules map[string][]C.Rule, format string) ([]C.Rule, error) {
|
||||
func parseRules(rulesConfig []string, proxies map[string]C.Proxy, ruleProviders map[string]P.RuleProvider, subRules map[string][]C.Rule, format string) ([]C.Rule, error) {
|
||||
var rules []C.Rule
|
||||
|
||||
// parse rules
|
||||
@@ -1273,7 +1274,7 @@ func parsePureDNSServer(server string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], ruleProviders map[string]providerTypes.RuleProvider, respectRules bool, preferH3 bool) ([]dns.Policy, error) {
|
||||
func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], ruleProviders map[string]P.RuleProvider, respectRules bool, preferH3 bool) ([]dns.Policy, error) {
|
||||
var policy []dns.Policy
|
||||
|
||||
for pair := nsPolicy.Oldest(); pair != nil; pair = pair.Next() {
|
||||
@@ -1348,7 +1349,7 @@ func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], rulePro
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
func parseDNS(rawCfg *RawConfig, ruleProviders map[string]providerTypes.RuleProvider) (*DNS, error) {
|
||||
func parseDNS(rawCfg *RawConfig, ruleProviders map[string]P.RuleProvider) (*DNS, error) {
|
||||
cfg := rawCfg.DNS
|
||||
if cfg.Enable && len(cfg.NameServer) == 0 {
|
||||
return nil, fmt.Errorf("if DNS configuration is turned on, NameServer cannot be empty")
|
||||
@@ -1632,7 +1633,7 @@ func parseTuicServer(rawTuic RawTuicServer, general *General) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]providerTypes.RuleProvider) (*sniffer.Config, error) {
|
||||
func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]P.RuleProvider) (*sniffer.Config, error) {
|
||||
snifferConfig := &sniffer.Config{
|
||||
Enable: snifferRaw.Enable,
|
||||
ForceDnsMapping: snifferRaw.ForceDnsMapping,
|
||||
@@ -1722,7 +1723,7 @@ func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]providerTypes.
|
||||
return snifferConfig, nil
|
||||
}
|
||||
|
||||
func parseIPCIDR(addresses []string, cidrSet *cidr.IpCidrSet, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (matchers []C.IpMatcher, err error) {
|
||||
func parseIPCIDR(addresses []string, cidrSet *cidr.IpCidrSet, adapterName string, ruleProviders map[string]P.RuleProvider) (matchers []C.IpMatcher, err error) {
|
||||
var matcher C.IpMatcher
|
||||
for _, ipcidr := range addresses {
|
||||
ipcidrLower := strings.ToLower(ipcidr)
|
||||
@@ -1769,7 +1770,7 @@ func parseIPCIDR(addresses []string, cidrSet *cidr.IpCidrSet, adapterName string
|
||||
return
|
||||
}
|
||||
|
||||
func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (matchers []C.DomainMatcher, err error) {
|
||||
func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapterName string, ruleProviders map[string]P.RuleProvider) (matchers []C.DomainMatcher, err error) {
|
||||
var matcher C.DomainMatcher
|
||||
for _, domain := range domains {
|
||||
domainLower := strings.ToLower(domain)
|
||||
@@ -1812,14 +1813,14 @@ func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapte
|
||||
return
|
||||
}
|
||||
|
||||
func parseIPRuleSet(domainSetName string, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (C.IpMatcher, error) {
|
||||
func parseIPRuleSet(domainSetName string, adapterName string, ruleProviders map[string]P.RuleProvider) (C.IpMatcher, error) {
|
||||
if rp, ok := ruleProviders[domainSetName]; !ok {
|
||||
return nil, fmt.Errorf("not found rule-set: %s", domainSetName)
|
||||
} else {
|
||||
switch rp.Behavior() {
|
||||
case providerTypes.Domain:
|
||||
case P.Domain:
|
||||
return nil, fmt.Errorf("rule provider type error, except ipcidr,actual %s", rp.Behavior())
|
||||
case providerTypes.Classical:
|
||||
case P.Classical:
|
||||
log.Warnln("%s provider is %s, only matching it contain ip rule", rp.Name(), rp.Behavior())
|
||||
default:
|
||||
}
|
||||
@@ -1827,14 +1828,14 @@ func parseIPRuleSet(domainSetName string, adapterName string, ruleProviders map[
|
||||
return RP.NewRuleSet(domainSetName, adapterName, false, true)
|
||||
}
|
||||
|
||||
func parseDomainRuleSet(domainSetName string, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (C.DomainMatcher, error) {
|
||||
func parseDomainRuleSet(domainSetName string, adapterName string, ruleProviders map[string]P.RuleProvider) (C.DomainMatcher, error) {
|
||||
if rp, ok := ruleProviders[domainSetName]; !ok {
|
||||
return nil, fmt.Errorf("not found rule-set: %s", domainSetName)
|
||||
} else {
|
||||
switch rp.Behavior() {
|
||||
case providerTypes.IPCIDR:
|
||||
case P.IPCIDR:
|
||||
return nil, fmt.Errorf("rule provider type error, except domain,actual %s", rp.Behavior())
|
||||
case providerTypes.Classical:
|
||||
case P.Classical:
|
||||
log.Warnln("%s provider is %s, only matching it contain domain rule", rp.Name(), rp.Behavior())
|
||||
default:
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/updater"
|
||||
"github.com/metacubex/mihomo/config"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/dns"
|
||||
"github.com/metacubex/mihomo/listener"
|
||||
authStore "github.com/metacubex/mihomo/listener/auth"
|
||||
@@ -303,18 +303,18 @@ func updateHosts(tree *trie.DomainTrie[resolver.HostValue]) {
|
||||
resolver.DefaultHosts = resolver.NewHosts(tree)
|
||||
}
|
||||
|
||||
func updateProxies(proxies map[string]C.Proxy, providers map[string]provider.ProxyProvider) {
|
||||
func updateProxies(proxies map[string]C.Proxy, providers map[string]P.ProxyProvider) {
|
||||
tunnel.UpdateProxies(proxies, providers)
|
||||
}
|
||||
|
||||
func updateRules(rules []C.Rule, subRules map[string][]C.Rule, ruleProviders map[string]provider.RuleProvider) {
|
||||
func updateRules(rules []C.Rule, subRules map[string][]C.Rule, ruleProviders map[string]P.RuleProvider) {
|
||||
tunnel.UpdateRules(rules, subRules, ruleProviders)
|
||||
}
|
||||
|
||||
func loadProvider[P provider.Provider](providers map[string]P) {
|
||||
load := func(pv P) {
|
||||
func loadProvider[T P.Provider](providers map[string]T) {
|
||||
load := func(pv T) {
|
||||
name := pv.Name()
|
||||
if pv.VehicleType() == provider.Compatible {
|
||||
if pv.VehicleType() == P.Compatible {
|
||||
log.Infoln("Start initial compatible provider %s", name)
|
||||
} else {
|
||||
log.Infoln("Start initial provider %s", name)
|
||||
@@ -322,11 +322,11 @@ func loadProvider[P provider.Provider](providers map[string]P) {
|
||||
|
||||
if err := pv.Initial(); err != nil {
|
||||
switch pv.Type() {
|
||||
case provider.Proxy:
|
||||
case P.Proxy:
|
||||
{
|
||||
log.Errorln("initial proxy provider %s error: %v", name, err)
|
||||
}
|
||||
case provider.Rule:
|
||||
case P.Rule:
|
||||
{
|
||||
log.Errorln("initial rule provider %s error: %v", name, err)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/metacubex/mihomo/config"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/hub/executor"
|
||||
P "github.com/metacubex/mihomo/listener"
|
||||
"github.com/metacubex/mihomo/listener"
|
||||
LC "github.com/metacubex/mihomo/listener/config"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
"github.com/metacubex/mihomo/tunnel"
|
||||
@@ -306,7 +306,7 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if general.AllowLan != nil {
|
||||
P.SetAllowLan(*general.AllowLan)
|
||||
listener.SetAllowLan(*general.AllowLan)
|
||||
}
|
||||
|
||||
if general.SkipAuthPrefixes != nil {
|
||||
@@ -322,7 +322,7 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if general.BindAddress != nil {
|
||||
P.SetBindAddress(*general.BindAddress)
|
||||
listener.SetBindAddress(*general.BindAddress)
|
||||
}
|
||||
|
||||
if general.Sniffing != nil {
|
||||
@@ -337,17 +337,17 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
|
||||
dialer.DefaultInterface.Store(*general.InterfaceName)
|
||||
}
|
||||
|
||||
ports := P.GetPorts()
|
||||
ports := listener.GetPorts()
|
||||
|
||||
P.ReCreateHTTP(pointerOrDefault(general.Port, ports.Port), tunnel.Tunnel)
|
||||
P.ReCreateSocks(pointerOrDefault(general.SocksPort, ports.SocksPort), tunnel.Tunnel)
|
||||
P.ReCreateRedir(pointerOrDefault(general.RedirPort, ports.RedirPort), tunnel.Tunnel)
|
||||
P.ReCreateTProxy(pointerOrDefault(general.TProxyPort, ports.TProxyPort), tunnel.Tunnel)
|
||||
P.ReCreateMixed(pointerOrDefault(general.MixedPort, ports.MixedPort), tunnel.Tunnel)
|
||||
P.ReCreateTun(pointerOrDefaultTun(general.Tun, P.LastTunConf), tunnel.Tunnel)
|
||||
P.ReCreateShadowSocks(pointerOrDefault(general.ShadowSocksConfig, ports.ShadowSocksConfig), tunnel.Tunnel)
|
||||
P.ReCreateVmess(pointerOrDefault(general.VmessConfig, ports.VmessConfig), tunnel.Tunnel)
|
||||
P.ReCreateTuic(pointerOrDefaultTuicServer(general.TuicServer, P.LastTuicConf), tunnel.Tunnel)
|
||||
listener.ReCreateHTTP(pointerOrDefault(general.Port, ports.Port), tunnel.Tunnel)
|
||||
listener.ReCreateSocks(pointerOrDefault(general.SocksPort, ports.SocksPort), tunnel.Tunnel)
|
||||
listener.ReCreateRedir(pointerOrDefault(general.RedirPort, ports.RedirPort), tunnel.Tunnel)
|
||||
listener.ReCreateTProxy(pointerOrDefault(general.TProxyPort, ports.TProxyPort), tunnel.Tunnel)
|
||||
listener.ReCreateMixed(pointerOrDefault(general.MixedPort, ports.MixedPort), tunnel.Tunnel)
|
||||
listener.ReCreateTun(pointerOrDefaultTun(general.Tun, listener.LastTunConf), tunnel.Tunnel)
|
||||
listener.ReCreateShadowSocks(pointerOrDefault(general.ShadowSocksConfig, ports.ShadowSocksConfig), tunnel.Tunnel)
|
||||
listener.ReCreateVmess(pointerOrDefault(general.VmessConfig, ports.VmessConfig), tunnel.Tunnel)
|
||||
listener.ReCreateTuic(pointerOrDefaultTuicServer(general.TuicServer, listener.LastTuicConf), tunnel.Tunnel)
|
||||
|
||||
if general.Mode != nil {
|
||||
tunnel.SetMode(*general.Mode)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/tunnel"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
@@ -45,12 +45,12 @@ func getProviders(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func getProvider(w http.ResponseWriter, r *http.Request) {
|
||||
provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
|
||||
provider := r.Context().Value(CtxKeyProvider).(P.ProxyProvider)
|
||||
render.JSON(w, r, provider)
|
||||
}
|
||||
|
||||
func updateProvider(w http.ResponseWriter, r *http.Request) {
|
||||
provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
|
||||
provider := r.Context().Value(CtxKeyProvider).(P.ProxyProvider)
|
||||
if err := provider.Update(); err != nil {
|
||||
render.Status(r, http.StatusServiceUnavailable)
|
||||
render.JSON(w, r, newError(err.Error()))
|
||||
@@ -60,7 +60,7 @@ func updateProvider(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func healthCheckProvider(w http.ResponseWriter, r *http.Request) {
|
||||
provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
|
||||
provider := r.Context().Value(CtxKeyProvider).(P.ProxyProvider)
|
||||
provider.HealthCheck()
|
||||
render.NoContent(w, r)
|
||||
}
|
||||
@@ -93,7 +93,7 @@ func findProviderProxyByName(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
name = r.Context().Value(CtxKeyProxyName).(string)
|
||||
pd = r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
|
||||
pd = r.Context().Value(CtxKeyProvider).(P.ProxyProvider)
|
||||
)
|
||||
proxy, exist := lo.Find(pd.Proxies(), func(proxy C.Proxy) bool {
|
||||
return proxy.Name() == name
|
||||
@@ -128,7 +128,7 @@ func getRuleProviders(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func updateRuleProvider(w http.ResponseWriter, r *http.Request) {
|
||||
provider := r.Context().Value(CtxKeyProvider).(provider.RuleProvider)
|
||||
provider := r.Context().Value(CtxKeyProvider).(P.RuleProvider)
|
||||
if err := provider.Update(); err != nil {
|
||||
render.Status(r, http.StatusServiceUnavailable)
|
||||
render.JSON(w, r, newError(err.Error()))
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/iface"
|
||||
"github.com/metacubex/mihomo/component/resolver"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
LC "github.com/metacubex/mihomo/listener/config"
|
||||
"github.com/metacubex/mihomo/listener/sing"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
@@ -133,7 +133,7 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis
|
||||
}
|
||||
}
|
||||
ctx := context.TODO()
|
||||
rpTunnel := tunnel.(provider.Tunnel)
|
||||
rpTunnel := tunnel.(P.Tunnel)
|
||||
if options.GSOMaxSize == 0 {
|
||||
options.GSOMaxSize = 65536
|
||||
}
|
||||
@@ -504,7 +504,7 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis
|
||||
return
|
||||
}
|
||||
|
||||
func (l *Listener) ruleUpdateCallback(ruleProvider provider.RuleProvider) {
|
||||
func (l *Listener) ruleUpdateCallback(ruleProvider P.RuleProvider) {
|
||||
name := ruleProvider.Name()
|
||||
if slices.Contains(l.options.RouteAddressSet, name) {
|
||||
l.updateRule(ruleProvider, false, true)
|
||||
@@ -520,7 +520,7 @@ type toIpCidr interface {
|
||||
ToIpCidr() *netipx.IPSet
|
||||
}
|
||||
|
||||
func (l *Listener) updateRule(ruleProvider provider.RuleProvider, exclude bool, update bool) {
|
||||
func (l *Listener) updateRule(ruleProvider P.RuleProvider, exclude bool, update bool) {
|
||||
l.ruleUpdateMutex.Lock()
|
||||
defer l.ruleUpdateMutex.Unlock()
|
||||
name := ruleProvider.Name()
|
||||
|
||||
+21
-21
@@ -17,13 +17,13 @@ import (
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
"github.com/metacubex/mihomo/component/loopback"
|
||||
"github.com/metacubex/mihomo/component/nat"
|
||||
P "github.com/metacubex/mihomo/component/process"
|
||||
"github.com/metacubex/mihomo/component/process"
|
||||
"github.com/metacubex/mihomo/component/resolver"
|
||||
"github.com/metacubex/mihomo/component/slowdown"
|
||||
"github.com/metacubex/mihomo/component/sniffer"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/features"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
icontext "github.com/metacubex/mihomo/context"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
"github.com/metacubex/mihomo/tunnel/statistic"
|
||||
@@ -43,8 +43,8 @@ var (
|
||||
listeners = make(map[string]C.InboundListener)
|
||||
subRules map[string][]C.Rule
|
||||
proxies = make(map[string]C.Proxy)
|
||||
providers map[string]provider.ProxyProvider
|
||||
ruleProviders map[string]provider.RuleProvider
|
||||
providers map[string]P.ProxyProvider
|
||||
ruleProviders map[string]P.RuleProvider
|
||||
configMux sync.RWMutex
|
||||
|
||||
// for compatibility, lazy init
|
||||
@@ -59,19 +59,19 @@ var (
|
||||
// default timeout for UDP session
|
||||
udpTimeout = 60 * time.Second
|
||||
|
||||
findProcessMode = atomic.NewInt32Enum(P.FindProcessStrict)
|
||||
findProcessMode = atomic.NewInt32Enum(process.FindProcessStrict)
|
||||
|
||||
snifferDispatcher *sniffer.Dispatcher
|
||||
sniffingEnable = false
|
||||
|
||||
ruleUpdateCallback = utils.NewCallback[provider.RuleProvider]()
|
||||
ruleUpdateCallback = utils.NewCallback[P.RuleProvider]()
|
||||
)
|
||||
|
||||
type tunnel struct{}
|
||||
|
||||
var Tunnel = tunnel{}
|
||||
var _ C.Tunnel = Tunnel
|
||||
var _ provider.Tunnel = Tunnel
|
||||
var _ P.Tunnel = Tunnel
|
||||
|
||||
func (t tunnel) HandleTCPConn(conn net.Conn, metadata *C.Metadata) {
|
||||
connCtx := icontext.NewConnContext(conn, metadata)
|
||||
@@ -112,15 +112,15 @@ func (t tunnel) NatTable() C.NatTable {
|
||||
return natTable
|
||||
}
|
||||
|
||||
func (t tunnel) Providers() map[string]provider.ProxyProvider {
|
||||
func (t tunnel) Providers() map[string]P.ProxyProvider {
|
||||
return providers
|
||||
}
|
||||
|
||||
func (t tunnel) RuleProviders() map[string]provider.RuleProvider {
|
||||
func (t tunnel) RuleProviders() map[string]P.RuleProvider {
|
||||
return ruleProviders
|
||||
}
|
||||
|
||||
func (t tunnel) RuleUpdateCallback() *utils.Callback[provider.RuleProvider] {
|
||||
func (t tunnel) RuleUpdateCallback() *utils.Callback[P.RuleProvider] {
|
||||
return ruleUpdateCallback
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ func Listeners() map[string]C.InboundListener {
|
||||
}
|
||||
|
||||
// UpdateRules handle update rules
|
||||
func UpdateRules(newRules []C.Rule, newSubRule map[string][]C.Rule, rp map[string]provider.RuleProvider) {
|
||||
func UpdateRules(newRules []C.Rule, newSubRule map[string][]C.Rule, rp map[string]P.RuleProvider) {
|
||||
configMux.Lock()
|
||||
rules = newRules
|
||||
ruleProviders = rp
|
||||
@@ -223,17 +223,17 @@ func ProxiesWithProviders() map[string]C.Proxy {
|
||||
}
|
||||
|
||||
// Providers return all compatible providers
|
||||
func Providers() map[string]provider.ProxyProvider {
|
||||
func Providers() map[string]P.ProxyProvider {
|
||||
return providers
|
||||
}
|
||||
|
||||
// RuleProviders return all loaded rule providers
|
||||
func RuleProviders() map[string]provider.RuleProvider {
|
||||
func RuleProviders() map[string]P.RuleProvider {
|
||||
return ruleProviders
|
||||
}
|
||||
|
||||
// UpdateProxies handle update proxies
|
||||
func UpdateProxies(newProxies map[string]C.Proxy, newProviders map[string]provider.ProxyProvider) {
|
||||
func UpdateProxies(newProxies map[string]C.Proxy, newProviders map[string]P.ProxyProvider) {
|
||||
configMux.Lock()
|
||||
proxies = newProxies
|
||||
providers = newProviders
|
||||
@@ -263,13 +263,13 @@ func SetMode(m TunnelMode) {
|
||||
mode = m
|
||||
}
|
||||
|
||||
func FindProcessMode() P.FindProcessMode {
|
||||
func FindProcessMode() process.FindProcessMode {
|
||||
return findProcessMode.Load()
|
||||
}
|
||||
|
||||
// SetFindProcessMode replace SetAlwaysFindProcess
|
||||
// always find process info if legacyAlways = true or mode.Always() = true, may be increase many memory
|
||||
func SetFindProcessMode(mode P.FindProcessMode) {
|
||||
func SetFindProcessMode(mode process.FindProcessMode) {
|
||||
findProcessMode.Store(mode)
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ func resolveMetadata(metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err erro
|
||||
attemptProcessLookup = false
|
||||
if !features.CMFA {
|
||||
// normal check for process
|
||||
uid, path, err := P.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, int(metadata.SrcPort))
|
||||
uid, path, err := process.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, int(metadata.SrcPort))
|
||||
if err != nil {
|
||||
log.Debugln("[Process] find process error for %s: %v", metadata.String(), err)
|
||||
} else {
|
||||
@@ -366,13 +366,13 @@ func resolveMetadata(metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err erro
|
||||
metadata.ProcessPath = path
|
||||
metadata.Uid = uid
|
||||
|
||||
if pkg, err := P.FindPackageName(metadata); err == nil { // for android (not CMFA) package names
|
||||
if pkg, err := process.FindPackageName(metadata); err == nil { // for android (not CMFA) package names
|
||||
metadata.Process = pkg
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// check package names
|
||||
pkg, err := P.FindPackageName(metadata)
|
||||
pkg, err := process.FindPackageName(metadata)
|
||||
if err != nil {
|
||||
log.Debugln("[Process] find process error for %s: %v", metadata.String(), err)
|
||||
} else {
|
||||
@@ -384,10 +384,10 @@ func resolveMetadata(metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err erro
|
||||
}
|
||||
|
||||
switch FindProcessMode() {
|
||||
case P.FindProcessAlways:
|
||||
case process.FindProcessAlways:
|
||||
helper.FindProcess()
|
||||
helper.FindProcess = nil
|
||||
case P.FindProcessOff:
|
||||
case process.FindProcessOff:
|
||||
helper.FindProcess = nil
|
||||
}
|
||||
|
||||
|
||||
Generated
+84
-84
@@ -365,7 +365,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -531,7 +531,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -566,7 +566,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -615,7 +615,7 @@ checksum = "99e1aca718ea7b89985790c94aad72d77533063fe00bc497bb79a7c2dae6a661"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -860,7 +860,7 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc-hash 1.1.0",
|
||||
"shlex",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"which 4.4.2",
|
||||
]
|
||||
|
||||
@@ -1058,7 +1058,7 @@ checksum = "9fd3f870829131332587f607a7ff909f1af5fc523fd1b192db55fbbdf52e8d3c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -1196,7 +1196,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1488,7 +1488,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1722,7 +1722,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2003,7 +2003,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2013,7 +2013,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2054,7 +2054,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2065,7 +2065,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2156,7 +2156,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2177,7 +2177,7 @@ dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2187,7 +2187,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||
dependencies = [
|
||||
"derive_builder_core",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2200,7 +2200,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2355,7 +2355,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2387,7 +2387,7 @@ checksum = "788160fb30de9cdd857af31c6a2675904b16ece8fc2737b2c7127ba368c9d0f4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2685,7 +2685,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2706,7 +2706,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2777,7 +2777,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2898,7 +2898,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3055,7 +3055,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3205,7 +3205,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3511,7 +3511,7 @@ dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3773,7 +3773,7 @@ dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4302,7 +4302,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4404,7 +4404,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"sha2 0.10.9",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4421,7 +4421,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.9",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"url",
|
||||
]
|
||||
|
||||
@@ -4519,7 +4519,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5122,7 +5122,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5632,7 +5632,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5694,7 +5694,7 @@ dependencies = [
|
||||
"proc-macro-crate 3.3.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5763,7 +5763,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6419,7 +6419,7 @@ checksum = "05bbaa5b6b98826bb62b164406f703bee72c5287af9986f9c863fa8ea992b476"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6461,7 +6461,7 @@ dependencies = [
|
||||
"phf 0.13.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6721,7 +6721,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6869,7 +6869,7 @@ dependencies = [
|
||||
"phf_shared 0.11.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
@@ -6883,7 +6883,7 @@ dependencies = [
|
||||
"phf_shared 0.13.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6946,7 +6946,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7124,7 +7124,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7210,7 +7210,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7608,7 +7608,7 @@ checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7817,7 +7817,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8025,7 +8025,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_derive_internals",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8169,7 +8169,7 @@ checksum = "d6185cf75117e20e62b1ff867b9518577271e58abe0037c40bb4794969355ab0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8180,7 +8180,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8215,7 +8215,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8277,7 +8277,7 @@ dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8325,7 +8325,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8717,7 +8717,7 @@ dependencies = [
|
||||
"Inflector",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8841,7 +8841,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8884,9 +8884,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.108"
|
||||
version = "2.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
|
||||
checksum = "2f17c7e013e88258aa9543dcbe81aca68a667a9ac37cd69c9fbc07858bfe0e2f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -8910,7 +8910,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9032,7 +9032,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9152,7 +9152,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.9",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"tauri-utils",
|
||||
"thiserror 2.0.17",
|
||||
"time",
|
||||
@@ -9170,7 +9170,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"tauri-codegen",
|
||||
"tauri-utils",
|
||||
]
|
||||
@@ -9476,7 +9476,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9645,7 +9645,7 @@ checksum = "451b374529930d7601b1eef8d32bc79ae870b6079b069401709c2a8bf9e75f36"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9691,7 +9691,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9702,7 +9702,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9859,7 +9859,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10082,7 +10082,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10174,7 +10174,7 @@ version = "0.2.5"
|
||||
source = "git+https://github.com/Frando/tracing-test.git?rev=e81ec65#e81ec655a5ec5c4351104628b1b1ba694f80a1dc"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10680,7 +10680,7 @@ dependencies = [
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -10715,7 +10715,7 @@ checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -10997,7 +10997,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11414,7 +11414,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11425,7 +11425,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11436,7 +11436,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11447,7 +11447,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -12229,7 +12229,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -12241,7 +12241,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -12297,7 +12297,7 @@ checksum = "dc6821851fa840b708b4cbbaf6241868cabc85a2dc22f426361b0292bfc0b836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"zbus-lockstep",
|
||||
"zbus_xml",
|
||||
"zvariant",
|
||||
@@ -12312,7 +12312,7 @@ dependencies = [
|
||||
"proc-macro-crate 3.3.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"zbus_names",
|
||||
"zvariant",
|
||||
"zvariant_utils",
|
||||
@@ -12360,7 +12360,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -12380,7 +12380,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -12401,7 +12401,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -12445,7 +12445,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -12456,7 +12456,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -12601,7 +12601,7 @@ dependencies = [
|
||||
"proc-macro-crate 3.3.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
@@ -12614,6 +12614,6 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn 2.0.108",
|
||||
"syn 2.0.109",
|
||||
"winnow 0.7.13",
|
||||
]
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"build": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "5.90.6",
|
||||
"@tanstack/react-query": "5.90.7",
|
||||
"@tauri-apps/api": "2.8.0",
|
||||
"ahooks": "3.9.6",
|
||||
"dayjs": "1.11.19",
|
||||
|
||||
@@ -56,9 +56,9 @@
|
||||
"@csstools/normalize.css": "12.1.1",
|
||||
"@emotion/babel-plugin": "11.13.5",
|
||||
"@emotion/react": "11.14.0",
|
||||
"@iconify/json": "2.2.403",
|
||||
"@iconify/json": "2.2.404",
|
||||
"@monaco-editor/react": "4.7.0",
|
||||
"@tanstack/react-query": "5.90.6",
|
||||
"@tanstack/react-query": "5.90.7",
|
||||
"@tanstack/react-router": "1.134.12",
|
||||
"@tanstack/react-router-devtools": "1.134.12",
|
||||
"@tanstack/router-plugin": "1.134.12",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"manifest_version": 1,
|
||||
"latest": {
|
||||
"mihomo": "v1.19.15",
|
||||
"mihomo_alpha": "alpha-5a285ac",
|
||||
"mihomo_alpha": "alpha-8b32c43",
|
||||
"clash_rs": "v0.9.2",
|
||||
"clash_premium": "2023-09-05-gdcc8d87",
|
||||
"clash_rs_alpha": "0.9.2-alpha+sha.b24d5a9"
|
||||
@@ -69,5 +69,5 @@
|
||||
"linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf"
|
||||
}
|
||||
},
|
||||
"updated_at": "2025-11-04T22:21:06.320Z"
|
||||
"updated_at": "2025-11-05T22:21:12.319Z"
|
||||
}
|
||||
|
||||
Generated
+16
-16
@@ -179,8 +179,8 @@ importers:
|
||||
frontend/interface:
|
||||
dependencies:
|
||||
'@tanstack/react-query':
|
||||
specifier: 5.90.6
|
||||
version: 5.90.6(react@19.2.0)
|
||||
specifier: 5.90.7
|
||||
version: 5.90.7(react@19.2.0)
|
||||
'@tauri-apps/api':
|
||||
specifier: 2.8.0
|
||||
version: 2.8.0
|
||||
@@ -346,14 +346,14 @@ importers:
|
||||
specifier: 11.14.0
|
||||
version: 11.14.0(@types/react@19.2.2)(react@19.2.0)
|
||||
'@iconify/json':
|
||||
specifier: 2.2.403
|
||||
version: 2.2.403
|
||||
specifier: 2.2.404
|
||||
version: 2.2.404
|
||||
'@monaco-editor/react':
|
||||
specifier: 4.7.0
|
||||
version: 4.7.0(monaco-editor@0.54.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||
'@tanstack/react-query':
|
||||
specifier: 5.90.6
|
||||
version: 5.90.6(react@19.2.0)
|
||||
specifier: 5.90.7
|
||||
version: 5.90.7(react@19.2.0)
|
||||
'@tanstack/react-router':
|
||||
specifier: 1.134.12
|
||||
version: 1.134.12(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||
@@ -1821,8 +1821,8 @@ packages:
|
||||
prettier-plugin-ember-template-tag:
|
||||
optional: true
|
||||
|
||||
'@iconify/json@2.2.403':
|
||||
resolution: {integrity: sha512-TU27b9pVsbYuTKF7i/OHAB5rUscWhe85AEk0vPkDT1MMqV7ZWWxUk5B7j03JHacX5NCtggB1KiCz985wjc7HVQ==}
|
||||
'@iconify/json@2.2.404':
|
||||
resolution: {integrity: sha512-K11bUBMW7gb/PhzJNZvDDJDq3hEVXoJArsdbr+9LQQqd2TrWEd5+PtctNcfJLu4epgjwDppaLJnN6AEPI1BL9w==}
|
||||
|
||||
'@iconify/types@2.0.0':
|
||||
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
||||
@@ -3170,11 +3170,11 @@ packages:
|
||||
resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@tanstack/query-core@5.90.6':
|
||||
resolution: {integrity: sha512-AnZSLF26R8uX+tqb/ivdrwbVdGemdEDm1Q19qM6pry6eOZ6bEYiY7mWhzXT1YDIPTNEVcZ5kYP9nWjoxDLiIVw==}
|
||||
'@tanstack/query-core@5.90.7':
|
||||
resolution: {integrity: sha512-6PN65csiuTNfBMXqQUxQhCNdtm1rV+9kC9YwWAIKcaxAauq3Wu7p18j3gQY3YIBJU70jT/wzCCZ2uqto/vQgiQ==}
|
||||
|
||||
'@tanstack/react-query@5.90.6':
|
||||
resolution: {integrity: sha512-gB1sljYjcobZKxjPbKSa31FUTyr+ROaBdoH+wSSs9Dk+yDCmMs+TkTV3PybRRVLC7ax7q0erJ9LvRWnMktnRAw==}
|
||||
'@tanstack/react-query@5.90.7':
|
||||
resolution: {integrity: sha512-wAHc/cgKzW7LZNFloThyHnV/AX9gTg3w5yAv0gvQHPZoCnepwqCMtzbuPbb2UvfvO32XZ46e8bPOYbfZhzVnnQ==}
|
||||
peerDependencies:
|
||||
react: ^18 || ^19
|
||||
|
||||
@@ -10349,7 +10349,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@iconify/json@2.2.403':
|
||||
'@iconify/json@2.2.404':
|
||||
dependencies:
|
||||
'@iconify/types': 2.0.0
|
||||
pathe: 2.0.3
|
||||
@@ -11598,11 +11598,11 @@ snapshots:
|
||||
dependencies:
|
||||
remove-accents: 0.5.0
|
||||
|
||||
'@tanstack/query-core@5.90.6': {}
|
||||
'@tanstack/query-core@5.90.7': {}
|
||||
|
||||
'@tanstack/react-query@5.90.6(react@19.2.0)':
|
||||
'@tanstack/react-query@5.90.7(react@19.2.0)':
|
||||
dependencies:
|
||||
'@tanstack/query-core': 5.90.6
|
||||
'@tanstack/query-core': 5.90.7
|
||||
react: 19.2.0
|
||||
|
||||
'@tanstack/react-router-devtools@1.134.12(@tanstack/react-router@1.134.12(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.134.12)(@types/node@24.10.0)(csstype@3.1.3)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass-embedded@1.93.3)(sass@1.93.3)(solid-js@1.9.5)(stylus@0.62.0)(terser@5.36.0)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1)':
|
||||
|
||||
@@ -41,8 +41,8 @@ async function resolvePublish() {
|
||||
const nextVersion = `${a}.${b}.${c}`
|
||||
const nextNightlyVersion = `${a}.${b}.${c + 1}`
|
||||
packageJson.version = nextVersion
|
||||
tauriJson.package.version = nextVersion
|
||||
tauriNightlyJson.package.version = nextNightlyVersion
|
||||
tauriJson.version = nextVersion
|
||||
tauriNightlyJson.version = nextNightlyVersion
|
||||
|
||||
// 发布更新前先写更新日志
|
||||
// const nextTag = `v${nextVersion}`;
|
||||
|
||||
@@ -321,15 +321,14 @@ menu "Target Images"
|
||||
depends on USES_BOOT_PART
|
||||
default 8 if TARGET_apm821xx_sata
|
||||
default 128 if TARGET_armsr
|
||||
default 64 if TARGET_bcm27xx
|
||||
default 64 if TARGET_bcm27xx || TARGET_x86 || TARGET_loongarch64
|
||||
default 32 if TARGET_rockchip
|
||||
default 16
|
||||
|
||||
config TARGET_ROOTFS_PARTSIZE
|
||||
int "Root filesystem partition size (in MiB)"
|
||||
depends on USES_ROOTFS_PART || TARGET_ROOTFS_EXT4FS
|
||||
default 232 if TARGET_loongarch64
|
||||
default 448 if TARGET_mediatek || TARGET_x86
|
||||
default 448 if TARGET_mediatek || TARGET_x86 || TARGET_loongarch64
|
||||
default 160
|
||||
help
|
||||
Select the root filesystem partition size.
|
||||
|
||||
@@ -481,15 +481,14 @@ define KernelPackage/drm-amdgpu
|
||||
DEPENDS:=@TARGET_x86 @DISPLAY_SUPPORT +kmod-backlight +kmod-drm-ttm \
|
||||
+kmod-drm-ttm-helper +kmod-drm-kms-helper +kmod-i2c-algo-bit +amdgpu-firmware \
|
||||
+kmod-drm-display-helper +kmod-drm-buddy +kmod-acpi-video \
|
||||
+(LINUX_6_6||LINUX_6_12):kmod-drm-exec +(LINUX_6_6||LINUX_6_12):kmod-drm-suballoc-helper
|
||||
+(LINUX_6_6||LINUX_6_12):kmod-drm-exec +(LINUX_6_6||LINUX_6_12):kmod-drm-suballoc-helper +kmod-drm-sched
|
||||
KCONFIG:=CONFIG_DRM_AMDGPU \
|
||||
CONFIG_DRM_AMDGPU_SI=y \
|
||||
CONFIG_DRM_AMDGPU_CIK=y \
|
||||
CONFIG_DRM_AMD_DC=y \
|
||||
CONFIG_DEBUG_KERNEL_DC=n
|
||||
FILES:=$(LINUX_DIR)/drivers/gpu/drm/amd/amdgpu/amdgpu.ko \
|
||||
$(LINUX_DIR)/drivers/gpu/drm/amd/amdxcp/amdxcp.ko@ge6.5 \
|
||||
$(LINUX_DIR)/drivers/gpu/drm/scheduler/gpu-sched.ko
|
||||
$(LINUX_DIR)/drivers/gpu/drm/amd/amdxcp/amdxcp.ko@ge6.5
|
||||
AUTOLOAD:=$(call AutoProbe,amdgpu)
|
||||
endef
|
||||
|
||||
@@ -754,6 +753,31 @@ endef
|
||||
|
||||
$(eval $(call KernelPackage,drm-nouveau))
|
||||
|
||||
|
||||
define KernelPackage/drm-xe
|
||||
SUBMENU:=$(VIDEO_MENU)
|
||||
TITLE:=Intel Xe GPU drm support
|
||||
DEPENDS:=@TARGET_x86 +kmod-drm-buddy +kmod-drm-ttm +kmod-drm-kms-helper +kmod-drm-i915 +i915-firmware \
|
||||
+kmod-drm-display-helper +kmod-acpi-video \
|
||||
+kmod-drm-exec +kmod-drm-suballoc-helper +kmod-drm-sched @LINUX_6_12
|
||||
KCONFIG:= \
|
||||
CONFIG_DRM_GPUVM \
|
||||
CONFIG_DRM_SCHED \
|
||||
CONFIG_DRM_XE
|
||||
FILES:= \
|
||||
$(LINUX_DIR)/drivers/gpu/drm/drm_gpuvm.ko \
|
||||
$(LINUX_DIR)/drivers/gpu/drm/xe/xe.ko
|
||||
AUTOLOAD:=$(call AutoProbe,gpu-sched drm_gpuvm xe)
|
||||
endef
|
||||
|
||||
define KernelPackage/drm-xe/description
|
||||
The drm/xe driver supports some future GFX cards with rendering, display,
|
||||
compute and media. Support for currently available platforms like TGL, ADL,
|
||||
DG2, etc is provided to prototype the driver.
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,drm-xe))
|
||||
|
||||
#
|
||||
# Video Capture
|
||||
#
|
||||
|
||||
@@ -22,6 +22,13 @@ define Package/autocore-arm
|
||||
VARIANT:=arm
|
||||
endef
|
||||
|
||||
define Package/autocore-loongarch64
|
||||
TITLE:=Loongarch64 auto core loadbalance script.
|
||||
MAINTAINER:=LEAN
|
||||
DEPENDS:=@loongarch64 +bc +ethtool +pciutils
|
||||
VARIANT:=loongarch64
|
||||
endef
|
||||
|
||||
define Package/autocore-x86
|
||||
TITLE:=x86/x64 auto core loadbalance script.
|
||||
MAINTAINER:=Lean
|
||||
@@ -33,6 +40,10 @@ define Package/autocore-arm/description
|
||||
A luci autoconfig hotplug script.
|
||||
endef
|
||||
|
||||
define Package/autocore-loongarch64/description
|
||||
A luci autoconfig hotplug script.
|
||||
endef
|
||||
|
||||
define Package/autocore-x86/description
|
||||
A usb autoconfig hotplug script.
|
||||
endef
|
||||
@@ -57,6 +68,19 @@ endif
|
||||
$(CP) ./files/luci-mod-status-autocore.json $(1)/usr/share/rpcd/acl.d/
|
||||
endef
|
||||
|
||||
define Package/autocore-loongarch64/install
|
||||
$(INSTALL_DIR) $(1)/etc
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/loongarch64/autocore $(1)/etc/init.d/autocore
|
||||
$(INSTALL_BIN) ./files/60-autocore-reload-rpcd $(1)/etc/uci-defaults/
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(INSTALL_BIN) ./files/loongarch64/sbin/cpuinfo $(1)/sbin/cpuinfo
|
||||
$(INSTALL_BIN) ./files/loongarch64/sbin/tempinfo $(1)/sbin/tempinfo
|
||||
$(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d
|
||||
$(CP) ./files/luci-mod-status-autocore.json $(1)/usr/share/rpcd/acl.d/
|
||||
endef
|
||||
|
||||
define Package/autocore-x86/install
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/x86/autocore $(1)/etc/init.d/autocore
|
||||
@@ -71,4 +95,5 @@ define Package/autocore-x86/install
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,autocore-arm))
|
||||
$(eval $(call BuildPackage,autocore-loongarch64))
|
||||
$(eval $(call BuildPackage,autocore-x86))
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2025 lean <coolsnowwolf@gmail.com>
|
||||
|
||||
START=99
|
||||
|
||||
start()
|
||||
{
|
||||
a=$(cat /proc/cpuinfo | grep 'Model Name' | cut -f2 -d: | head -n 1)
|
||||
b=$(echo -n ' : ')
|
||||
c=$(cat /proc/cpuinfo | grep 'core' | sort -u | wc -l)
|
||||
d=$(echo -n 'C')
|
||||
e=$(cat /proc/cpuinfo | grep 'global_id' | sort -u | wc -l)
|
||||
f=$(echo -n 'T ')
|
||||
g=$(cat /proc/cpuinfo | grep 'CPU Family' | cut -f2 -d: | head -n 1)
|
||||
|
||||
h=${g}' - '${a}${b}${c}${d}${e}${f}
|
||||
|
||||
mkdir -p /tmp/sysinfo
|
||||
echo $h > /tmp/sysinfo/model
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
MHz=`grep 'MHz' /proc/cpuinfo | cut -c13- |sed -n '1p'`
|
||||
|
||||
echo "$MHz MHz"
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/lua
|
||||
-- Copyright (C) 2022 ImmortalWrt.org
|
||||
|
||||
local util = require "luci.util"
|
||||
local jsonc = require "luci.jsonc"
|
||||
|
||||
local eth_info = {}
|
||||
local ifname, stat
|
||||
|
||||
for ifname, stat in pairs(util.ubus("network.device", "status")) do
|
||||
while true do
|
||||
if (ifname:match("^(br-.+)$")) == ifname then
|
||||
break
|
||||
else
|
||||
local status, speed, duplex
|
||||
|
||||
if(stat.speed ~= nil) then
|
||||
status = stat.carrier and 1 or 0
|
||||
|
||||
if stat.speed:sub(1, 1) == "-" then
|
||||
speed = " - "
|
||||
else
|
||||
speed = stat.speed:sub(1, -2) .. "Mb/s"
|
||||
end
|
||||
|
||||
if stat.carrier and stat.speed:sub(-1) == "F" then
|
||||
duplex = 1
|
||||
else
|
||||
duplex = 0
|
||||
end
|
||||
|
||||
eth_info[#eth_info+1] = { name = ifname, status = status,
|
||||
speed = speed, duplex = duplex }
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(eth_info,
|
||||
function(a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
|
||||
print(jsonc.stringify(eth_info))
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
TEMP=`awk '{printf("%.1f°C", $0 / 1000)}' "/sys/class/thermal/thermal_zone0/temp" 2>"/dev/null"`
|
||||
|
||||
echo "$TEMP "
|
||||
@@ -8,7 +8,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=fstools
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/fstools.git
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/libfstools/common.h
|
||||
+++ b/libfstools/common.h
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "libfstools.h"
|
||||
#include "volume.h"
|
||||
|
||||
-#define F2FS_MINSIZE (100ULL * 1024ULL * 1024ULL)
|
||||
+#define F2FS_MINSIZE (1024ULL * 1024ULL * 1024ULL)
|
||||
|
||||
int read_uint_from_file(char *dirname, char *filename, unsigned int *i);
|
||||
char *read_string_from_file(const char *dirname, const char *filename, char *buf, size_t bufsz);
|
||||
@@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
|
||||
ARCH:=loongarch64
|
||||
BOARD:=loongarch64
|
||||
BOARDNAME:=Loongson LoongArch
|
||||
FEATURES:=audio display ext4 pcie boot-part rootfs-part rtc usb targz
|
||||
FEATURES:=squashfs audio display ext4 pcie boot-part rootfs-part rtc usb targz
|
||||
SUBTARGETS:=generic
|
||||
|
||||
KERNEL_PATCHVER:=6.12
|
||||
@@ -18,6 +18,7 @@ KERNELNAME:=vmlinuz.efi dtbs
|
||||
include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
DEFAULT_PACKAGES += \
|
||||
partx-utils blkid e2fsprogs grub2-efi-loongarch64 kmod-yt6801
|
||||
partx-utils blkid e2fsprogs grub2-efi-loongarch64 kmod-yt6801 \
|
||||
kmod-fs-ext4 kmod-fs-f2fs losetup mkf2fs f2fsck e2fsprogs autocore-loongarch64
|
||||
|
||||
$(eval $(call BuildTarget))
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
N "github.com/metacubex/mihomo/common/net"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
)
|
||||
|
||||
type Fallback struct {
|
||||
@@ -150,7 +150,7 @@ func (f *Fallback) ForceSet(name string) {
|
||||
f.selected = name
|
||||
}
|
||||
|
||||
func NewFallback(option *GroupCommonOption, providers []provider.ProxyProvider) *Fallback {
|
||||
func NewFallback(option *GroupCommonOption, providers []P.ProxyProvider) *Fallback {
|
||||
return &Fallback{
|
||||
GroupBase: NewGroupBase(GroupBaseOption{
|
||||
Name: option.Name,
|
||||
|
||||
@@ -12,8 +12,7 @@ import (
|
||||
"github.com/metacubex/mihomo/common/atomic"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
"github.com/metacubex/mihomo/tunnel"
|
||||
|
||||
@@ -26,7 +25,7 @@ type GroupBase struct {
|
||||
filterRegs []*regexp2.Regexp
|
||||
excludeFilterRegs []*regexp2.Regexp
|
||||
excludeTypeArray []string
|
||||
providers []provider.ProxyProvider
|
||||
providers []P.ProxyProvider
|
||||
failedTestMux sync.Mutex
|
||||
failedTimes int
|
||||
failedTime time.Time
|
||||
@@ -48,7 +47,7 @@ type GroupBaseOption struct {
|
||||
ExcludeType string
|
||||
TestTimeout int
|
||||
MaxFailedTimes int
|
||||
Providers []provider.ProxyProvider
|
||||
Providers []P.ProxyProvider
|
||||
}
|
||||
|
||||
func NewGroupBase(opt GroupBaseOption) *GroupBase {
|
||||
@@ -125,7 +124,7 @@ func (gb *GroupBase) GetProxies(touch bool) []C.Proxy {
|
||||
}
|
||||
} else {
|
||||
for _, pd := range gb.providers {
|
||||
if pd.VehicleType() == types.Compatible { // compatible provider unneeded filter
|
||||
if pd.VehicleType() == P.Compatible { // compatible provider unneeded filter
|
||||
proxies = append(proxies, pd.Proxies()...)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
N "github.com/metacubex/mihomo/common/net"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
|
||||
"golang.org/x/net/publicsuffix"
|
||||
)
|
||||
@@ -239,7 +239,7 @@ func (lb *LoadBalance) MarshalJSON() ([]byte, error) {
|
||||
})
|
||||
}
|
||||
|
||||
func NewLoadBalance(option *GroupCommonOption, providers []provider.ProxyProvider, strategy string) (lb *LoadBalance, err error) {
|
||||
func NewLoadBalance(option *GroupCommonOption, providers []P.ProxyProvider, strategy string) (lb *LoadBalance, err error) {
|
||||
var strategyFn strategyFn
|
||||
switch strategy {
|
||||
case "consistent-hashing":
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/metacubex/mihomo/common/structure"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
)
|
||||
|
||||
@@ -48,7 +48,7 @@ type GroupCommonOption struct {
|
||||
RoutingMark int `group:"routing-mark,omitempty"`
|
||||
}
|
||||
|
||||
func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, providersMap map[string]types.ProxyProvider, AllProxies []string, AllProviders []string) (C.ProxyAdapter, error) {
|
||||
func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, providersMap map[string]P.ProxyProvider, AllProxies []string, AllProviders []string) (C.ProxyAdapter, error) {
|
||||
decoder := structure.NewDecoder(structure.Option{TagName: "group", WeaklyTypedInput: true})
|
||||
|
||||
groupOption := &GroupCommonOption{
|
||||
@@ -71,7 +71,7 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide
|
||||
|
||||
groupName := groupOption.Name
|
||||
|
||||
providers := []types.ProxyProvider{}
|
||||
providers := []P.ProxyProvider{}
|
||||
|
||||
if groupOption.IncludeAll {
|
||||
groupOption.IncludeAllProviders = true
|
||||
@@ -169,7 +169,7 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide
|
||||
return nil, fmt.Errorf("%s: %w", groupName, err)
|
||||
}
|
||||
|
||||
providers = append([]types.ProxyProvider{pd}, providers...)
|
||||
providers = append([]P.ProxyProvider{pd}, providers...)
|
||||
providersMap[groupName] = pd
|
||||
}
|
||||
|
||||
@@ -206,15 +206,15 @@ func getProxies(mapping map[string]C.Proxy, list []string) ([]C.Proxy, error) {
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
func getProviders(mapping map[string]types.ProxyProvider, list []string) ([]types.ProxyProvider, error) {
|
||||
var ps []types.ProxyProvider
|
||||
func getProviders(mapping map[string]P.ProxyProvider, list []string) ([]P.ProxyProvider, error) {
|
||||
var ps []P.ProxyProvider
|
||||
for _, name := range list {
|
||||
p, ok := mapping[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("'%s' not found", name)
|
||||
}
|
||||
|
||||
if p.VehicleType() == types.Compatible {
|
||||
if p.VehicleType() == P.Compatible {
|
||||
return nil, fmt.Errorf("proxy group %s can't contains in `use`", name)
|
||||
}
|
||||
ps = append(ps, p)
|
||||
@@ -222,7 +222,7 @@ func getProviders(mapping map[string]types.ProxyProvider, list []string) ([]type
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
func addTestUrlToProviders(providers []types.ProxyProvider, url string, expectedStatus utils.IntRanges[uint16], filter string, interval uint) {
|
||||
func addTestUrlToProviders(providers []P.ProxyProvider, url string, expectedStatus utils.IntRanges[uint16], filter string, interval uint) {
|
||||
if len(providers) == 0 || len(url) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,22 +4,22 @@ package outboundgroup
|
||||
|
||||
import (
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
)
|
||||
|
||||
type ProxyGroup interface {
|
||||
C.ProxyAdapter
|
||||
|
||||
Providers() []provider.ProxyProvider
|
||||
Providers() []P.ProxyProvider
|
||||
Proxies() []C.Proxy
|
||||
Now() string
|
||||
}
|
||||
|
||||
func (f *Fallback) Providers() []provider.ProxyProvider {
|
||||
func (f *Fallback) Providers() []P.ProxyProvider {
|
||||
return f.providers
|
||||
}
|
||||
|
||||
func (lb *LoadBalance) Providers() []provider.ProxyProvider {
|
||||
func (lb *LoadBalance) Providers() []P.ProxyProvider {
|
||||
return lb.providers
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func (lb *LoadBalance) Now() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *Relay) Providers() []provider.ProxyProvider {
|
||||
func (r *Relay) Providers() []P.ProxyProvider {
|
||||
return r.providers
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func (r *Relay) Now() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *Selector) Providers() []provider.ProxyProvider {
|
||||
func (s *Selector) Providers() []P.ProxyProvider {
|
||||
return s.providers
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func (s *Selector) Proxies() []C.Proxy {
|
||||
return s.GetProxies(false)
|
||||
}
|
||||
|
||||
func (u *URLTest) Providers() []provider.ProxyProvider {
|
||||
func (u *URLTest) Providers() []P.ProxyProvider {
|
||||
return u.providers
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/dialer"
|
||||
"github.com/metacubex/mihomo/component/proxydialer"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
)
|
||||
|
||||
@@ -149,7 +149,7 @@ func (r *Relay) Addr() string {
|
||||
return proxies[len(proxies)-1].Addr()
|
||||
}
|
||||
|
||||
func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *Relay {
|
||||
func NewRelay(option *GroupCommonOption, providers []P.ProxyProvider) *Relay {
|
||||
log.Warnln("The group [%s] with relay type is deprecated, please using dialer-proxy instead", option.Name)
|
||||
return &Relay{
|
||||
GroupBase: NewGroupBase(GroupBaseOption{
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"errors"
|
||||
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
)
|
||||
|
||||
type Selector struct {
|
||||
@@ -108,7 +108,7 @@ func (s *Selector) selectedProxy(touch bool) C.Proxy {
|
||||
return proxies[0]
|
||||
}
|
||||
|
||||
func NewSelector(option *GroupCommonOption, providers []provider.ProxyProvider) *Selector {
|
||||
func NewSelector(option *GroupCommonOption, providers []P.ProxyProvider) *Selector {
|
||||
return &Selector{
|
||||
GroupBase: NewGroupBase(GroupBaseOption{
|
||||
Name: option.Name,
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/metacubex/mihomo/common/singledo"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
)
|
||||
|
||||
type urlTestOption func(*URLTest)
|
||||
@@ -202,7 +202,7 @@ func parseURLTestOption(config map[string]any) []urlTestOption {
|
||||
return opts
|
||||
}
|
||||
|
||||
func NewURLTest(option *GroupCommonOption, providers []provider.ProxyProvider, options ...urlTestOption) *URLTest {
|
||||
func NewURLTest(option *GroupCommonOption, providers []P.ProxyProvider, options ...urlTestOption) *URLTest {
|
||||
urlTest := &URLTest{
|
||||
GroupBase: NewGroupBase(GroupBaseOption{
|
||||
Name: option.Name,
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
|
||||
"github.com/dlclark/regexp2"
|
||||
)
|
||||
@@ -73,7 +73,7 @@ type proxyProviderSchema struct {
|
||||
Header map[string][]string `provider:"header,omitempty"`
|
||||
}
|
||||
|
||||
func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvider, error) {
|
||||
func ParseProxyProvider(name string, mapping map[string]any) (P.ProxyProvider, error) {
|
||||
decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true})
|
||||
|
||||
schema := &proxyProviderSchema{
|
||||
@@ -104,7 +104,7 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var vehicle types.Vehicle
|
||||
var vehicle P.Vehicle
|
||||
switch schema.Type {
|
||||
case "file":
|
||||
path := C.Path.Resolve(schema.Path)
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/profile/cachefile"
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/tunnel/statistic"
|
||||
|
||||
"github.com/dlclark/regexp2"
|
||||
@@ -68,8 +68,8 @@ func (bp *baseProvider) HealthCheck() {
|
||||
bp.healthCheck.check()
|
||||
}
|
||||
|
||||
func (bp *baseProvider) Type() types.ProviderType {
|
||||
return types.Proxy
|
||||
func (bp *baseProvider) Type() P.ProviderType {
|
||||
return P.Proxy
|
||||
}
|
||||
|
||||
func (bp *baseProvider) Proxies() []C.Proxy {
|
||||
@@ -171,7 +171,7 @@ func (pp *proxySetProvider) Close() error {
|
||||
return pp.Fetcher.Close()
|
||||
}
|
||||
|
||||
func NewProxySetProvider(name string, interval time.Duration, payload []map[string]any, parser resource.Parser[[]C.Proxy], vehicle types.Vehicle, hc *HealthCheck) (*ProxySetProvider, error) {
|
||||
func NewProxySetProvider(name string, interval time.Duration, payload []map[string]any, parser resource.Parser[[]C.Proxy], vehicle P.Vehicle, hc *HealthCheck) (*ProxySetProvider, error) {
|
||||
pd := &proxySetProvider{
|
||||
baseProvider: baseProvider{
|
||||
name: name,
|
||||
@@ -238,8 +238,8 @@ func (ip *inlineProvider) MarshalJSON() ([]byte, error) {
|
||||
})
|
||||
}
|
||||
|
||||
func (ip *inlineProvider) VehicleType() types.VehicleType {
|
||||
return types.Inline
|
||||
func (ip *inlineProvider) VehicleType() P.VehicleType {
|
||||
return P.Inline
|
||||
}
|
||||
|
||||
func (ip *inlineProvider) Update() error {
|
||||
@@ -303,8 +303,8 @@ func (cp *compatibleProvider) Update() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cp *compatibleProvider) VehicleType() types.VehicleType {
|
||||
return types.Compatible
|
||||
func (cp *compatibleProvider) VehicleType() P.VehicleType {
|
||||
return P.Compatible
|
||||
}
|
||||
|
||||
func NewCompatibleProvider(name string, proxies []C.Proxy, hc *HealthCheck) (*CompatibleProvider, error) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
"github.com/metacubex/mihomo/component/slowdown"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
|
||||
"github.com/metacubex/fswatch"
|
||||
@@ -22,7 +22,7 @@ type Fetcher[V any] struct {
|
||||
ctxCancel context.CancelFunc
|
||||
resourceType string
|
||||
name string
|
||||
vehicle types.Vehicle
|
||||
vehicle P.Vehicle
|
||||
updatedAt time.Time
|
||||
hash utils.HashType
|
||||
parser Parser[V]
|
||||
@@ -37,11 +37,11 @@ func (f *Fetcher[V]) Name() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
func (f *Fetcher[V]) Vehicle() types.Vehicle {
|
||||
func (f *Fetcher[V]) Vehicle() P.Vehicle {
|
||||
return f.vehicle
|
||||
}
|
||||
|
||||
func (f *Fetcher[V]) VehicleType() types.VehicleType {
|
||||
func (f *Fetcher[V]) VehicleType() P.VehicleType {
|
||||
return f.vehicle.Type()
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ func (f *Fetcher[V]) Update() (V, bool, error) {
|
||||
f.backoff.AddAttempt() // add a failed attempt to backoff
|
||||
return lo.Empty[V](), false, err
|
||||
}
|
||||
return f.loadBuf(buf, hash, f.vehicle.Type() != types.File)
|
||||
return f.loadBuf(buf, hash, f.vehicle.Type() != P.File)
|
||||
}
|
||||
|
||||
func (f *Fetcher[V]) SideUpdate(buf []byte) (V, bool, error) {
|
||||
@@ -180,7 +180,7 @@ func (f *Fetcher[V]) pullLoop(forceUpdate bool) {
|
||||
|
||||
func (f *Fetcher[V]) startPullLoop(forceUpdate bool) (err error) {
|
||||
// pull contents automatically
|
||||
if f.vehicle.Type() == types.File {
|
||||
if f.vehicle.Type() == P.File {
|
||||
f.watcher, err = fswatch.NewWatcher(fswatch.Options{
|
||||
Path: []string{f.vehicle.Path()},
|
||||
Callback: f.updateCallback,
|
||||
@@ -218,7 +218,7 @@ func (f *Fetcher[V]) updateWithLog() {
|
||||
return
|
||||
}
|
||||
|
||||
func NewFetcher[V any](name string, interval time.Duration, vehicle types.Vehicle, parser Parser[V], onUpdate func(V)) *Fetcher[V] {
|
||||
func NewFetcher[V any](name string, interval time.Duration, vehicle P.Vehicle, parser Parser[V], onUpdate func(V)) *Fetcher[V] {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
minBackoff := 10 * time.Second
|
||||
if interval < minBackoff {
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
mihomoHttp "github.com/metacubex/mihomo/component/http"
|
||||
"github.com/metacubex/mihomo/component/profile/cachefile"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -50,8 +50,8 @@ type FileVehicle struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func (f *FileVehicle) Type() types.VehicleType {
|
||||
return types.File
|
||||
func (f *FileVehicle) Type() P.VehicleType {
|
||||
return P.File
|
||||
}
|
||||
|
||||
func (f *FileVehicle) Path() string {
|
||||
@@ -91,15 +91,15 @@ type HTTPVehicle struct {
|
||||
timeout time.Duration
|
||||
sizeLimit int64
|
||||
inRead func(response *http.Response)
|
||||
provider types.ProxyProvider
|
||||
provider P.ProxyProvider
|
||||
}
|
||||
|
||||
func (h *HTTPVehicle) Url() string {
|
||||
return h.url
|
||||
}
|
||||
|
||||
func (h *HTTPVehicle) Type() types.VehicleType {
|
||||
return types.HTTP
|
||||
func (h *HTTPVehicle) Type() P.VehicleType {
|
||||
return P.HTTP
|
||||
}
|
||||
|
||||
func (h *HTTPVehicle) Path() string {
|
||||
|
||||
+97
-96
@@ -20,15 +20,15 @@ import (
|
||||
"github.com/metacubex/mihomo/component/cidr"
|
||||
"github.com/metacubex/mihomo/component/fakeip"
|
||||
"github.com/metacubex/mihomo/component/geodata"
|
||||
P "github.com/metacubex/mihomo/component/process"
|
||||
"github.com/metacubex/mihomo/component/process"
|
||||
"github.com/metacubex/mihomo/component/resolver"
|
||||
"github.com/metacubex/mihomo/component/sniffer"
|
||||
"github.com/metacubex/mihomo/component/trie"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
providerTypes "github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
snifferTypes "github.com/metacubex/mihomo/constant/sniffer"
|
||||
"github.com/metacubex/mihomo/dns"
|
||||
L "github.com/metacubex/mihomo/listener"
|
||||
"github.com/metacubex/mihomo/listener"
|
||||
LC "github.com/metacubex/mihomo/listener/config"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
R "github.com/metacubex/mihomo/rules"
|
||||
@@ -44,27 +44,27 @@ import (
|
||||
// General config
|
||||
type General struct {
|
||||
Inbound
|
||||
Mode T.TunnelMode `json:"mode"`
|
||||
UnifiedDelay bool `json:"unified-delay"`
|
||||
LogLevel log.LogLevel `json:"log-level"`
|
||||
IPv6 bool `json:"ipv6"`
|
||||
Interface string `json:"interface-name"`
|
||||
RoutingMark int `json:"routing-mark"`
|
||||
GeoXUrl GeoXUrl `json:"geox-url"`
|
||||
GeoAutoUpdate bool `json:"geo-auto-update"`
|
||||
GeoUpdateInterval int `json:"geo-update-interval"`
|
||||
GeodataMode bool `json:"geodata-mode"`
|
||||
GeodataLoader string `json:"geodata-loader"`
|
||||
GeositeMatcher string `json:"geosite-matcher"`
|
||||
TCPConcurrent bool `json:"tcp-concurrent"`
|
||||
FindProcessMode P.FindProcessMode `json:"find-process-mode"`
|
||||
Sniffing bool `json:"sniffing"`
|
||||
GlobalClientFingerprint string `json:"global-client-fingerprint"`
|
||||
GlobalUA string `json:"global-ua"`
|
||||
ETagSupport bool `json:"etag-support"`
|
||||
KeepAliveIdle int `json:"keep-alive-idle"`
|
||||
KeepAliveInterval int `json:"keep-alive-interval"`
|
||||
DisableKeepAlive bool `json:"disable-keep-alive"`
|
||||
Mode T.TunnelMode `json:"mode"`
|
||||
UnifiedDelay bool `json:"unified-delay"`
|
||||
LogLevel log.LogLevel `json:"log-level"`
|
||||
IPv6 bool `json:"ipv6"`
|
||||
Interface string `json:"interface-name"`
|
||||
RoutingMark int `json:"routing-mark"`
|
||||
GeoXUrl GeoXUrl `json:"geox-url"`
|
||||
GeoAutoUpdate bool `json:"geo-auto-update"`
|
||||
GeoUpdateInterval int `json:"geo-update-interval"`
|
||||
GeodataMode bool `json:"geodata-mode"`
|
||||
GeodataLoader string `json:"geodata-loader"`
|
||||
GeositeMatcher string `json:"geosite-matcher"`
|
||||
TCPConcurrent bool `json:"tcp-concurrent"`
|
||||
FindProcessMode process.FindProcessMode `json:"find-process-mode"`
|
||||
Sniffing bool `json:"sniffing"`
|
||||
GlobalClientFingerprint string `json:"global-client-fingerprint"`
|
||||
GlobalUA string `json:"global-ua"`
|
||||
ETagSupport bool `json:"etag-support"`
|
||||
KeepAliveIdle int `json:"keep-alive-idle"`
|
||||
KeepAliveInterval int `json:"keep-alive-interval"`
|
||||
DisableKeepAlive bool `json:"disable-keep-alive"`
|
||||
}
|
||||
|
||||
// Inbound config
|
||||
@@ -199,8 +199,8 @@ type Config struct {
|
||||
Users []auth.AuthUser
|
||||
Proxies map[string]C.Proxy
|
||||
Listeners map[string]C.InboundListener
|
||||
Providers map[string]providerTypes.ProxyProvider
|
||||
RuleProviders map[string]providerTypes.RuleProvider
|
||||
Providers map[string]P.ProxyProvider
|
||||
RuleProviders map[string]P.RuleProvider
|
||||
Tunnels []LC.Tunnel
|
||||
Sniffer *sniffer.Config
|
||||
TLS *TLS
|
||||
@@ -382,51 +382,51 @@ type RawTLS struct {
|
||||
}
|
||||
|
||||
type RawConfig struct {
|
||||
Port int `yaml:"port" json:"port"`
|
||||
SocksPort int `yaml:"socks-port" json:"socks-port"`
|
||||
RedirPort int `yaml:"redir-port" json:"redir-port"`
|
||||
TProxyPort int `yaml:"tproxy-port" json:"tproxy-port"`
|
||||
MixedPort int `yaml:"mixed-port" json:"mixed-port"`
|
||||
ShadowSocksConfig string `yaml:"ss-config" json:"ss-config"`
|
||||
VmessConfig string `yaml:"vmess-config" json:"vmess-config"`
|
||||
InboundTfo bool `yaml:"inbound-tfo" json:"inbound-tfo"`
|
||||
InboundMPTCP bool `yaml:"inbound-mptcp" json:"inbound-mptcp"`
|
||||
Authentication []string `yaml:"authentication" json:"authentication"`
|
||||
SkipAuthPrefixes []netip.Prefix `yaml:"skip-auth-prefixes" json:"skip-auth-prefixes"`
|
||||
LanAllowedIPs []netip.Prefix `yaml:"lan-allowed-ips" json:"lan-allowed-ips"`
|
||||
LanDisAllowedIPs []netip.Prefix `yaml:"lan-disallowed-ips" json:"lan-disallowed-ips"`
|
||||
AllowLan bool `yaml:"allow-lan" json:"allow-lan"`
|
||||
BindAddress string `yaml:"bind-address" json:"bind-address"`
|
||||
Mode T.TunnelMode `yaml:"mode" json:"mode"`
|
||||
UnifiedDelay bool `yaml:"unified-delay" json:"unified-delay"`
|
||||
LogLevel log.LogLevel `yaml:"log-level" json:"log-level"`
|
||||
IPv6 bool `yaml:"ipv6" json:"ipv6"`
|
||||
ExternalController string `yaml:"external-controller" json:"external-controller"`
|
||||
ExternalControllerPipe string `yaml:"external-controller-pipe" json:"external-controller-pipe"`
|
||||
ExternalControllerUnix string `yaml:"external-controller-unix" json:"external-controller-unix"`
|
||||
ExternalControllerTLS string `yaml:"external-controller-tls" json:"external-controller-tls"`
|
||||
ExternalControllerCors RawCors `yaml:"external-controller-cors" json:"external-controller-cors"`
|
||||
ExternalUI string `yaml:"external-ui" json:"external-ui"`
|
||||
ExternalUIURL string `yaml:"external-ui-url" json:"external-ui-url"`
|
||||
ExternalUIName string `yaml:"external-ui-name" json:"external-ui-name"`
|
||||
ExternalDohServer string `yaml:"external-doh-server" json:"external-doh-server"`
|
||||
Secret string `yaml:"secret" json:"secret"`
|
||||
Interface string `yaml:"interface-name" json:"interface-name"`
|
||||
RoutingMark int `yaml:"routing-mark" json:"routing-mark"`
|
||||
Tunnels []LC.Tunnel `yaml:"tunnels" json:"tunnels"`
|
||||
GeoAutoUpdate bool `yaml:"geo-auto-update" json:"geo-auto-update"`
|
||||
GeoUpdateInterval int `yaml:"geo-update-interval" json:"geo-update-interval"`
|
||||
GeodataMode bool `yaml:"geodata-mode" json:"geodata-mode"`
|
||||
GeodataLoader string `yaml:"geodata-loader" json:"geodata-loader"`
|
||||
GeositeMatcher string `yaml:"geosite-matcher" json:"geosite-matcher"`
|
||||
TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"`
|
||||
FindProcessMode P.FindProcessMode `yaml:"find-process-mode" json:"find-process-mode"`
|
||||
GlobalClientFingerprint string `yaml:"global-client-fingerprint" json:"global-client-fingerprint"`
|
||||
GlobalUA string `yaml:"global-ua" json:"global-ua"`
|
||||
ETagSupport bool `yaml:"etag-support" json:"etag-support"`
|
||||
KeepAliveIdle int `yaml:"keep-alive-idle" json:"keep-alive-idle"`
|
||||
KeepAliveInterval int `yaml:"keep-alive-interval" json:"keep-alive-interval"`
|
||||
DisableKeepAlive bool `yaml:"disable-keep-alive" json:"disable-keep-alive"`
|
||||
Port int `yaml:"port" json:"port"`
|
||||
SocksPort int `yaml:"socks-port" json:"socks-port"`
|
||||
RedirPort int `yaml:"redir-port" json:"redir-port"`
|
||||
TProxyPort int `yaml:"tproxy-port" json:"tproxy-port"`
|
||||
MixedPort int `yaml:"mixed-port" json:"mixed-port"`
|
||||
ShadowSocksConfig string `yaml:"ss-config" json:"ss-config"`
|
||||
VmessConfig string `yaml:"vmess-config" json:"vmess-config"`
|
||||
InboundTfo bool `yaml:"inbound-tfo" json:"inbound-tfo"`
|
||||
InboundMPTCP bool `yaml:"inbound-mptcp" json:"inbound-mptcp"`
|
||||
Authentication []string `yaml:"authentication" json:"authentication"`
|
||||
SkipAuthPrefixes []netip.Prefix `yaml:"skip-auth-prefixes" json:"skip-auth-prefixes"`
|
||||
LanAllowedIPs []netip.Prefix `yaml:"lan-allowed-ips" json:"lan-allowed-ips"`
|
||||
LanDisAllowedIPs []netip.Prefix `yaml:"lan-disallowed-ips" json:"lan-disallowed-ips"`
|
||||
AllowLan bool `yaml:"allow-lan" json:"allow-lan"`
|
||||
BindAddress string `yaml:"bind-address" json:"bind-address"`
|
||||
Mode T.TunnelMode `yaml:"mode" json:"mode"`
|
||||
UnifiedDelay bool `yaml:"unified-delay" json:"unified-delay"`
|
||||
LogLevel log.LogLevel `yaml:"log-level" json:"log-level"`
|
||||
IPv6 bool `yaml:"ipv6" json:"ipv6"`
|
||||
ExternalController string `yaml:"external-controller" json:"external-controller"`
|
||||
ExternalControllerPipe string `yaml:"external-controller-pipe" json:"external-controller-pipe"`
|
||||
ExternalControllerUnix string `yaml:"external-controller-unix" json:"external-controller-unix"`
|
||||
ExternalControllerTLS string `yaml:"external-controller-tls" json:"external-controller-tls"`
|
||||
ExternalControllerCors RawCors `yaml:"external-controller-cors" json:"external-controller-cors"`
|
||||
ExternalUI string `yaml:"external-ui" json:"external-ui"`
|
||||
ExternalUIURL string `yaml:"external-ui-url" json:"external-ui-url"`
|
||||
ExternalUIName string `yaml:"external-ui-name" json:"external-ui-name"`
|
||||
ExternalDohServer string `yaml:"external-doh-server" json:"external-doh-server"`
|
||||
Secret string `yaml:"secret" json:"secret"`
|
||||
Interface string `yaml:"interface-name" json:"interface-name"`
|
||||
RoutingMark int `yaml:"routing-mark" json:"routing-mark"`
|
||||
Tunnels []LC.Tunnel `yaml:"tunnels" json:"tunnels"`
|
||||
GeoAutoUpdate bool `yaml:"geo-auto-update" json:"geo-auto-update"`
|
||||
GeoUpdateInterval int `yaml:"geo-update-interval" json:"geo-update-interval"`
|
||||
GeodataMode bool `yaml:"geodata-mode" json:"geodata-mode"`
|
||||
GeodataLoader string `yaml:"geodata-loader" json:"geodata-loader"`
|
||||
GeositeMatcher string `yaml:"geosite-matcher" json:"geosite-matcher"`
|
||||
TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"`
|
||||
FindProcessMode process.FindProcessMode `yaml:"find-process-mode" json:"find-process-mode"`
|
||||
GlobalClientFingerprint string `yaml:"global-client-fingerprint" json:"global-client-fingerprint"`
|
||||
GlobalUA string `yaml:"global-ua" json:"global-ua"`
|
||||
ETagSupport bool `yaml:"etag-support" json:"etag-support"`
|
||||
KeepAliveIdle int `yaml:"keep-alive-idle" json:"keep-alive-idle"`
|
||||
KeepAliveInterval int `yaml:"keep-alive-interval" json:"keep-alive-interval"`
|
||||
DisableKeepAlive bool `yaml:"disable-keep-alive" json:"disable-keep-alive"`
|
||||
|
||||
ProxyProvider map[string]map[string]any `yaml:"proxy-providers" json:"proxy-providers"`
|
||||
RuleProvider map[string]map[string]any `yaml:"rule-providers" json:"rule-providers"`
|
||||
@@ -479,7 +479,7 @@ func DefaultRawConfig() *RawConfig {
|
||||
Proxy: []map[string]any{},
|
||||
ProxyGroup: []map[string]any{},
|
||||
TCPConcurrent: false,
|
||||
FindProcessMode: P.FindProcessStrict,
|
||||
FindProcessMode: process.FindProcessStrict,
|
||||
GlobalUA: "clash.meta/" + C.Version,
|
||||
ETagSupport: true,
|
||||
DNS: RawDNS{
|
||||
@@ -653,11 +653,11 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
|
||||
config.Proxies = proxies
|
||||
config.Providers = providers
|
||||
|
||||
listener, err := parseListeners(rawCfg)
|
||||
listeners, err := parseListeners(rawCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Listeners = listener
|
||||
config.Listeners = listeners
|
||||
|
||||
log.Infoln("Geodata Loader mode: %s", geodata.LoaderName())
|
||||
log.Infoln("Geosite Matcher implementation: %s", geodata.SiteMatcherName())
|
||||
@@ -845,9 +845,9 @@ func parseTLS(cfg *RawConfig) (*TLS, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[string]providerTypes.ProxyProvider, err error) {
|
||||
func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[string]P.ProxyProvider, err error) {
|
||||
proxies = make(map[string]C.Proxy)
|
||||
providersMap = make(map[string]providerTypes.ProxyProvider)
|
||||
providersMap = make(map[string]P.ProxyProvider)
|
||||
proxiesConfig := cfg.Proxy
|
||||
groupsConfig := cfg.ProxyGroup
|
||||
providersConfig := cfg.ProxyProvider
|
||||
@@ -947,7 +947,7 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[
|
||||
&outboundgroup.GroupCommonOption{
|
||||
Name: "GLOBAL",
|
||||
},
|
||||
[]providerTypes.ProxyProvider{pd},
|
||||
[]P.ProxyProvider{pd},
|
||||
)
|
||||
proxies["GLOBAL"] = adapter.NewProxy(global)
|
||||
}
|
||||
@@ -957,24 +957,25 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[
|
||||
func parseListeners(cfg *RawConfig) (listeners map[string]C.InboundListener, err error) {
|
||||
listeners = make(map[string]C.InboundListener)
|
||||
for index, mapping := range cfg.Listeners {
|
||||
listener, err := L.ParseListener(mapping)
|
||||
inboundListener, err := listener.ParseListener(mapping)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("proxy %d: %w", index, err)
|
||||
}
|
||||
|
||||
if _, exist := mapping[listener.Name()]; exist {
|
||||
return nil, fmt.Errorf("listener %s is the duplicate name", listener.Name())
|
||||
name := inboundListener.Name()
|
||||
if _, exist := mapping[name]; exist {
|
||||
return nil, fmt.Errorf("listener %s is the duplicate name", name)
|
||||
}
|
||||
|
||||
listeners[listener.Name()] = listener
|
||||
listeners[name] = inboundListener
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseRuleProviders(cfg *RawConfig) (ruleProviders map[string]providerTypes.RuleProvider, err error) {
|
||||
func parseRuleProviders(cfg *RawConfig) (ruleProviders map[string]P.RuleProvider, err error) {
|
||||
RP.SetTunnel(T.Tunnel)
|
||||
ruleProviders = map[string]providerTypes.RuleProvider{}
|
||||
ruleProviders = map[string]P.RuleProvider{}
|
||||
// parse rule provider
|
||||
for name, mapping := range cfg.RuleProvider {
|
||||
rp, err := RP.ParseRuleProvider(name, mapping, R.ParseRule)
|
||||
@@ -987,7 +988,7 @@ func parseRuleProviders(cfg *RawConfig) (ruleProviders map[string]providerTypes.
|
||||
return
|
||||
}
|
||||
|
||||
func parseSubRules(cfg *RawConfig, proxies map[string]C.Proxy, ruleProviders map[string]providerTypes.RuleProvider) (subRules map[string][]C.Rule, err error) {
|
||||
func parseSubRules(cfg *RawConfig, proxies map[string]C.Proxy, ruleProviders map[string]P.RuleProvider) (subRules map[string][]C.Rule, err error) {
|
||||
subRules = map[string][]C.Rule{}
|
||||
for name := range cfg.SubRules {
|
||||
subRules[name] = make([]C.Rule, 0)
|
||||
@@ -1050,7 +1051,7 @@ func verifySubRuleCircularReferences(n string, subRules map[string][]C.Rule, arr
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseRules(rulesConfig []string, proxies map[string]C.Proxy, ruleProviders map[string]providerTypes.RuleProvider, subRules map[string][]C.Rule, format string) ([]C.Rule, error) {
|
||||
func parseRules(rulesConfig []string, proxies map[string]C.Proxy, ruleProviders map[string]P.RuleProvider, subRules map[string][]C.Rule, format string) ([]C.Rule, error) {
|
||||
var rules []C.Rule
|
||||
|
||||
// parse rules
|
||||
@@ -1273,7 +1274,7 @@ func parsePureDNSServer(server string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], ruleProviders map[string]providerTypes.RuleProvider, respectRules bool, preferH3 bool) ([]dns.Policy, error) {
|
||||
func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], ruleProviders map[string]P.RuleProvider, respectRules bool, preferH3 bool) ([]dns.Policy, error) {
|
||||
var policy []dns.Policy
|
||||
|
||||
for pair := nsPolicy.Oldest(); pair != nil; pair = pair.Next() {
|
||||
@@ -1348,7 +1349,7 @@ func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], rulePro
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
func parseDNS(rawCfg *RawConfig, ruleProviders map[string]providerTypes.RuleProvider) (*DNS, error) {
|
||||
func parseDNS(rawCfg *RawConfig, ruleProviders map[string]P.RuleProvider) (*DNS, error) {
|
||||
cfg := rawCfg.DNS
|
||||
if cfg.Enable && len(cfg.NameServer) == 0 {
|
||||
return nil, fmt.Errorf("if DNS configuration is turned on, NameServer cannot be empty")
|
||||
@@ -1632,7 +1633,7 @@ func parseTuicServer(rawTuic RawTuicServer, general *General) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]providerTypes.RuleProvider) (*sniffer.Config, error) {
|
||||
func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]P.RuleProvider) (*sniffer.Config, error) {
|
||||
snifferConfig := &sniffer.Config{
|
||||
Enable: snifferRaw.Enable,
|
||||
ForceDnsMapping: snifferRaw.ForceDnsMapping,
|
||||
@@ -1722,7 +1723,7 @@ func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]providerTypes.
|
||||
return snifferConfig, nil
|
||||
}
|
||||
|
||||
func parseIPCIDR(addresses []string, cidrSet *cidr.IpCidrSet, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (matchers []C.IpMatcher, err error) {
|
||||
func parseIPCIDR(addresses []string, cidrSet *cidr.IpCidrSet, adapterName string, ruleProviders map[string]P.RuleProvider) (matchers []C.IpMatcher, err error) {
|
||||
var matcher C.IpMatcher
|
||||
for _, ipcidr := range addresses {
|
||||
ipcidrLower := strings.ToLower(ipcidr)
|
||||
@@ -1769,7 +1770,7 @@ func parseIPCIDR(addresses []string, cidrSet *cidr.IpCidrSet, adapterName string
|
||||
return
|
||||
}
|
||||
|
||||
func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (matchers []C.DomainMatcher, err error) {
|
||||
func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapterName string, ruleProviders map[string]P.RuleProvider) (matchers []C.DomainMatcher, err error) {
|
||||
var matcher C.DomainMatcher
|
||||
for _, domain := range domains {
|
||||
domainLower := strings.ToLower(domain)
|
||||
@@ -1812,14 +1813,14 @@ func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapte
|
||||
return
|
||||
}
|
||||
|
||||
func parseIPRuleSet(domainSetName string, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (C.IpMatcher, error) {
|
||||
func parseIPRuleSet(domainSetName string, adapterName string, ruleProviders map[string]P.RuleProvider) (C.IpMatcher, error) {
|
||||
if rp, ok := ruleProviders[domainSetName]; !ok {
|
||||
return nil, fmt.Errorf("not found rule-set: %s", domainSetName)
|
||||
} else {
|
||||
switch rp.Behavior() {
|
||||
case providerTypes.Domain:
|
||||
case P.Domain:
|
||||
return nil, fmt.Errorf("rule provider type error, except ipcidr,actual %s", rp.Behavior())
|
||||
case providerTypes.Classical:
|
||||
case P.Classical:
|
||||
log.Warnln("%s provider is %s, only matching it contain ip rule", rp.Name(), rp.Behavior())
|
||||
default:
|
||||
}
|
||||
@@ -1827,14 +1828,14 @@ func parseIPRuleSet(domainSetName string, adapterName string, ruleProviders map[
|
||||
return RP.NewRuleSet(domainSetName, adapterName, false, true)
|
||||
}
|
||||
|
||||
func parseDomainRuleSet(domainSetName string, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (C.DomainMatcher, error) {
|
||||
func parseDomainRuleSet(domainSetName string, adapterName string, ruleProviders map[string]P.RuleProvider) (C.DomainMatcher, error) {
|
||||
if rp, ok := ruleProviders[domainSetName]; !ok {
|
||||
return nil, fmt.Errorf("not found rule-set: %s", domainSetName)
|
||||
} else {
|
||||
switch rp.Behavior() {
|
||||
case providerTypes.IPCIDR:
|
||||
case P.IPCIDR:
|
||||
return nil, fmt.Errorf("rule provider type error, except domain,actual %s", rp.Behavior())
|
||||
case providerTypes.Classical:
|
||||
case P.Classical:
|
||||
log.Warnln("%s provider is %s, only matching it contain domain rule", rp.Name(), rp.Behavior())
|
||||
default:
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/updater"
|
||||
"github.com/metacubex/mihomo/config"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/dns"
|
||||
"github.com/metacubex/mihomo/listener"
|
||||
authStore "github.com/metacubex/mihomo/listener/auth"
|
||||
@@ -303,18 +303,18 @@ func updateHosts(tree *trie.DomainTrie[resolver.HostValue]) {
|
||||
resolver.DefaultHosts = resolver.NewHosts(tree)
|
||||
}
|
||||
|
||||
func updateProxies(proxies map[string]C.Proxy, providers map[string]provider.ProxyProvider) {
|
||||
func updateProxies(proxies map[string]C.Proxy, providers map[string]P.ProxyProvider) {
|
||||
tunnel.UpdateProxies(proxies, providers)
|
||||
}
|
||||
|
||||
func updateRules(rules []C.Rule, subRules map[string][]C.Rule, ruleProviders map[string]provider.RuleProvider) {
|
||||
func updateRules(rules []C.Rule, subRules map[string][]C.Rule, ruleProviders map[string]P.RuleProvider) {
|
||||
tunnel.UpdateRules(rules, subRules, ruleProviders)
|
||||
}
|
||||
|
||||
func loadProvider[P provider.Provider](providers map[string]P) {
|
||||
load := func(pv P) {
|
||||
func loadProvider[T P.Provider](providers map[string]T) {
|
||||
load := func(pv T) {
|
||||
name := pv.Name()
|
||||
if pv.VehicleType() == provider.Compatible {
|
||||
if pv.VehicleType() == P.Compatible {
|
||||
log.Infoln("Start initial compatible provider %s", name)
|
||||
} else {
|
||||
log.Infoln("Start initial provider %s", name)
|
||||
@@ -322,11 +322,11 @@ func loadProvider[P provider.Provider](providers map[string]P) {
|
||||
|
||||
if err := pv.Initial(); err != nil {
|
||||
switch pv.Type() {
|
||||
case provider.Proxy:
|
||||
case P.Proxy:
|
||||
{
|
||||
log.Errorln("initial proxy provider %s error: %v", name, err)
|
||||
}
|
||||
case provider.Rule:
|
||||
case P.Rule:
|
||||
{
|
||||
log.Errorln("initial rule provider %s error: %v", name, err)
|
||||
}
|
||||
|
||||
+13
-13
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/metacubex/mihomo/config"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/hub/executor"
|
||||
P "github.com/metacubex/mihomo/listener"
|
||||
"github.com/metacubex/mihomo/listener"
|
||||
LC "github.com/metacubex/mihomo/listener/config"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
"github.com/metacubex/mihomo/tunnel"
|
||||
@@ -306,7 +306,7 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if general.AllowLan != nil {
|
||||
P.SetAllowLan(*general.AllowLan)
|
||||
listener.SetAllowLan(*general.AllowLan)
|
||||
}
|
||||
|
||||
if general.SkipAuthPrefixes != nil {
|
||||
@@ -322,7 +322,7 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if general.BindAddress != nil {
|
||||
P.SetBindAddress(*general.BindAddress)
|
||||
listener.SetBindAddress(*general.BindAddress)
|
||||
}
|
||||
|
||||
if general.Sniffing != nil {
|
||||
@@ -337,17 +337,17 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
|
||||
dialer.DefaultInterface.Store(*general.InterfaceName)
|
||||
}
|
||||
|
||||
ports := P.GetPorts()
|
||||
ports := listener.GetPorts()
|
||||
|
||||
P.ReCreateHTTP(pointerOrDefault(general.Port, ports.Port), tunnel.Tunnel)
|
||||
P.ReCreateSocks(pointerOrDefault(general.SocksPort, ports.SocksPort), tunnel.Tunnel)
|
||||
P.ReCreateRedir(pointerOrDefault(general.RedirPort, ports.RedirPort), tunnel.Tunnel)
|
||||
P.ReCreateTProxy(pointerOrDefault(general.TProxyPort, ports.TProxyPort), tunnel.Tunnel)
|
||||
P.ReCreateMixed(pointerOrDefault(general.MixedPort, ports.MixedPort), tunnel.Tunnel)
|
||||
P.ReCreateTun(pointerOrDefaultTun(general.Tun, P.LastTunConf), tunnel.Tunnel)
|
||||
P.ReCreateShadowSocks(pointerOrDefault(general.ShadowSocksConfig, ports.ShadowSocksConfig), tunnel.Tunnel)
|
||||
P.ReCreateVmess(pointerOrDefault(general.VmessConfig, ports.VmessConfig), tunnel.Tunnel)
|
||||
P.ReCreateTuic(pointerOrDefaultTuicServer(general.TuicServer, P.LastTuicConf), tunnel.Tunnel)
|
||||
listener.ReCreateHTTP(pointerOrDefault(general.Port, ports.Port), tunnel.Tunnel)
|
||||
listener.ReCreateSocks(pointerOrDefault(general.SocksPort, ports.SocksPort), tunnel.Tunnel)
|
||||
listener.ReCreateRedir(pointerOrDefault(general.RedirPort, ports.RedirPort), tunnel.Tunnel)
|
||||
listener.ReCreateTProxy(pointerOrDefault(general.TProxyPort, ports.TProxyPort), tunnel.Tunnel)
|
||||
listener.ReCreateMixed(pointerOrDefault(general.MixedPort, ports.MixedPort), tunnel.Tunnel)
|
||||
listener.ReCreateTun(pointerOrDefaultTun(general.Tun, listener.LastTunConf), tunnel.Tunnel)
|
||||
listener.ReCreateShadowSocks(pointerOrDefault(general.ShadowSocksConfig, ports.ShadowSocksConfig), tunnel.Tunnel)
|
||||
listener.ReCreateVmess(pointerOrDefault(general.VmessConfig, ports.VmessConfig), tunnel.Tunnel)
|
||||
listener.ReCreateTuic(pointerOrDefaultTuicServer(general.TuicServer, listener.LastTuicConf), tunnel.Tunnel)
|
||||
|
||||
if general.Mode != nil {
|
||||
tunnel.SetMode(*general.Mode)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/tunnel"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
@@ -45,12 +45,12 @@ func getProviders(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func getProvider(w http.ResponseWriter, r *http.Request) {
|
||||
provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
|
||||
provider := r.Context().Value(CtxKeyProvider).(P.ProxyProvider)
|
||||
render.JSON(w, r, provider)
|
||||
}
|
||||
|
||||
func updateProvider(w http.ResponseWriter, r *http.Request) {
|
||||
provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
|
||||
provider := r.Context().Value(CtxKeyProvider).(P.ProxyProvider)
|
||||
if err := provider.Update(); err != nil {
|
||||
render.Status(r, http.StatusServiceUnavailable)
|
||||
render.JSON(w, r, newError(err.Error()))
|
||||
@@ -60,7 +60,7 @@ func updateProvider(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func healthCheckProvider(w http.ResponseWriter, r *http.Request) {
|
||||
provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
|
||||
provider := r.Context().Value(CtxKeyProvider).(P.ProxyProvider)
|
||||
provider.HealthCheck()
|
||||
render.NoContent(w, r)
|
||||
}
|
||||
@@ -93,7 +93,7 @@ func findProviderProxyByName(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
name = r.Context().Value(CtxKeyProxyName).(string)
|
||||
pd = r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
|
||||
pd = r.Context().Value(CtxKeyProvider).(P.ProxyProvider)
|
||||
)
|
||||
proxy, exist := lo.Find(pd.Proxies(), func(proxy C.Proxy) bool {
|
||||
return proxy.Name() == name
|
||||
@@ -128,7 +128,7 @@ func getRuleProviders(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func updateRuleProvider(w http.ResponseWriter, r *http.Request) {
|
||||
provider := r.Context().Value(CtxKeyProvider).(provider.RuleProvider)
|
||||
provider := r.Context().Value(CtxKeyProvider).(P.RuleProvider)
|
||||
if err := provider.Update(); err != nil {
|
||||
render.Status(r, http.StatusServiceUnavailable)
|
||||
render.JSON(w, r, newError(err.Error()))
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/iface"
|
||||
"github.com/metacubex/mihomo/component/resolver"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
LC "github.com/metacubex/mihomo/listener/config"
|
||||
"github.com/metacubex/mihomo/listener/sing"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
@@ -133,7 +133,7 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis
|
||||
}
|
||||
}
|
||||
ctx := context.TODO()
|
||||
rpTunnel := tunnel.(provider.Tunnel)
|
||||
rpTunnel := tunnel.(P.Tunnel)
|
||||
if options.GSOMaxSize == 0 {
|
||||
options.GSOMaxSize = 65536
|
||||
}
|
||||
@@ -504,7 +504,7 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis
|
||||
return
|
||||
}
|
||||
|
||||
func (l *Listener) ruleUpdateCallback(ruleProvider provider.RuleProvider) {
|
||||
func (l *Listener) ruleUpdateCallback(ruleProvider P.RuleProvider) {
|
||||
name := ruleProvider.Name()
|
||||
if slices.Contains(l.options.RouteAddressSet, name) {
|
||||
l.updateRule(ruleProvider, false, true)
|
||||
@@ -520,7 +520,7 @@ type toIpCidr interface {
|
||||
ToIpCidr() *netipx.IPSet
|
||||
}
|
||||
|
||||
func (l *Listener) updateRule(ruleProvider provider.RuleProvider, exclude bool, update bool) {
|
||||
func (l *Listener) updateRule(ruleProvider P.RuleProvider, exclude bool, update bool) {
|
||||
l.ruleUpdateMutex.Lock()
|
||||
defer l.ruleUpdateMutex.Unlock()
|
||||
name := ruleProvider.Name()
|
||||
|
||||
+21
-21
@@ -17,13 +17,13 @@ import (
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
"github.com/metacubex/mihomo/component/loopback"
|
||||
"github.com/metacubex/mihomo/component/nat"
|
||||
P "github.com/metacubex/mihomo/component/process"
|
||||
"github.com/metacubex/mihomo/component/process"
|
||||
"github.com/metacubex/mihomo/component/resolver"
|
||||
"github.com/metacubex/mihomo/component/slowdown"
|
||||
"github.com/metacubex/mihomo/component/sniffer"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/features"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
icontext "github.com/metacubex/mihomo/context"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
"github.com/metacubex/mihomo/tunnel/statistic"
|
||||
@@ -43,8 +43,8 @@ var (
|
||||
listeners = make(map[string]C.InboundListener)
|
||||
subRules map[string][]C.Rule
|
||||
proxies = make(map[string]C.Proxy)
|
||||
providers map[string]provider.ProxyProvider
|
||||
ruleProviders map[string]provider.RuleProvider
|
||||
providers map[string]P.ProxyProvider
|
||||
ruleProviders map[string]P.RuleProvider
|
||||
configMux sync.RWMutex
|
||||
|
||||
// for compatibility, lazy init
|
||||
@@ -59,19 +59,19 @@ var (
|
||||
// default timeout for UDP session
|
||||
udpTimeout = 60 * time.Second
|
||||
|
||||
findProcessMode = atomic.NewInt32Enum(P.FindProcessStrict)
|
||||
findProcessMode = atomic.NewInt32Enum(process.FindProcessStrict)
|
||||
|
||||
snifferDispatcher *sniffer.Dispatcher
|
||||
sniffingEnable = false
|
||||
|
||||
ruleUpdateCallback = utils.NewCallback[provider.RuleProvider]()
|
||||
ruleUpdateCallback = utils.NewCallback[P.RuleProvider]()
|
||||
)
|
||||
|
||||
type tunnel struct{}
|
||||
|
||||
var Tunnel = tunnel{}
|
||||
var _ C.Tunnel = Tunnel
|
||||
var _ provider.Tunnel = Tunnel
|
||||
var _ P.Tunnel = Tunnel
|
||||
|
||||
func (t tunnel) HandleTCPConn(conn net.Conn, metadata *C.Metadata) {
|
||||
connCtx := icontext.NewConnContext(conn, metadata)
|
||||
@@ -112,15 +112,15 @@ func (t tunnel) NatTable() C.NatTable {
|
||||
return natTable
|
||||
}
|
||||
|
||||
func (t tunnel) Providers() map[string]provider.ProxyProvider {
|
||||
func (t tunnel) Providers() map[string]P.ProxyProvider {
|
||||
return providers
|
||||
}
|
||||
|
||||
func (t tunnel) RuleProviders() map[string]provider.RuleProvider {
|
||||
func (t tunnel) RuleProviders() map[string]P.RuleProvider {
|
||||
return ruleProviders
|
||||
}
|
||||
|
||||
func (t tunnel) RuleUpdateCallback() *utils.Callback[provider.RuleProvider] {
|
||||
func (t tunnel) RuleUpdateCallback() *utils.Callback[P.RuleProvider] {
|
||||
return ruleUpdateCallback
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ func Listeners() map[string]C.InboundListener {
|
||||
}
|
||||
|
||||
// UpdateRules handle update rules
|
||||
func UpdateRules(newRules []C.Rule, newSubRule map[string][]C.Rule, rp map[string]provider.RuleProvider) {
|
||||
func UpdateRules(newRules []C.Rule, newSubRule map[string][]C.Rule, rp map[string]P.RuleProvider) {
|
||||
configMux.Lock()
|
||||
rules = newRules
|
||||
ruleProviders = rp
|
||||
@@ -223,17 +223,17 @@ func ProxiesWithProviders() map[string]C.Proxy {
|
||||
}
|
||||
|
||||
// Providers return all compatible providers
|
||||
func Providers() map[string]provider.ProxyProvider {
|
||||
func Providers() map[string]P.ProxyProvider {
|
||||
return providers
|
||||
}
|
||||
|
||||
// RuleProviders return all loaded rule providers
|
||||
func RuleProviders() map[string]provider.RuleProvider {
|
||||
func RuleProviders() map[string]P.RuleProvider {
|
||||
return ruleProviders
|
||||
}
|
||||
|
||||
// UpdateProxies handle update proxies
|
||||
func UpdateProxies(newProxies map[string]C.Proxy, newProviders map[string]provider.ProxyProvider) {
|
||||
func UpdateProxies(newProxies map[string]C.Proxy, newProviders map[string]P.ProxyProvider) {
|
||||
configMux.Lock()
|
||||
proxies = newProxies
|
||||
providers = newProviders
|
||||
@@ -263,13 +263,13 @@ func SetMode(m TunnelMode) {
|
||||
mode = m
|
||||
}
|
||||
|
||||
func FindProcessMode() P.FindProcessMode {
|
||||
func FindProcessMode() process.FindProcessMode {
|
||||
return findProcessMode.Load()
|
||||
}
|
||||
|
||||
// SetFindProcessMode replace SetAlwaysFindProcess
|
||||
// always find process info if legacyAlways = true or mode.Always() = true, may be increase many memory
|
||||
func SetFindProcessMode(mode P.FindProcessMode) {
|
||||
func SetFindProcessMode(mode process.FindProcessMode) {
|
||||
findProcessMode.Store(mode)
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ func resolveMetadata(metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err erro
|
||||
attemptProcessLookup = false
|
||||
if !features.CMFA {
|
||||
// normal check for process
|
||||
uid, path, err := P.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, int(metadata.SrcPort))
|
||||
uid, path, err := process.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, int(metadata.SrcPort))
|
||||
if err != nil {
|
||||
log.Debugln("[Process] find process error for %s: %v", metadata.String(), err)
|
||||
} else {
|
||||
@@ -366,13 +366,13 @@ func resolveMetadata(metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err erro
|
||||
metadata.ProcessPath = path
|
||||
metadata.Uid = uid
|
||||
|
||||
if pkg, err := P.FindPackageName(metadata); err == nil { // for android (not CMFA) package names
|
||||
if pkg, err := process.FindPackageName(metadata); err == nil { // for android (not CMFA) package names
|
||||
metadata.Process = pkg
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// check package names
|
||||
pkg, err := P.FindPackageName(metadata)
|
||||
pkg, err := process.FindPackageName(metadata)
|
||||
if err != nil {
|
||||
log.Debugln("[Process] find process error for %s: %v", metadata.String(), err)
|
||||
} else {
|
||||
@@ -384,10 +384,10 @@ func resolveMetadata(metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err erro
|
||||
}
|
||||
|
||||
switch FindProcessMode() {
|
||||
case P.FindProcessAlways:
|
||||
case process.FindProcessAlways:
|
||||
helper.FindProcess()
|
||||
helper.FindProcess = nil
|
||||
case P.FindProcessOff:
|
||||
case process.FindProcessOff:
|
||||
helper.FindProcess = nil
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-ddns-go
|
||||
PKG_VERSION:=1.6.3
|
||||
PKG_RELEASE:=20251025
|
||||
PKG_VERSION:=1.6.4
|
||||
PKG_RELEASE:=20251106
|
||||
|
||||
PKG_MAINTAINER:=sirpdboy <herboy2008@gmail.com>
|
||||
PKG_CONFIG_DEPENDS:=
|
||||
|
||||
+2
-2
@@ -77,8 +77,8 @@ function renderStatus(isRunning, listen_port, noweb, version) {
|
||||
);
|
||||
|
||||
if (isRunning) {
|
||||
html += String.format(' <a class="btn cbi-button" href="%s//%s:%s" target="_blank">%s</a>',
|
||||
window.location.protocol, window.location.hostname, listen_port, _('Open Web Interface'));
|
||||
html += String.format(' <a class="btn cbi-button" href="http://%s:%s" target="_blank">%s</a>',
|
||||
window.location.hostname, listen_port, _('Open Web Interface'));
|
||||
}
|
||||
|
||||
return html;
|
||||
|
||||
+64
-37
@@ -21,57 +21,84 @@ return view.extend({
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
render: function() {
|
||||
var self = this;
|
||||
|
||||
return this.checkRunning().then(function(checkResult) {
|
||||
var isRunning = checkResult.isRunning;
|
||||
var port = uci.get('ddns-go', 'config', 'port') || '[::]:9876';
|
||||
var noweb = uci.get('ddns-go', 'config', 'noweb');
|
||||
port = port.split(':').pop();
|
||||
|
||||
return this.checkRunning().then(function(checkResult) {
|
||||
var isRunning = checkResult.isRunning;
|
||||
var port = uci.get('ddns-go', 'config', 'port') || '[::]:9876';
|
||||
var noweb = uci.get('ddns-go', 'config', 'noweb') ;
|
||||
port = port.split(':').pop();
|
||||
|
||||
var container = E('div');
|
||||
console.log('Debug: isRunning=' + isRunning + ', noweb=' + noweb + ', port=' + port);
|
||||
if (!isRunning || noweb === '1') {
|
||||
var container = E('div');
|
||||
if (!isRunning || noweb === '1') {
|
||||
if (!isRunning) {
|
||||
var message = _('DDNS-GO Service Not Running');
|
||||
}
|
||||
if (noweb === '1') {
|
||||
if (noweb === '1') {
|
||||
var message = _('DDNS-GO Web Interface Disabled');
|
||||
}
|
||||
|
||||
container.appendChild(E('div', {
|
||||
style: 'text-align: center; padding: 2em;'
|
||||
container.appendChild(E('div', {
|
||||
style: 'text-align: center; padding: 2em;'
|
||||
}, [
|
||||
E('img', {
|
||||
src: 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMjQiIGhlaWdodD0iMTAyNCIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCI+PHBhdGggZmlsbD0iI2RmMDAwMCIgZD0iTTk0Mi40MjEgMjM0LjYyNGw4MC44MTEtODAuODExLTE1My4wNDUtMTUzLjA0NS04MC44MTEgODAuODExYy03OS45NTctNTEuNjI3LTE3NS4xNDctODEuNTc5LTI3Ny4zNzYtODEuNTc5LTI4Mi43NTIgMC01MTIgMjI5LjI0OC01MTIgNTEyIDAgMTAyLjIyOSAyOS45NTIgMTk3LjQxOSA4MS41NzkgMjc3LjM3NmwtODAuODExIDgwLjgxMSAxNTMuMDQ1IDE1My4wNDUgODAuODExLTgwLjgxMWM3OS45NTcgNTEuNjI3IDE3NS4xNDcgODEuNTc5IDI3Ny4zNzYgODEuNTc5IDI4Mi43NTIgMCA1MTItMjI5LjI0OCA1MTItNTEyIDAtMTAyLjIyOS0yOS45NTItMTk3LjQxOS04MS41NzktMjc3LjM3NnpNMTk0Ljk0NCA1MTJjMC0xNzUuMTA0IDE0MS45NTItMzE3LjA1NiAzMTcuMDU2LTMxNy4wNTYgNDggMCA5My40ODMgMTAuNjY3IDEzNC4yMjkgMjkuNzgxbC00MjEuNTQ3IDQyMS41NDdjLTE5LjA3Mi00MC43ODktMjkuNzM5LTg2LjI3Mi0yOS43MzktMTM0LjI3MnpNNTEyIDgyOS4wNTZjLTQ4IDAtOTMuNDgzLTEwLjY2Ny0xMzQuMjI5LTI5Ljc4MWw0MjEuNTQ3LTQyMS41NDdjMTkuMDcyIDQwLjc4OSAyOS43ODEgODYuMjcyIDI5Ljc4MSAxMzQuMjI5LTAuMDQzIDE3NS4xNDctMTQxLjk5NSAzMTcuMDk5LTMxNy4wOTkgMzE3LjA5OXoiLz48L3N2Zz4=',
|
||||
style: 'width: 100px; height: 100px; margin-bottom: 1em;'
|
||||
}),
|
||||
E('h2', {}, message)
|
||||
]));
|
||||
} else {
|
||||
var isHttps = window.location.protocol === 'https:';
|
||||
|
||||
if (isHttps) {
|
||||
var buttonContainer = E('div', {
|
||||
style: 'text-align: center; padding: 2em;'
|
||||
}, [
|
||||
E('img', {
|
||||
src: 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMjQiIGhlaWdodD0iMTAyNCIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCI+PHBhdGggZmlsbD0iI2RmMDAwMCIgZD0iTTk0Mi40MjEgMjM0LjYyNGw4MC44MTEtODAuODExLTE1My4wNDUtMTUzLjA0NS04MC44MTEgODAuODExYy03OS45NTctNTEuNjI3LTE3NS4xNDctODEuNTc5LTI3Ny4zNzYtODEuNTc5LTI4Mi43NTIgMC01MTIgMjI5LjI0OC01MTIgNTEyIDAgMTAyLjIyOSAyOS45NTIgMTk3LjQxOSA4MS41NzkgMjc3LjM3NmwtODAuODExIDgwLjgxMSAxNTMuMDQ1IDE1My4wNDUgODAuODExLTgwLjgxMWM3OS45NTcgNTEuNjI3IDE3NS4xNDcgODEuNTc5IDI3Ny4zNzYgODEuNTc5IDI4Mi43NTIgMCA1MTItMjI5LjI0OCA1MTItNTEyIDAtMTAyLjIyOS0yOS45NTItMTk3LjQxOS04MS41NzktMjc3LjM3NnpNMTk0Ljk0NCA1MTJjMC0xNzUuMTA0IDE0MS45NTItMzE3LjA1NiAzMTcuMDU2LTMxNy4wNTYgNDggMCA5My40ODMgMTAuNjY3IDEzNC4yMjkgMjkuNzgxbC00MjEuNTQ3IDQyMS41NDdjLTE5LjA3Mi00MC43ODktMjkuNzM5LTg2LjI3Mi0yOS43MzktMTM0LjI3MnpNNTEyIDgyOS4wNTZjLTQ4IDAtOTMuNDgzLTEwLjY2Ny0xMzQuMjI5LTI5Ljc4MWw0MjEuNTQ3LTQyMS41NDdjMTkuMDcyIDQwLjc4OSAyOS43ODEgODYuMjcyIDI5Ljc4MSAxMzQuMjI5LTAuMDQzIDE3NS4xNDctMTQxLjk5NSAzMTcuMDk5LTMxNy4wOTkgMzE3LjA5OXoiLz48L3N2Zz4=',
|
||||
style: 'width: 100px; height: 100px; margin-bottom: 1em;'
|
||||
}),
|
||||
E('h2', {}, message)
|
||||
]));
|
||||
E('h2', {}, _('DDNS-GO Control panel')),
|
||||
E('p', {}, _('Due to browser security policies, the DDNS-GO interface https cannot be embedded directly.')),
|
||||
E('a', {
|
||||
href: 'http://' + window.location.hostname + ':' + port,
|
||||
target: '_blank',
|
||||
class: 'cbi-button cbi-button-apply',
|
||||
style: 'display: inline-block; margin-top: 1em; padding: 10px 20px; font-size: 16px; text-decoration: none; color: white;'
|
||||
}, _('Open Web Interface')),
|
||||
E('div', { 'style': 'text-align: right; font-style: italic;' }, [
|
||||
E('span', {}, [
|
||||
_('© github '),
|
||||
E('a', {
|
||||
'href': 'https://github.com/sirpdboy',
|
||||
'target': '_blank',
|
||||
'style': 'text-decoration: none;'
|
||||
}, 'by sirpdboy')
|
||||
])
|
||||
])
|
||||
]);
|
||||
container.appendChild(buttonContainer);
|
||||
} else {
|
||||
var iframe = E('iframe', {
|
||||
src: window.location.protocol + '//' + window.location.hostname + ':' + port,
|
||||
src: 'http://' + window.location.hostname + ':' + port,
|
||||
style: 'width: 100%; min-height: 100vh; border: none;'
|
||||
});
|
||||
container.appendChild(iframe);
|
||||
}
|
||||
|
||||
poll.add(function() {
|
||||
return self.checkRunning().then(function(checkResult) {
|
||||
var newStatus = checkResult.isRunning;
|
||||
if (newStatus !== isRunning) {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
}, 5);
|
||||
|
||||
poll.start();
|
||||
|
||||
return container;
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
poll.add(function() {
|
||||
return self.checkRunning().then(function(checkResult) {
|
||||
var newStatus = checkResult.isRunning;
|
||||
if (newStatus !== isRunning) {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
}, 5);
|
||||
|
||||
poll.start();
|
||||
|
||||
return container;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
|
||||
@@ -118,5 +118,5 @@ msgstr "立刻重启服务"
|
||||
msgid "Restart Later"
|
||||
msgstr "稍后重启"
|
||||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
msgid "Due to browser security policies, the DDNS-GO interface https cannot be embedded directly."
|
||||
msgstr "由于浏览器安全策略,DDNS-GO接口https不能直接嵌入。"
|
||||
|
||||
@@ -10,8 +10,8 @@ THEME_TITLE:=Kucat Theme
|
||||
PKG_NAME:=luci-theme-$(THEME_NAME)
|
||||
LUCI_TITLE:=Kucat Theme by sirpdboy
|
||||
LUCI_DEPENDS:=
|
||||
PKG_VERSION:=2.7.3
|
||||
PKG_RELEASE:=20251028
|
||||
PKG_VERSION:=2.7.4
|
||||
PKG_RELEASE:=20251106
|
||||
|
||||
define Package/luci-theme-$(THEME_NAME)/conffiles
|
||||
/www/luci-static/resources/background/
|
||||
|
||||
@@ -869,7 +869,7 @@ small {
|
||||
.main-right>#maincontent {
|
||||
position: relative;
|
||||
background-color: rgba(var(--primary-rgbbody),var(--primary-rgbm-ts));
|
||||
padding: 0.2rem 0.2rem 3rem 0.2rem;
|
||||
padding: 0.2rem 0.2rem 3rem 0.5rem;
|
||||
z-index: 50
|
||||
}
|
||||
|
||||
@@ -960,7 +960,51 @@ header .fill .status span {
|
||||
flex-wrap: nowrap
|
||||
}
|
||||
|
||||
span[data-indicator="uci-changes"],span[data-indicator="poll-status"] {
|
||||
span[data-indicator="poll-status"] {
|
||||
font-size: 0 !important;
|
||||
cursor: pointer;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
color: transparent !important;
|
||||
-webkit-appearance: none;
|
||||
display: flex;
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
-moz-appearance: none;
|
||||
padding: 1rem;
|
||||
transition: all .3s
|
||||
}
|
||||
|
||||
span[data-indicator="poll-status"]:not([data-style="inactive"]):before {
|
||||
font-size: 1.5rem !important;
|
||||
font-family: 'kucat' !important;
|
||||
content: "\e20b";
|
||||
color: var(--body-color);
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
span[data-indicator="poll-status"]:not([data-style="active"]):before {
|
||||
font-size: 1.5rem !important;
|
||||
font-family: 'kucat' !important;
|
||||
content: "\e20a";
|
||||
color: var(--body-color);
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
#indicators span[data-indicator="poll-status"],{
|
||||
line-height: 1;
|
||||
padding: 1rem;
|
||||
cursor: pointer !important;
|
||||
font-weight: normal !important;
|
||||
margin: 0;
|
||||
display: inline-block
|
||||
}
|
||||
|
||||
#indicators span[data-indicator="poll-status"]:hover {
|
||||
border-radius: var(--radius1);
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
span[data-indicator="uci-changes"],#indicators span[data-indicator="poll-status"] {
|
||||
font-size: 0 !important;
|
||||
cursor: pointer;
|
||||
background-repeat: no-repeat;
|
||||
@@ -979,7 +1023,7 @@ span[data-indicator="uci-changes"]:before {
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
span[data-indicator="poll-status"]:not([data-style="inactive"]):before {
|
||||
#indicators span[data-indicator="poll-status"]:not([data-style="inactive"]):before {
|
||||
font-size: 1.5rem !important;
|
||||
font-family: 'kucat' !important;
|
||||
content: "\e936";
|
||||
@@ -987,7 +1031,7 @@ span[data-indicator="poll-status"]:not([data-style="inactive"]):before {
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
span[data-indicator="poll-status"]:not([data-style="active"]):before {
|
||||
#indicators span[data-indicator="poll-status"]:not([data-style="active"]):before {
|
||||
font-family: 'kucat' !important;
|
||||
font-size: 1.5rem !important;
|
||||
content: "\e932";
|
||||
@@ -995,7 +1039,7 @@ span[data-indicator="poll-status"]:not([data-style="active"]):before {
|
||||
text-decoration: none
|
||||
}
|
||||
.pdboy-dark:hover,.pdboy-light:hover,
|
||||
span[data-indicator="uci-changes"]:hover,span[data-indicator="poll-status"]:hover,.pdboy-qlogout:hover,.showSide:hover {
|
||||
span[data-indicator="uci-changes"]:hover,#indicators span[data-indicator="poll-status"]:hover,.pdboy-qlogout:hover,.showSide:hover {
|
||||
background-color: var(--menu-hover-barbgcolor) !important;
|
||||
color: var(--menu-hover-color);
|
||||
border-radius: var(--radius1);
|
||||
@@ -1003,7 +1047,7 @@ span[data-indicator="uci-changes"]:hover,span[data-indicator="poll-status"]:hove
|
||||
}
|
||||
|
||||
.pdboy-dark,.pdboy-light,
|
||||
span[data-indicator="uci-changes"],span[data-indicator="poll-status"],.pdboy-qlogout {
|
||||
span[data-indicator="uci-changes"],#indicators span[data-indicator="poll-status"],.pdboy-qlogout {
|
||||
line-height: 1;
|
||||
padding: 1rem;
|
||||
cursor: pointer !important;
|
||||
@@ -1089,63 +1133,6 @@ span[data-indicator="uci-changes"],span[data-indicator="poll-status"],.pdboy-qlo
|
||||
-moz-osx-font-smoothing: grayscale
|
||||
}
|
||||
|
||||
.danger {
|
||||
background-color: #d9534f !important;
|
||||
color: #eee
|
||||
}
|
||||
|
||||
.warning {
|
||||
background-color: #b98413 !important;
|
||||
margin: 0 0 0.5rem 0;
|
||||
color: #eee
|
||||
}
|
||||
|
||||
.success {
|
||||
background-color: #1a8361 !important;
|
||||
color: #eee;
|
||||
width: 14rem !important
|
||||
}
|
||||
|
||||
#log_textarea {
|
||||
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.16),0 0 1px 0 var(--input-boxcolor)
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #f00
|
||||
}
|
||||
|
||||
.alert,.alert-message {
|
||||
padding: 1rem;
|
||||
border: 0;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
line-height: 1.6em;
|
||||
font-family: inherit;
|
||||
min-width: inherit;
|
||||
overflow: unset;
|
||||
border-radius: var(--radius1);
|
||||
background-color: rgba(var(--primary-rgbbody),var(--primary-rgbm-ts));
|
||||
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 var(--input-boxcolor)
|
||||
}
|
||||
|
||||
.alert-message>* {
|
||||
margin: 0;
|
||||
white-space: normal
|
||||
}
|
||||
|
||||
.alert-message>h4 {
|
||||
margin: 0.5rem;
|
||||
color: red;
|
||||
padding: 0.5rem 1rem;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.errorbox {
|
||||
color: #f8f8f8;
|
||||
background-color: #f0ad4e;
|
||||
border-color: #eea236
|
||||
}
|
||||
|
||||
.container .alert,.container .alert-message {
|
||||
margin-top: 1rem
|
||||
}
|
||||
@@ -1420,7 +1407,7 @@ h2 {
|
||||
h3 {
|
||||
font-size: var(--font-d);
|
||||
display: block;
|
||||
margin: 0.5rem 0;
|
||||
margin: 0.5rem 0 0 1rem;
|
||||
color: var(--primary-title-color);
|
||||
font-weight: bold;
|
||||
letter-spacing: 0.1rem;
|
||||
@@ -1433,7 +1420,7 @@ h4 {
|
||||
padding: 0.75rem 1.25rem;
|
||||
font-weight: 600;
|
||||
font-size: var(--font-z);
|
||||
color: var(--primary-title-color) !important;
|
||||
color: var(--primary-title-color) ;
|
||||
padding-bottom: 10px
|
||||
}
|
||||
|
||||
@@ -2529,11 +2516,68 @@ select,input {
|
||||
min-width: 270px;
|
||||
max-width: 900px;
|
||||
min-height: 32px;
|
||||
border-radius: var(--radius2) !important;
|
||||
background-color: rgba(var(--primary-rgbbody), 1)!important;
|
||||
color: var(--primary-title-color)!important;
|
||||
box-shadow: 0 2px 10px 0px rgba(255, 255, 255, .16), 0 0 10px 0 rgba(255, 255, 255, .12);
|
||||
margin: 5em auto;
|
||||
padding: 1rem;
|
||||
border-radius: var(--radius2) !important;
|
||||
background-color: rgba(var(--primary-rgbbody),1)!important;
|
||||
box-shadow: 0 2px 10px 0px rgba(255,255,255,.16),0 0 10px 0 rgba(255,255,255,.12)
|
||||
}
|
||||
|
||||
.danger {
|
||||
background-color: #d9534f ;
|
||||
color: #eee
|
||||
}
|
||||
|
||||
#log_textarea {
|
||||
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.16),0 0 1px 0 var(--input-boxcolor)
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #f00
|
||||
}
|
||||
|
||||
.alert,.alert-message {
|
||||
padding: 1rem;
|
||||
border: 0;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
line-height: 1.6em;
|
||||
font-family: inherit;
|
||||
min-width: inherit;
|
||||
overflow: unset;
|
||||
border-radius: var(--radius1);
|
||||
background-color: rgba(var(--primary-rgbbody),var(--primary-rgbm-ts));
|
||||
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 var(--input-boxcolor)
|
||||
}
|
||||
|
||||
.alert-message>* {
|
||||
margin: 0;
|
||||
white-space: normal
|
||||
}
|
||||
|
||||
.alert-message>h4 {
|
||||
margin: 0.5rem;
|
||||
color: red;
|
||||
padding: 0.5rem 1rem;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.warning {
|
||||
background-color: #b98413 !important;
|
||||
color: #eee!important;
|
||||
}
|
||||
|
||||
.success {
|
||||
background-color: #1a8361 !important;
|
||||
color: #eee!important;
|
||||
width: 14rem !important
|
||||
}
|
||||
|
||||
.errorbox {
|
||||
color: #f8f8f8!important;
|
||||
background-color: #f0ad4e!important;
|
||||
border-color: #eea236
|
||||
}
|
||||
|
||||
#modal_overlay .cbi-section,.modal .cbi-section {
|
||||
@@ -2599,10 +2643,9 @@ select,input {
|
||||
}
|
||||
|
||||
.notice {
|
||||
background-color: #b98413 !important;
|
||||
background-color: rgba(var(--primary-rgbm),1) !important;
|
||||
color: var(--primary-title-color);
|
||||
background-color: rgba(var(--primary-rgbbody), 1);
|
||||
padding: 2rem 1rem;
|
||||
color: #eee
|
||||
}
|
||||
.modal>p {
|
||||
font-size: var(--font-x);
|
||||
@@ -2718,9 +2761,8 @@ body.modal-overlay-active #modal_overlay {
|
||||
bottom: 0;
|
||||
left: .2em;
|
||||
width: 32px;
|
||||
color: var(--body-color);
|
||||
content: "";
|
||||
|
||||
color: var(--body-color);
|
||||
background: url(../../resources/icons/loading.svg) no-repeat center,
|
||||
url(../../resources/icons/loading.gif) no-repeat center;
|
||||
background-size: 20px;
|
||||
@@ -4028,6 +4070,7 @@ pre.command-output {
|
||||
--bg-light: rgba(255, 255, 255, 0);
|
||||
--bg-gray: rgba(var(--primary-rgbm), 0.02);
|
||||
--text-title: var(--primary-title-color);
|
||||
--text-secondary: var(--body-color);
|
||||
--border-color: rgba(255, 255, 255, 0);
|
||||
--border-light: rgba(255, 255, 255, 0);
|
||||
--text-primary: var(--inputtext-color);
|
||||
@@ -4189,12 +4232,11 @@ pre.command-output {
|
||||
.bandix-card ,
|
||||
.stats-card
|
||||
{
|
||||
background-color: rgba(var(--primary-rgbm), 0.1)!important;
|
||||
border-radius: 0 !important;
|
||||
box-shadow: 0 0 0 0 rgba(0, 0, 0, 0) !important;
|
||||
margin-bottom: 0 !important;
|
||||
background-color: rgba(var(--primary-rgbm), 0.05)!important;
|
||||
box-shadow: 0 1px 3px 0 var(--input-boxcolor) !important;
|
||||
border: 0px solid #333!important;
|
||||
border-bottom: 0px solid var(--input-boxcolor)!important;
|
||||
margin-bottom: 0 !important;
|
||||
overflow: auto!important;
|
||||
}
|
||||
|
||||
@@ -4283,6 +4325,9 @@ border-bottom: 0px solid #f1f5f9!important;
|
||||
[data-page="admin-system-package-manager"] .modal>textarea {
|
||||
white-space: nowrap
|
||||
}
|
||||
[data-page="admin-status-overview"] #view>div {
|
||||
padding: 0rem 0rem 1rem 0.5rem;
|
||||
}
|
||||
|
||||
.main>.main-left,.cbi-section,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),#maincontent>.container>form,#maincontent>.container>form>div,.tabs,.cbi-tabmenu,.cbi-tooltip,#view>p,#view>div,#view>table {
|
||||
backdrop-filter: var(--ufilter);
|
||||
@@ -4392,24 +4437,29 @@ div#add_link_div {
|
||||
padding: 0.5rem
|
||||
}
|
||||
|
||||
div#file-manager-container {
|
||||
#file-manager-container {
|
||||
margin-left: 0.5rem
|
||||
}
|
||||
|
||||
div#content-filemanager>div#file-list-container {
|
||||
margin-top: 10px !important
|
||||
#content-filemanager>#file-list-container {
|
||||
margin-top: 10px !important;
|
||||
min-width: 800px !important;
|
||||
max-width: 100% !important;
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
div#file-manager-container #file-table tr>th {
|
||||
#file-manager-container #file-table tr>th {
|
||||
background-color: rgba(var(--primary-rgbm),1);
|
||||
color: var(--menu-color)
|
||||
}
|
||||
|
||||
div#file-manager-container #status-bar {
|
||||
#file-list-container table>tbody>tr>td span {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
#file-manager-container #status-bar {
|
||||
background-color: rgba(var(--primary-rgbm),0.3)
|
||||
}
|
||||
|
||||
div#file-manager-container #status-bar #status-info {
|
||||
#file-manager-container #status-bar #status-info {
|
||||
color: var(--title-color)
|
||||
}
|
||||
|
||||
@@ -4417,6 +4467,9 @@ div#file-manager-container #status-bar #status-info {
|
||||
background-color: rgba(var(--primary-rgbm),0.4) !important
|
||||
}
|
||||
|
||||
#file-list-container table>tbody>tr>td {
|
||||
padding: 0.2rem
|
||||
}
|
||||
.cbi-tabcontainer-content #editor-container {
|
||||
width: 100%;
|
||||
border: 1px solid var(--inputborder-color)
|
||||
@@ -4441,9 +4494,6 @@ div#file-manager-container #status-bar #status-info {
|
||||
--clr-header: var(--title-color)
|
||||
}
|
||||
|
||||
#file-list-container table>tbody>tr>td {
|
||||
padding: 0.2rem
|
||||
}
|
||||
|
||||
.tr.cbi-section-table-row[id*="wolplus"],.tr.cbi-section-table-row[id*="firewall"] {
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -140,6 +140,7 @@ function link_add_node()
|
||||
local chunk = http.formvalue("chunk")
|
||||
local chunk_index = tonumber(http.formvalue("chunk_index"))
|
||||
local total_chunks = tonumber(http.formvalue("total_chunks"))
|
||||
local group = http.formvalue("group") or "default"
|
||||
|
||||
if chunk and chunk_index ~= nil and total_chunks ~= nil then
|
||||
-- 按顺序拼接到文件
|
||||
@@ -154,7 +155,7 @@ function link_add_node()
|
||||
end
|
||||
-- 如果是最后一片,才执行
|
||||
if chunk_index + 1 == total_chunks then
|
||||
luci.sys.call("lua /usr/share/passwall/subscribe.lua add log")
|
||||
luci.sys.call("lua /usr/share/passwall/subscribe.lua add " .. group)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,10 +23,12 @@ o.default = translate("Remarks")
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "group", translate("Group Name"))
|
||||
o.default = ""
|
||||
o:value("", translate("default"))
|
||||
local groups = {}
|
||||
m.uci:foreach(appname, "nodes", function(s)
|
||||
if s[".name"] ~= arg[1] then
|
||||
if s.group then
|
||||
if s.group and s.group ~= "" then
|
||||
groups[s.group] = true
|
||||
end
|
||||
end
|
||||
|
||||
+198
-4
@@ -4,7 +4,7 @@ local api = require "luci.passwall.api"
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
function ajax_add_node(link) {
|
||||
function ajax_add_node(link, group) {
|
||||
const chunkSize = 1000; // 分片发送以突破uhttpd的限制,每块1000字符
|
||||
const totalChunks = Math.ceil(link.length / chunkSize);
|
||||
let currentChunk = 0;
|
||||
@@ -31,6 +31,7 @@ local api = require "luci.passwall.api"
|
||||
formData.append("chunk", chunk);
|
||||
formData.append("chunk_index", currentChunk);
|
||||
formData.append("total_chunks", totalChunks);
|
||||
formData.append("group", group);
|
||||
xhr.send(formData);
|
||||
} else {
|
||||
window.location.href = '<%=api.url("node_list")%>';
|
||||
@@ -50,11 +51,12 @@ local api = require "luci.passwall.api"
|
||||
|
||||
function add_node() {
|
||||
var nodes_link = document.getElementById("nodes_link").value;
|
||||
var group = (document.querySelector('#addlink_group_custom input[type="hidden"]')?.value || "default");
|
||||
nodes_link = nodes_link.replace(/\t/g, "").replace(/\r\n|\r/g, "\n").trim();
|
||||
if (nodes_link != "") {
|
||||
var s = nodes_link.split('://');
|
||||
if (s.length > 1) {
|
||||
ajax_add_node(nodes_link);
|
||||
ajax_add_node(nodes_link, group);
|
||||
}
|
||||
else {
|
||||
alert("<%:Please enter the correct link.%>");
|
||||
@@ -83,6 +85,84 @@ local api = require "luci.passwall.api"
|
||||
window.location.href = '<%=api.url("add_node")%>?redirect=1';
|
||||
}
|
||||
|
||||
//自定义分组下拉列表事件
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var dropdown = document.getElementById("addlink_group_custom");
|
||||
if (!dropdown) return;
|
||||
|
||||
var display = dropdown.querySelector(".selected-display");
|
||||
var displayText = display.querySelector(".text");
|
||||
var list = dropdown.querySelector(".dropdown-list");
|
||||
var hidden = dropdown.querySelector('input[type="hidden"]');
|
||||
var input = dropdown.querySelector(".create-item-input");
|
||||
|
||||
display.addEventListener("click", function() {
|
||||
list.style.display = list.style.display === "none" ? "block" : "none";
|
||||
input.value = "";
|
||||
input.focus();
|
||||
});
|
||||
|
||||
function selectItem(li) {
|
||||
list.querySelectorAll(".dropdown-item").forEach(function(el){
|
||||
el.classList.remove("selected");
|
||||
});
|
||||
li.classList.add("selected");
|
||||
hidden.value = li.dataset.value;
|
||||
displayText.textContent = li.dataset.value || "<%:default%>";
|
||||
list.style.display = "none";
|
||||
}
|
||||
|
||||
list.addEventListener("click", function(e){
|
||||
var li = e.target.closest(".dropdown-item");
|
||||
if (!li || li.classList.contains("custom-input")) return;
|
||||
selectItem(li);
|
||||
});
|
||||
|
||||
input.addEventListener("keydown", function(e){
|
||||
if (e.keyCode !== 13) return;
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
var val = input.value.trim();
|
||||
if (!val) return;
|
||||
|
||||
var li = Array.from(list.querySelectorAll(".dropdown-item")).find(function(el){
|
||||
return el.dataset.value === val;
|
||||
});
|
||||
if (!li) {
|
||||
li = document.createElement("li");
|
||||
li.className = "dropdown-item";
|
||||
li.dataset.value = val;
|
||||
li.textContent = val;
|
||||
list.insertBefore(li, input.parentNode);
|
||||
}
|
||||
|
||||
input.value = "";
|
||||
selectItem(li);
|
||||
});
|
||||
// 从tab中读取分组名称
|
||||
var observer = new MutationObserver(function(mutations, obs){
|
||||
var tabs = document.querySelectorAll(".cbi-tabmenu li");
|
||||
if(!tabs.length) return;
|
||||
|
||||
tabs.forEach(function(li){
|
||||
var group = li.id.split('.').pop();
|
||||
if(group === "default") return;
|
||||
if(Array.from(list.querySelectorAll(".dropdown-item")).some(el => el.dataset.value === group)) return;
|
||||
|
||||
var newLi = document.createElement("li");
|
||||
newLi.className = "dropdown-item";
|
||||
newLi.dataset.value = group;
|
||||
newLi.textContent = group;
|
||||
|
||||
list.insertBefore(newLi, input.parentNode);
|
||||
});
|
||||
|
||||
obs.disconnect();
|
||||
});
|
||||
observer.observe(document.body, {childList: true, subtree: true});
|
||||
});
|
||||
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
@@ -93,6 +173,24 @@ local api = require "luci.passwall.api"
|
||||
<textarea id="nodes_link" rows="10"></textarea>
|
||||
<p id="nodes_link_text"><%:Enter share links, one per line. Subscription links are not supported!%></p>
|
||||
</div>
|
||||
<div class="cbi-value modal-center">
|
||||
<label class="cbi-value-title"><%:Group Name%></label>
|
||||
<div class="cbi-value-field">
|
||||
<div id="addlink_group_custom" class="custom-dropdown">
|
||||
<div class="selected-display">
|
||||
<span class="text"><%:default%></span>
|
||||
<span class="arrow">▾</span>
|
||||
</div>
|
||||
<ul class="dropdown-list" style="display:none;">
|
||||
<li class="dropdown-item" data-value=""><%:default%></li>
|
||||
<li class="dropdown-item custom-input">
|
||||
<input type="text" placeholder="-- <%:custom%> --" class="create-item-input">
|
||||
</li>
|
||||
</ul>
|
||||
<input type="hidden" name="addlink_group" value="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="add_link_button_container">
|
||||
<input class="btn cbi-button cbi-button-add" type="button" onclick="add_node()" value="<%:Add%>" />
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" onclick="close_add_link_div()" value="<%:Close%>" />
|
||||
@@ -107,7 +205,7 @@ local api = require "luci.passwall.api"
|
||||
<input class="btn cbi-button cbi-button-add" type="button" onclick="open_add_link_div()" value="<%:Add the node via the link%>" />
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" onclick="clear_all_nodes()" value="<%:Clear all nodes%>" />
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" onclick="delete_select_nodes()" value="<%:Delete select nodes%>" />
|
||||
<input class="btn cbi-button" type="button" onclick="checked_all_node(this)" value="<%:Select all%>" />
|
||||
<input class="btn cbi-button" type="button" id="select_all_btn" onclick="checked_all_node(this)" value="<%:Select all%>" />
|
||||
<input class="btn cbi-button cbi-button-apply" type="submit" name="cbi.apply" value="<%:Save & Apply%>" />
|
||||
<input class="btn cbi-button cbi-button-save" type="submit" name="cbi.save" value="<%:Save%>" />
|
||||
<input class="btn cbi-button cbi-button-reset" type="button" value="<%:Reset%>" onclick="location.href='<%=REQUEST_URI%>'" />
|
||||
@@ -147,12 +245,13 @@ local api = require "luci.passwall.api"
|
||||
padding: 5px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
|
||||
#nodes_link_text {
|
||||
color: red;
|
||||
font-size: 14px;
|
||||
margin-top: 5px;
|
||||
margin-top: 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -164,4 +263,99 @@ local api = require "luci.passwall.api"
|
||||
max-width: 300px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#add_link_modal_container .modal-center {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 15px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#add_link_modal_container .modal-center .cbi-value-title {
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
text-align: right;
|
||||
font-size: 13px;
|
||||
line-height: 28px;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
#add_link_modal_container .modal-center .cbi-value-field {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.custom-dropdown {
|
||||
position: relative;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 2px;
|
||||
width: 200px;
|
||||
font-size: 13px;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.selected-display {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 8px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.selected-display:hover {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.selected-display .arrow {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.dropdown-list {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-top: none;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.15);
|
||||
background: #fff;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-height: 250px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
z-index: 100;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
padding: 4px 8px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.dropdown-item.selected {
|
||||
background-color: #1e90ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dropdown-item.custom-input input {
|
||||
width: 100%;
|
||||
max-width: 200px;
|
||||
box-sizing: border-box;
|
||||
padding: 3px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -60,6 +60,12 @@ table td, .table .td {
|
||||
|
||||
function cbi_t_switch(section, tab) {
|
||||
if( cbi_t[section] && cbi_t[section][tab] ) {
|
||||
//在切换选项卡之前,先取消当前激活选项卡的全选状态
|
||||
var btn = document.getElementById("select_all_btn");
|
||||
if (btn) {
|
||||
dechecked_all_node(btn);
|
||||
}
|
||||
|
||||
var o = cbi_t[section][tab];
|
||||
var h = document.getElementById('tab.' + section);
|
||||
for( var tid in cbi_t[section] ) {
|
||||
@@ -176,7 +182,9 @@ table td, .table .td {
|
||||
}
|
||||
|
||||
function checked_all_node(btn) {
|
||||
var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select");
|
||||
var visibleContainer = document.querySelector('#cbi-passwall-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-passwall-nodes > .cbi-tabcontainer[style*="display: block"]');
|
||||
if (!visibleContainer) return;
|
||||
var doms = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (doms && doms.length > 0) {
|
||||
for (var i = 0 ; i < doms.length; i++) {
|
||||
doms[i].checked = true;
|
||||
@@ -187,7 +195,9 @@ table td, .table .td {
|
||||
}
|
||||
|
||||
function dechecked_all_node(btn) {
|
||||
var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select");
|
||||
var visibleContainer = document.querySelector('#cbi-passwall-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-passwall-nodes > .cbi-tabcontainer[style*="display: block"]');
|
||||
if (!visibleContainer) return;
|
||||
var doms = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (doms && doms.length > 0) {
|
||||
for (var i = 0 ; i < doms.length; i++) {
|
||||
doms[i].checked = false;
|
||||
@@ -199,7 +209,9 @@ table td, .table .td {
|
||||
|
||||
function delete_select_nodes() {
|
||||
var ids = [];
|
||||
var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select");
|
||||
var visibleContainer = document.querySelector('#cbi-passwall-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-passwall-nodes > .cbi-tabcontainer[style*="display: block"]');
|
||||
if (!visibleContainer) return;
|
||||
var doms = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (doms && doms.length > 0) {
|
||||
for (var i = 0 ; i < doms.length; i++) {
|
||||
if (doms[i].checked) {
|
||||
@@ -555,8 +567,8 @@ table td, .table .td {
|
||||
var group_nodes = {}
|
||||
for (let i = 0; i < node_list.length; i++) {
|
||||
let _node = node_list[i]
|
||||
if (!_node.group) {
|
||||
_node.group = "<%:default%>"
|
||||
if (!_node.group || _node.group === "") {
|
||||
_node.group = "default"
|
||||
}
|
||||
if (!group_nodes[_node.group]) {
|
||||
group_nodes[_node.group] = []
|
||||
@@ -618,10 +630,15 @@ table td, .table .td {
|
||||
_html = _html.split("{{node-tr}}").join(node_tr_html);
|
||||
table_html = _html;
|
||||
}
|
||||
|
||||
var group_name = group
|
||||
if (group === "default") {
|
||||
group_name = "<%:default%>"
|
||||
}
|
||||
|
||||
tab_ul_li_html +=
|
||||
'<li id="tab.passwall.nodes.' + group + '" class="cbi-tab">' +
|
||||
'<a onclick="this.blur(); return cbi_t_switch(\'passwall.nodes\', \'' + group + '\')" href="<%=REQUEST_URI%>?tab.passwall.nodes=' + group + '">' + group + " | " + "<font style='color: red'>" + group_nodes[group].length + '</font></a>' +
|
||||
'<a onclick="this.blur(); return cbi_t_switch(\'passwall.nodes\', \'' + group + '\')" href="<%=REQUEST_URI%>?tab.passwall.nodes=' + group + '">' + group_name + " | " + "<font style='color: red'>" + group_nodes[group].length + '</font></a>' +
|
||||
'</li>'
|
||||
tab_content_html +=
|
||||
'<div class="cbi-tabcontainer" id="container.passwall.nodes.' + group + '" style="display: none;">' +
|
||||
|
||||
@@ -990,6 +990,7 @@ add_firewall_rule() {
|
||||
$ipt_m -N PSW
|
||||
$ipt_m -A PSW $(dst $IPSET_LAN) -j RETURN
|
||||
$ipt_m -A PSW $(dst $IPSET_VPS) -j RETURN
|
||||
$ipt_m -A PSW -m conntrack --ctdir REPLY -j RETURN
|
||||
|
||||
[ ! -z "${WAN_IP}" ] && {
|
||||
$ipt_m -A PSW $(comment "WAN_IP_RETURN") -d "${WAN_IP}" -j RETURN
|
||||
|
||||
@@ -1734,7 +1734,9 @@ local function update_node(manual)
|
||||
if type(vvv) == "table" and next(vvv) ~= nil then
|
||||
uci:set_list(appname, cfgid, kkk, vvv)
|
||||
else
|
||||
uci:set(appname, cfgid, kkk, vvv)
|
||||
if kkk ~= "group" or vvv ~= "default" then
|
||||
uci:set(appname, cfgid, kkk, vvv)
|
||||
end
|
||||
-- sing-box 域名解析策略
|
||||
if kkk == "type" and vvv == "sing-box" then
|
||||
uci:set(appname, cfgid, "domain_strategy", domain_strategy_node)
|
||||
@@ -2031,7 +2033,7 @@ if arg[1] then
|
||||
local f = assert(io.open("/tmp/links.conf", 'r'))
|
||||
local raw = f:read('*all')
|
||||
f:close()
|
||||
parse_link(raw, "1", "导入")
|
||||
parse_link(raw, "1", arg[2])
|
||||
update_node(1)
|
||||
luci.sys.call("rm -f /tmp/links.conf")
|
||||
elseif arg[1] == "truncate" then
|
||||
|
||||
@@ -23,10 +23,12 @@ o.default = translate("Remarks")
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "group", translate("Group Name"))
|
||||
o.default = ""
|
||||
o:value("", translate("default"))
|
||||
local groups = {}
|
||||
m.uci:foreach(appname, "nodes", function(s)
|
||||
if s[".name"] ~= arg[1] then
|
||||
if s.group then
|
||||
if s.group and s.group ~= "" then
|
||||
groups[s.group] = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -107,7 +107,7 @@ local api = require "luci.passwall.api"
|
||||
<input class="btn cbi-button cbi-button-add" type="button" onclick="open_add_link_div()" value="<%:Add the node via the link%>" />
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" onclick="clear_all_nodes()" value="<%:Clear all nodes%>" />
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" onclick="delete_select_nodes()" value="<%:Delete select nodes%>" />
|
||||
<input class="btn cbi-button" type="button" onclick="checked_all_node(this)" value="<%:Select all%>" />
|
||||
<input class="btn cbi-button" type="button" id="select_all_btn" onclick="checked_all_node(this)" value="<%:Select all%>" />
|
||||
<input class="btn cbi-button cbi-button-apply" type="submit" name="cbi.apply" value="<%:Save & Apply%>" />
|
||||
<input class="btn cbi-button cbi-button-save" type="submit" name="cbi.save" value="<%:Save%>" />
|
||||
<input class="btn cbi-button cbi-button-reset" type="button" value="<%:Reset%>" onclick="location.href='<%=REQUEST_URI%>'" />
|
||||
|
||||
@@ -60,6 +60,12 @@ table td, .table .td {
|
||||
|
||||
function cbi_t_switch(section, tab) {
|
||||
if( cbi_t[section] && cbi_t[section][tab] ) {
|
||||
//在切换选项卡之前,先取消当前激活选项卡的全选状态
|
||||
var btn = document.getElementById("select_all_btn");
|
||||
if (btn) {
|
||||
dechecked_all_node(btn);
|
||||
}
|
||||
|
||||
var o = cbi_t[section][tab];
|
||||
var h = document.getElementById('tab.' + section);
|
||||
for( var tid in cbi_t[section] ) {
|
||||
@@ -176,7 +182,9 @@ table td, .table .td {
|
||||
}
|
||||
|
||||
function checked_all_node(btn) {
|
||||
var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select");
|
||||
var visibleContainer = document.querySelector('#cbi-passwall-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-passwall-nodes > .cbi-tabcontainer[style*="display: block"]');
|
||||
if (!visibleContainer) return;
|
||||
var doms = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (doms && doms.length > 0) {
|
||||
for (var i = 0 ; i < doms.length; i++) {
|
||||
doms[i].checked = true;
|
||||
@@ -187,7 +195,9 @@ table td, .table .td {
|
||||
}
|
||||
|
||||
function dechecked_all_node(btn) {
|
||||
var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select");
|
||||
var visibleContainer = document.querySelector('#cbi-passwall-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-passwall-nodes > .cbi-tabcontainer[style*="display: block"]');
|
||||
if (!visibleContainer) return;
|
||||
var doms = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (doms && doms.length > 0) {
|
||||
for (var i = 0 ; i < doms.length; i++) {
|
||||
doms[i].checked = false;
|
||||
@@ -199,7 +209,9 @@ table td, .table .td {
|
||||
|
||||
function delete_select_nodes() {
|
||||
var ids = [];
|
||||
var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select");
|
||||
var visibleContainer = document.querySelector('#cbi-passwall-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-passwall-nodes > .cbi-tabcontainer[style*="display: block"]');
|
||||
if (!visibleContainer) return;
|
||||
var doms = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (doms && doms.length > 0) {
|
||||
for (var i = 0 ; i < doms.length; i++) {
|
||||
if (doms[i].checked) {
|
||||
@@ -555,7 +567,7 @@ table td, .table .td {
|
||||
var group_nodes = {}
|
||||
for (let i = 0; i < node_list.length; i++) {
|
||||
let _node = node_list[i]
|
||||
if (!_node.group) {
|
||||
if (!_node.group || _node.group === "") {
|
||||
_node.group = "<%:default%>"
|
||||
}
|
||||
if (!group_nodes[_node.group]) {
|
||||
|
||||
@@ -990,6 +990,7 @@ add_firewall_rule() {
|
||||
$ipt_m -N PSW
|
||||
$ipt_m -A PSW $(dst $IPSET_LAN) -j RETURN
|
||||
$ipt_m -A PSW $(dst $IPSET_VPS) -j RETURN
|
||||
$ipt_m -A PSW -m conntrack --ctdir REPLY -j RETURN
|
||||
|
||||
[ ! -z "${WAN_IP}" ] && {
|
||||
$ipt_m -A PSW $(comment "WAN_IP_RETURN") -d "${WAN_IP}" -j RETURN
|
||||
@@ -1052,8 +1053,8 @@ add_firewall_rule() {
|
||||
$ip6t_m -N PSW_RULE
|
||||
$ip6t_m -A PSW_RULE -j CONNMARK --restore-mark
|
||||
$ip6t_m -A PSW_RULE -m mark --mark 1 -j RETURN
|
||||
$ip6t_m -A PSW2_RULE -p tcp -m tcp --syn -j MARK --set-xmark 1
|
||||
$ip6t_m -A PSW2_RULE -p udp -m conntrack --ctstate NEW,RELATED -j MARK --set-xmark 1
|
||||
$ip6t_m -A PSW_RULE -p tcp -m tcp --syn -j MARK --set-xmark 1
|
||||
$ip6t_m -A PSW_RULE -p udp -m conntrack --ctstate NEW,RELATED -j MARK --set-xmark 1
|
||||
$ip6t_m -A PSW_RULE -j CONNMARK --save-mark
|
||||
|
||||
$ip6t_m -N PSW
|
||||
|
||||
@@ -21,13 +21,13 @@ define Download/geoip
|
||||
HASH:=2445b44d9ae3ab9a867c9d1e0e244646c4c378622e14b9afaf3658ecf46a40b9
|
||||
endef
|
||||
|
||||
GEOSITE_VER:=20251101070148
|
||||
GEOSITE_VER:=20251106100932
|
||||
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
|
||||
define Download/geosite
|
||||
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
|
||||
URL_FILE:=dlc.dat
|
||||
FILE:=$(GEOSITE_FILE)
|
||||
HASH:=434469c8a61ec36d2f3e1ddd6ff65c594bf76ebcb4e472705695b6d4ab51ba47
|
||||
HASH:=1f18e36e19f6c08fd44de1744b8390a816b198dbab4fcf7d6815a934f415dceb
|
||||
endef
|
||||
|
||||
GEOSITE_IRAN_VER:=202511030041
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=v2rayA
|
||||
PKG_VERSION:=2.2.7.3
|
||||
PKG_VERSION:=2.2.7.4
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/v2rayA/v2rayA/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=4b36275dff287d8cf03ee8fa5331d731593f35020459a8ea0ff925e8496a52cf
|
||||
PKG_HASH:=801a5488493cef8c2603d596e5982d226c07ad8f4a2969d942922be79169ec29
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/service
|
||||
|
||||
PKG_LICENSE:=AGPL-3.0-only
|
||||
@@ -60,7 +60,7 @@ define Download/v2raya-web
|
||||
URL:=https://github.com/v2rayA/v2rayA/releases/download/v$(PKG_VERSION)/
|
||||
URL_FILE:=web.tar.gz
|
||||
FILE:=$(WEB_FILE)
|
||||
HASH:=99e789fa7cbfe9f6bc49afa8365556dff6d6c664e6136b045dd7f43322d0de7f
|
||||
HASH:=985b083a75b7b34ea9c5151cbc096f6f44fa369a807fea85b435fed5229dae65
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
|
||||
+6
-4
@@ -4,6 +4,7 @@ on:
|
||||
inputs:
|
||||
tag:
|
||||
type: string
|
||||
description: 'The tag to release'
|
||||
required: true
|
||||
jobs:
|
||||
Build_v2rayA_Web:
|
||||
@@ -595,15 +596,16 @@ jobs:
|
||||
- name: Download v2rayA binary for checksum
|
||||
run: |
|
||||
mkdir v2raya_linux
|
||||
for arch in x86 x64 longarch64 armv7 arm64; do
|
||||
for arch in x86 x64 loongarch64 armv7 arm64; do
|
||||
curl -L https://github.com/v2rayA/v2rayA/releases/download/v${VERSION}/v2raya_linux_${arch}_${VERSION} -o v2raya_linux/v2raya_linux_${arch}_${VERSION}
|
||||
chmod +x v2raya_linux/v2raya_linux_${arch}_${VERSION}
|
||||
done
|
||||
- name: Set Path
|
||||
- name: List Files and Install expect
|
||||
run: |
|
||||
sudo apt update -y && sudo apt install -y expect >/dev/null
|
||||
ls -l v2raya_linux
|
||||
echo "P_DIR=$(pwd)/v2raya_linux" >> $GITHUB_ENV
|
||||
echo "P_DIR=$(pwd)/v2raya_linux" >> $GITHUB_OUTPUT
|
||||
echo "P_DIR=$(pwd)" >> $GITHUB_ENV
|
||||
echo "P_DIR=$(pwd)" >> $GITHUB_OUTPUT
|
||||
id: set_path
|
||||
- name: Release to AUR
|
||||
env:
|
||||
|
||||
+39
-107
@@ -3,66 +3,37 @@
|
||||
<b-navbar ref="navs" fixed-top shadow type="is-light">
|
||||
<template slot="brand">
|
||||
<b-navbar-item href="/">
|
||||
<img
|
||||
src="@/assets/img/logo2.png"
|
||||
alt="v2rayA"
|
||||
class="logo no-select"
|
||||
/>
|
||||
<img src="@/assets/img/logo2.png" alt="v2rayA" class="logo no-select" />
|
||||
</b-navbar-item>
|
||||
<b-navbar-item tag="div">
|
||||
<b-tag
|
||||
id="statusTag"
|
||||
class="pointerTag"
|
||||
:type="statusMap[runningState.running]"
|
||||
@mouseenter.native="handleOnStatusMouseEnter"
|
||||
@mouseleave.native="handleOnStatusMouseLeave"
|
||||
@click.native="handleClickStatus"
|
||||
>{{ coverStatusText ? coverStatusText : runningState.running }}
|
||||
<b-tag id="statusTag" class="pointerTag" :type="statusMap[runningState.running]"
|
||||
@mouseenter.native="handleOnStatusMouseEnter" @mouseleave.native="handleOnStatusMouseLeave"
|
||||
@click.native="handleClickStatus">{{ coverStatusText ? coverStatusText : runningState.running }}
|
||||
</b-tag>
|
||||
</b-navbar-item>
|
||||
<b-navbar-item tag="div">
|
||||
<b-dropdown
|
||||
v-if="updateOutboundDropdown"
|
||||
:triggers="isMobile ? ['click'] : ['click', 'hover']"
|
||||
aria-role="list"
|
||||
:close-on-click="false"
|
||||
@mouseenter.native="handleOutboundDropdownActiveChange"
|
||||
@active-change="handleOutboundDropdownActiveChange"
|
||||
>
|
||||
<b-dropdown v-if="updateOutboundDropdown" :triggers="isMobile ? ['click'] : ['click', 'hover']"
|
||||
aria-role="list" :close-on-click="false" @mouseenter.native="handleOutboundDropdownActiveChange"
|
||||
@active-change="handleOutboundDropdownActiveChange">
|
||||
<template #trigger>
|
||||
<b-tag class="pointerTag" type="is-info" icon-right="menu-down"
|
||||
>{{ outboundName.toUpperCase() }}
|
||||
<b-tag class="pointerTag" type="is-info" icon-right="menu-down">{{ outboundName.toUpperCase() }}
|
||||
</b-tag>
|
||||
</template>
|
||||
|
||||
<b-dropdown-item
|
||||
v-for="outbound in outbounds"
|
||||
:key="outbound"
|
||||
aria-role="listitem"
|
||||
<b-dropdown-item v-for="outbound in outbounds" :key="outbound" aria-role="listitem"
|
||||
class="is-flex padding-right-1rem justify-content-space-between outbound-dropdown"
|
||||
@mouseenter.native="handleOnOutboundMouseEnter(outbound)"
|
||||
@mouseleave.native="handleOnOutboundMouseLeave"
|
||||
@click="outboundName = outbound"
|
||||
><p class="is-relative is-fullwidth">
|
||||
@mouseenter.native="handleOnOutboundMouseEnter(outbound)" @mouseleave.native="handleOnOutboundMouseLeave"
|
||||
@click="outboundName = outbound">
|
||||
<p class="is-relative is-fullwidth">
|
||||
<span>{{ outboundNameDecorator(outbound) }}</span>
|
||||
<span>
|
||||
<i
|
||||
v-show="isMobile || outboundDropdownHover[outbound]"
|
||||
class="iconfont icon-setting outbound-setting"
|
||||
@click="handleClickOutboundSetting($event, outbound)"
|
||||
></i
|
||||
></span></p
|
||||
></b-dropdown-item>
|
||||
<b-dropdown-item
|
||||
aria-role="listitem"
|
||||
class="is-flex padding-right-1rem"
|
||||
separator
|
||||
></b-dropdown-item>
|
||||
<b-dropdown-item
|
||||
aria-role="listitem"
|
||||
class="is-flex padding-right-1rem"
|
||||
@click="handleAddOutbound"
|
||||
>{{ $t("operations.addOutbound") }}
|
||||
<i v-show="isMobile || outboundDropdownHover[outbound]" class="iconfont icon-setting outbound-setting"
|
||||
@click="handleClickOutboundSetting($event, outbound)"></i></span>
|
||||
</p>
|
||||
</b-dropdown-item>
|
||||
<b-dropdown-item aria-role="listitem" class="is-flex padding-right-1rem" separator></b-dropdown-item>
|
||||
<b-dropdown-item aria-role="listitem" class="is-flex padding-right-1rem" @click="handleAddOutbound">{{
|
||||
$t("operations.addOutbound") }}
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
</b-navbar-item>
|
||||
@@ -86,74 +57,34 @@
|
||||
<i class="iconfont icon-info" style="font-size: 1.25em"></i>
|
||||
{{ $t("common.log") }}
|
||||
</b-navbar-item>
|
||||
<b-dropdown
|
||||
position="is-bottom-left"
|
||||
aria-role="menu"
|
||||
style="margin-right: 10px"
|
||||
class="menudropdown"
|
||||
>
|
||||
<b-dropdown position="is-bottom-left" aria-role="menu" style="margin-right: 10px" class="menudropdown">
|
||||
<a slot="trigger" class="navbar-item" role="button">
|
||||
<span class="no-select">{{ username }}</span>
|
||||
<i
|
||||
class="iconfont icon-caret-down"
|
||||
style="position: relative; top: 1px; left: 2px"
|
||||
></i>
|
||||
<i class="iconfont icon-caret-down" style="position: relative; top: 1px; left: 2px"></i>
|
||||
</a>
|
||||
<b-dropdown-item
|
||||
custom
|
||||
aria-role="menuitem"
|
||||
v-html="$t('common.loggedAs', { username })"
|
||||
>
|
||||
<b-dropdown-item custom aria-role="menuitem" v-html="$t('common.loggedAs', { username })">
|
||||
</b-dropdown-item>
|
||||
<b-dropdown-item
|
||||
custom
|
||||
aria-role="menuitem"
|
||||
class="is-flex"
|
||||
style="
|
||||
<b-dropdown-item custom aria-role="menuitem" class="is-flex" style="
|
||||
box-sizing: content-box;
|
||||
height: 16px;
|
||||
width: 60px;
|
||||
justify-content: space-between;
|
||||
"
|
||||
>
|
||||
<img
|
||||
v-for="lang of langs"
|
||||
:key="lang.flag"
|
||||
:src="require(`@/assets/img/flags/flag_${lang.flag}.svg`)"
|
||||
:alt="lang.alt"
|
||||
style="height: 100%; flex-shrink: 0; cursor: pointer"
|
||||
@click="handleClickLang(lang.flag)"
|
||||
/>
|
||||
">
|
||||
<img v-for="lang of langs" :key="lang.flag" :src="require(`@/assets/img/flags/flag_${lang.flag}.svg`)"
|
||||
:alt="lang.alt" style="height: 100%; flex-shrink: 0; cursor: pointer"
|
||||
@click="handleClickLang(lang.flag)" />
|
||||
</b-dropdown-item>
|
||||
<hr class="dropdown-divider" />
|
||||
<b-dropdown-item
|
||||
value="logout"
|
||||
aria-role="menuitem"
|
||||
class="no-select"
|
||||
@click="handleClickLogout"
|
||||
>
|
||||
<i
|
||||
class="iconfont icon-logout"
|
||||
style="position: relative; top: 1px"
|
||||
></i>
|
||||
<b-dropdown-item value="logout" aria-role="menuitem" class="no-select" @click="handleClickLogout">
|
||||
<i class="iconfont icon-logout" style="position: relative; top: 1px"></i>
|
||||
{{ $t("operations.logout") }}
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
</template>
|
||||
</b-navbar>
|
||||
<node
|
||||
v-model="runningState"
|
||||
:outbound="outboundName"
|
||||
:observatory="observatory"
|
||||
/>
|
||||
<b-modal
|
||||
:active.sync="showCustomPorts"
|
||||
has-modal-card
|
||||
trap-focus
|
||||
aria-role="dialog"
|
||||
aria-modal
|
||||
class="modal-custom-ports"
|
||||
>
|
||||
<node v-model="runningState" :outbound="outboundName" :observatory="observatory" />
|
||||
<b-modal :active.sync="showCustomPorts" has-modal-card trap-focus aria-role="dialog" aria-modal
|
||||
class="modal-custom-ports">
|
||||
<ModalCustomAddress @close="showCustomPorts = false" />
|
||||
</b-modal>
|
||||
<div id="login"></div>
|
||||
@@ -297,9 +228,8 @@ export default {
|
||||
if (u.protocol === "https") {
|
||||
protocol = "wss";
|
||||
}
|
||||
url = `${protocol}://${u.host}:${
|
||||
u.port
|
||||
}/api/message?Authorization=${encodeURIComponent(localStorage["token"])}`;
|
||||
url = `${protocol}://${u.host}:${u.port
|
||||
}/api/message?Authorization=${encodeURIComponent(localStorage["token"])}`;
|
||||
if (this.ws) {
|
||||
// console.log("ws close");
|
||||
this.ws.close();
|
||||
@@ -343,9 +273,8 @@ export default {
|
||||
if (
|
||||
typeof this.runningState.outboundToServerName[outbound] === "number"
|
||||
) {
|
||||
return `${outbound} - ${this.$t("common.loadBalance")} (${
|
||||
this.runningState.outboundToServerName[outbound]
|
||||
})`;
|
||||
return `${outbound} - ${this.$t("common.loadBalance")} (${this.runningState.outboundToServerName[outbound]
|
||||
})`;
|
||||
} else {
|
||||
return `${outbound} - ${this.runningState.outboundToServerName[outbound]}`;
|
||||
}
|
||||
@@ -519,6 +448,7 @@ export default {
|
||||
handleClickStatus() {
|
||||
if (this.runningState.running === this.$t("common.notRunning")) {
|
||||
let cancel;
|
||||
let loading = this.$buefy.loading.open();
|
||||
waitingConnected(
|
||||
this.$axios({
|
||||
url: apiRoot + "/v2ray",
|
||||
@@ -541,6 +471,8 @@ export default {
|
||||
queue: false,
|
||||
});
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.close();
|
||||
}),
|
||||
3 * 1000,
|
||||
cancel
|
||||
|
||||
@@ -4,52 +4,26 @@
|
||||
<p class="modal-card-title">{{ $t("common.setting") }}</p>
|
||||
</header>
|
||||
<section class="modal-card-body rules">
|
||||
<b-field
|
||||
label="GFWList"
|
||||
horizontal
|
||||
custom-class="modal-setting-label"
|
||||
style="position: relative"
|
||||
><span>{{ $t("common.latest") }}:</span>
|
||||
<a
|
||||
href="https://github.com/v2rayA/dist-v2ray-rules-dat/releases"
|
||||
target="_blank"
|
||||
class="is-link"
|
||||
>{{ remoteGFWListVersion }}</a
|
||||
><span>{{ $t("common.local") }}:</span>
|
||||
<b-tooltip
|
||||
v-if="dayjs(localGFWListVersion).isAfter(dayjs(remoteGFWListVersion))"
|
||||
:label="$t('setting.messages.gfwlist')"
|
||||
position="is-bottom"
|
||||
type="is-danger"
|
||||
dashed
|
||||
multilined
|
||||
animated
|
||||
>
|
||||
<b-field label="GFWList" horizontal custom-class="modal-setting-label" style="position: relative"><span>{{
|
||||
$t("common.latest") }}:</span>
|
||||
<a href="https://github.com/v2rayA/dist-v2ray-rules-dat/releases" target="_blank" class="is-link">{{
|
||||
remoteGFWListVersion }}</a><span>{{ $t("common.local") }}:</span>
|
||||
<b-tooltip v-if="dayjs(localGFWListVersion).isAfter(dayjs(remoteGFWListVersion))"
|
||||
:label="$t('setting.messages.gfwlist')" position="is-bottom" type="is-danger" dashed multilined animated>
|
||||
{{ localGFWListVersion ? localGFWListVersion : $t("common.none") }}
|
||||
</b-tooltip>
|
||||
<span v-else>{{ localGFWListVersion ? localGFWListVersion : $t("common.none") }}</span>
|
||||
<b-button
|
||||
size="is-small"
|
||||
style="position: relative; top: -2px; text-decoration: none; font-weight: bold"
|
||||
@click="handleClickUpdateGFWList"
|
||||
>{{ $t("operations.update") }}
|
||||
<b-button size="is-small" style="position: relative; top: -2px; text-decoration: none; font-weight: bold"
|
||||
@click="handleClickUpdateGFWList">{{ $t("operations.update") }}
|
||||
</b-button>
|
||||
</b-field>
|
||||
<hr class="dropdown-divider" style="margin: 1.25rem 0 1.25rem" />
|
||||
<b-field label-position="on-border" class="with-icon-alert">
|
||||
<template slot="label">
|
||||
{{ $t("setting.transparentProxy") }}
|
||||
<b-tooltip
|
||||
type="is-dark"
|
||||
:label="$t('setting.messages.transparentProxy')"
|
||||
multilined
|
||||
position="is-right"
|
||||
>
|
||||
<b-icon
|
||||
size="is-small"
|
||||
icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal"
|
||||
/>
|
||||
<b-tooltip type="is-dark" :label="$t('setting.messages.transparentProxy')" multilined position="is-right">
|
||||
<b-icon size="is-small" icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal" />
|
||||
</b-tooltip>
|
||||
</template>
|
||||
<b-select v-model="transparent" expanded>
|
||||
@@ -69,59 +43,48 @@
|
||||
{{ $t("setting.options.sameAsPacMode") }}
|
||||
</option>
|
||||
</b-select>
|
||||
<b-checkbox-button
|
||||
v-show="!lite"
|
||||
v-model="ipforward"
|
||||
:native-value="true"
|
||||
style="position: relative; left: -1px"
|
||||
>{{ $t("setting.ipForwardOn") }}
|
||||
<b-checkbox-button v-show="!lite" v-model="ipforward" :native-value="true"
|
||||
style="position: relative; left: -1px">{{
|
||||
$t("setting.ipForwardOn") }}
|
||||
</b-checkbox-button>
|
||||
<b-checkbox-button
|
||||
v-model="portSharing"
|
||||
:native-value="true"
|
||||
style="position: relative; left: -1px"
|
||||
>{{ $t("setting.portSharingOn") }}
|
||||
<b-checkbox-button v-model="portSharing" :native-value="true" style="position: relative; left: -1px">{{
|
||||
$t("setting.portSharingOn") }}
|
||||
</b-checkbox-button>
|
||||
</b-field>
|
||||
|
||||
<b-field v-show="transparent !== 'close'" label-position="on-border">
|
||||
<template slot="label">
|
||||
{{ $t("setting.transparentType") }}
|
||||
<b-tooltip
|
||||
type="is-dark"
|
||||
multilined
|
||||
:label="$t('setting.messages.transparentType')"
|
||||
position="is-right"
|
||||
>
|
||||
<b-icon
|
||||
size="is-small"
|
||||
icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal"
|
||||
/>
|
||||
<b-tooltip type="is-dark" multilined :label="$t('setting.messages.transparentType')" position="is-right">
|
||||
<b-icon size="is-small" icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal" />
|
||||
</b-tooltip>
|
||||
</template>
|
||||
<b-select v-model="transparentType" expanded class="left-border">
|
||||
<b-select v-model="transparentType" expanded>
|
||||
<option v-show="!lite" value="redirect">redirect</option>
|
||||
<option v-show="!lite" value="tproxy">tproxy</option>
|
||||
<option v-show="!lite" value="gvisor_tun">gvisor tun</option>
|
||||
<option v-show="!lite" value="system_tun">system tun</option>
|
||||
<option value="system_proxy">system proxy</option>
|
||||
</b-select>
|
||||
|
||||
<template v-if="transparentType == 'tproxy'">
|
||||
<b-button style="
|
||||
margin-left: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
" outlined @click="handleClickTproxyWhiteIpGroups">{{ $t("operations.tproxyWhiteIpGroups") }}
|
||||
</b-button>
|
||||
</template>
|
||||
</b-field>
|
||||
|
||||
<b-field label-position="on-border">
|
||||
<template slot="label">
|
||||
{{ $t("setting.pacMode") }}
|
||||
<b-tooltip
|
||||
type="is-dark"
|
||||
:label="$t('setting.messages.pacMode')"
|
||||
multilined
|
||||
position="is-right"
|
||||
>
|
||||
<b-icon
|
||||
size="is-small"
|
||||
icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal"
|
||||
/>
|
||||
<b-tooltip type="is-dark" :label="$t('setting.messages.pacMode')" multilined position="is-right">
|
||||
<b-icon size="is-small" icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal" />
|
||||
</b-tooltip>
|
||||
</template>
|
||||
<b-select v-model="pacMode" expanded style="flex-shrink: 0">
|
||||
@@ -135,30 +98,21 @@
|
||||
<option value="routingA">RoutingA</option>
|
||||
</b-select>
|
||||
<template v-if="pacMode === 'custom'">
|
||||
<b-button
|
||||
type="is-primary"
|
||||
style="
|
||||
<b-button type="is-primary" style="
|
||||
margin-left: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
"
|
||||
outlined
|
||||
@click="handleClickConfigurePac"
|
||||
>{{ $t("operations.configure") }}
|
||||
" outlined @click="handleClickConfigurePac">{{ $t("operations.configure") }}
|
||||
</b-button>
|
||||
</template>
|
||||
<template v-if="pacMode === 'routingA'">
|
||||
<b-button
|
||||
style="
|
||||
<b-button style="
|
||||
margin-left: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
"
|
||||
outlined
|
||||
@click="handleClickConfigureRoutingA"
|
||||
>{{ $t("operations.configure") }}
|
||||
" outlined @click="handleClickConfigureRoutingA">{{ $t("operations.configure") }}
|
||||
</b-button>
|
||||
</template>
|
||||
<p></p>
|
||||
@@ -166,17 +120,9 @@
|
||||
<b-field label-position="on-border">
|
||||
<template slot="label">
|
||||
{{ $t("setting.preventDnsSpoofing") }}
|
||||
<b-tooltip
|
||||
type="is-dark"
|
||||
:label="$t('setting.messages.preventDnsSpoofing')"
|
||||
multilined
|
||||
position="is-right"
|
||||
>
|
||||
<b-icon
|
||||
size="is-small"
|
||||
icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal"
|
||||
/>
|
||||
<b-tooltip type="is-dark" :label="$t('setting.messages.preventDnsSpoofing')" multilined position="is-right">
|
||||
<b-icon size="is-small" icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal" />
|
||||
</b-tooltip>
|
||||
</template>
|
||||
<b-select v-model="antipollution" expanded class="left-border">
|
||||
@@ -190,14 +136,10 @@
|
||||
<option value="doh">{{ $t("setting.options.doh") }}</option>
|
||||
<option value="advanced">{{ $t("setting.options.advanced") }}</option>
|
||||
</b-select>
|
||||
<b-button
|
||||
v-if="antipollution === 'advanced'"
|
||||
:class="{
|
||||
'right-extra-button': antipollution === 'closed',
|
||||
'no-border-radius': antipollution !== 'closed',
|
||||
}"
|
||||
@click="handleClickDnsSetting"
|
||||
>
|
||||
<b-button v-if="antipollution === 'advanced'" :class="{
|
||||
'right-extra-button': antipollution === 'closed',
|
||||
'no-border-radius': antipollution !== 'closed',
|
||||
}" @click="handleClickDnsSetting">
|
||||
{{ $t("operations.configure") }}
|
||||
</b-button>
|
||||
<p></p>
|
||||
@@ -205,17 +147,9 @@
|
||||
<b-field v-show="showSpecialMode" label-position="on-border">
|
||||
<template slot="label">
|
||||
{{ $t("setting.specialMode") }}
|
||||
<b-tooltip
|
||||
type="is-dark"
|
||||
multilined
|
||||
:label="$t('setting.messages.specialMode')"
|
||||
position="is-right"
|
||||
>
|
||||
<b-icon
|
||||
size="is-small"
|
||||
icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal"
|
||||
/>
|
||||
<b-tooltip type="is-dark" multilined :label="$t('setting.messages.specialMode')" position="is-right">
|
||||
<b-icon size="is-small" icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal" />
|
||||
</b-tooltip>
|
||||
</template>
|
||||
<b-select v-model="specialMode" expanded class="left-border">
|
||||
@@ -227,17 +161,9 @@
|
||||
<b-field label-position="on-border">
|
||||
<template slot="label">
|
||||
TCPFastOpen
|
||||
<b-tooltip
|
||||
type="is-dark"
|
||||
:label="$t('setting.messages.tcpFastOpen')"
|
||||
multilined
|
||||
position="is-right"
|
||||
>
|
||||
<b-icon
|
||||
size="is-small"
|
||||
icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal"
|
||||
/>
|
||||
<b-tooltip type="is-dark" :label="$t('setting.messages.tcpFastOpen')" multilined position="is-right">
|
||||
<b-icon size="is-small" icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal" />
|
||||
</b-tooltip>
|
||||
</template>
|
||||
<b-select v-model="tcpFastOpen" expanded>
|
||||
@@ -246,20 +172,13 @@
|
||||
<option value="no">{{ $t("setting.options.off") }}</option>
|
||||
</b-select>
|
||||
</b-field>
|
||||
|
||||
<b-field label-position="on-border">
|
||||
<template slot="label">
|
||||
{{ $t("setting.inboundSniffing") }}
|
||||
<b-tooltip
|
||||
type="is-dark"
|
||||
:label="$t('setting.messages.inboundSniffing')"
|
||||
multilined
|
||||
position="is-right"
|
||||
>
|
||||
<b-icon
|
||||
size="is-small"
|
||||
icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal"
|
||||
/>
|
||||
<b-tooltip type="is-dark" :label="$t('setting.messages.inboundSniffing')" multilined position="is-right">
|
||||
<b-icon size="is-small" icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal" />
|
||||
</b-tooltip>
|
||||
</template>
|
||||
<b-select v-model="inboundSniffing" expanded>
|
||||
@@ -268,58 +187,36 @@
|
||||
<option value="http,tls,quic">Http + TLS + Quic</option>
|
||||
</b-select>
|
||||
<template v-if="inboundSniffing != 'disable'">
|
||||
<b-button
|
||||
type="is-primary"
|
||||
style="
|
||||
<b-button style="
|
||||
margin-left: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
border-radius: 0px;
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
"
|
||||
outlined
|
||||
@click="handleClickDomainsExcluded"
|
||||
>{{ $t("operations.domainsExcluded") }}
|
||||
" outlined @click="handleClickDomainsExcluded">{{ $t("operations.domainsExcluded") }}
|
||||
</b-button>
|
||||
<b-checkbox-button v-model="routeOnly" :native-value="true" style="position: relative; left: -1px;">
|
||||
RouteOnly
|
||||
</b-checkbox-button>
|
||||
</template>
|
||||
</b-field>
|
||||
|
||||
<b-field label-position="on-border" class="with-icon-alert">
|
||||
<template slot="label">
|
||||
{{ $t("setting.mux") }}
|
||||
<b-tooltip
|
||||
type="is-dark"
|
||||
:label="$t('setting.messages.mux')"
|
||||
multilined
|
||||
position="is-right"
|
||||
>
|
||||
<b-icon
|
||||
size="is-small"
|
||||
icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal"
|
||||
/>
|
||||
<b-tooltip type="is-dark" :label="$t('setting.messages.mux')" multilined position="is-right">
|
||||
<b-icon size="is-small" icon=" iconfont icon-help-circle-outline"
|
||||
style="position: relative; top: 2px; right: 3px; font-weight: normal" />
|
||||
</b-tooltip>
|
||||
</template>
|
||||
<b-select v-model="muxOn" expanded style="flex: 1">
|
||||
<option value="no">{{ $t("setting.options.off") }}</option>
|
||||
<option value="yes">{{ $t("setting.options.on") }}</option>
|
||||
</b-select>
|
||||
<cus-b-input
|
||||
v-if="muxOn === 'yes'"
|
||||
ref="muxinput"
|
||||
v-model="mux"
|
||||
:placeholder="$t('setting.concurrency')"
|
||||
custom-class="no-shadow"
|
||||
type="number"
|
||||
min="1"
|
||||
max="1024"
|
||||
validation-icon=" iconfont icon-alert"
|
||||
style="flex: 1"
|
||||
/>
|
||||
<cus-b-input v-if="muxOn === 'yes'" ref="muxinput" v-model="mux" :placeholder="$t('setting.concurrency')"
|
||||
custom-class="no-shadow" type="number" min="1" max="1024" validation-icon=" iconfont icon-alert"
|
||||
style="flex: 1" />
|
||||
</b-field>
|
||||
<b-field
|
||||
v-show="pacMode === 'gfwlist' || transparent === 'gfwlist'"
|
||||
:label="$t('setting.autoUpdateGfwlist')"
|
||||
label-position="on-border"
|
||||
>
|
||||
<b-field v-show="pacMode === 'gfwlist' || transparent === 'gfwlist'" :label="$t('setting.autoUpdateGfwlist')"
|
||||
label-position="on-border">
|
||||
<b-select v-model="pacAutoUpdateMode" expanded>
|
||||
<option value="none">{{ $t("setting.options.off") }}</option>
|
||||
<option value="auto_update">
|
||||
@@ -329,16 +226,9 @@
|
||||
{{ $t("setting.options.updateGfwlistAtIntervals") }}
|
||||
</option>
|
||||
</b-select>
|
||||
<cus-b-input
|
||||
v-if="pacAutoUpdateMode === 'auto_update_at_intervals'"
|
||||
ref="autoUpdatePacInput"
|
||||
v-model="pacAutoUpdateIntervalHour"
|
||||
custom-class="no-shadow"
|
||||
type="number"
|
||||
min="1"
|
||||
validation-icon=" iconfont icon-alert"
|
||||
style="flex: 1"
|
||||
/>
|
||||
<cus-b-input v-if="pacAutoUpdateMode === 'auto_update_at_intervals'" ref="autoUpdatePacInput"
|
||||
v-model="pacAutoUpdateIntervalHour" custom-class="no-shadow" type="number" min="1"
|
||||
validation-icon=" iconfont icon-alert" style="flex: 1" />
|
||||
</b-field>
|
||||
<b-field :label="$t('setting.autoUpdateSub')" label-position="on-border">
|
||||
<b-select v-model="subscriptionAutoUpdateMode" expanded>
|
||||
@@ -350,16 +240,9 @@
|
||||
{{ $t("setting.options.updateSubAtIntervals") }}
|
||||
</option>
|
||||
</b-select>
|
||||
<cus-b-input
|
||||
v-if="subscriptionAutoUpdateMode === 'auto_update_at_intervals'"
|
||||
ref="autoUpdateSubInput"
|
||||
v-model="subscriptionAutoUpdateIntervalHour"
|
||||
custom-class="no-shadow"
|
||||
type="number"
|
||||
min="1"
|
||||
validation-icon=" iconfont icon-alert"
|
||||
style="flex: 1"
|
||||
/>
|
||||
<cus-b-input v-if="subscriptionAutoUpdateMode === 'auto_update_at_intervals'" ref="autoUpdateSubInput"
|
||||
v-model="subscriptionAutoUpdateIntervalHour" custom-class="no-shadow" type="number" min="1"
|
||||
validation-icon=" iconfont icon-alert" style="flex: 1" />
|
||||
</b-field>
|
||||
<b-field :label="$t('setting.preferModeWhenUpdate')" label-position="on-border">
|
||||
<b-select v-model="proxyModeWhenSubscribe" expanded>
|
||||
@@ -376,11 +259,7 @@
|
||||
</b-field>
|
||||
</section>
|
||||
<footer class="modal-card-foot flex-end">
|
||||
<button
|
||||
class="button footer-absolute-left"
|
||||
type="button"
|
||||
@click="$emit('clickPorts')"
|
||||
>
|
||||
<button class="button footer-absolute-left" type="button" @click="$emit('clickPorts')">
|
||||
{{ $t("customAddressPort.title") }}
|
||||
</button>
|
||||
<button class="button" type="button" @click="$parent.close()">
|
||||
@@ -399,6 +278,7 @@ import dayjs from "dayjs";
|
||||
import ModalCustomRouting from "@/components/modalCustomRouting";
|
||||
import ModalCustomRoutingA from "@/components/modalCustomRoutingA";
|
||||
import modalDomainsExcluded from "@/components/modalDomainsExcluded";
|
||||
import modalTproxyWhiteIpGroups from "@/components/modalTproxyWhiteIpGroups";
|
||||
import modalUpdateGfwList from "@/components/modalUpdateGfwList";
|
||||
import CusBInput from "./input/Input.vue";
|
||||
import { parseURL, toInt } from "@/assets/js/utils";
|
||||
@@ -418,12 +298,13 @@ export default {
|
||||
muxOn: "no",
|
||||
mux: "8",
|
||||
transparent: "close",
|
||||
transparentType: "redirect",
|
||||
transparentType: "tproxy",
|
||||
ipforward: false,
|
||||
portSharing: false,
|
||||
dnsForceMode: false,
|
||||
dnsforward: "no",
|
||||
antipollution: "none",
|
||||
routeOnly: false,
|
||||
specialMode: "none",
|
||||
pacAutoUpdateMode: "none",
|
||||
pacAutoUpdateIntervalHour: 0,
|
||||
@@ -493,6 +374,7 @@ export default {
|
||||
});
|
||||
},
|
||||
requestUpdateSetting() {
|
||||
let loading = this.$buefy.loading.open();
|
||||
let cancel;
|
||||
waitingConnected(
|
||||
this.$axios({
|
||||
@@ -515,6 +397,7 @@ export default {
|
||||
transparentType: this.transparentType,
|
||||
ipforward: this.ipforward,
|
||||
portSharing: this.portSharing,
|
||||
routeOnly: this.routeOnly,
|
||||
dnsforward: this.antipollution === "dnsforward" ? "yes" : "no", //版本兼容
|
||||
antipollution: this.antipollution,
|
||||
specialMode: this.specialMode,
|
||||
@@ -539,6 +422,7 @@ export default {
|
||||
// FIXME: tricky
|
||||
this.$parent.$parent.runningState.running = this.$t("common.notRunning");
|
||||
}
|
||||
loading.close();
|
||||
}),
|
||||
3 * 1000,
|
||||
cancel
|
||||
@@ -592,6 +476,14 @@ export default {
|
||||
canCancel: true,
|
||||
});
|
||||
},
|
||||
handleClickTproxyWhiteIpGroups() {
|
||||
this.$buefy.modal.open({
|
||||
parent: this,
|
||||
component: modalTproxyWhiteIpGroups,
|
||||
hasModalCard: true,
|
||||
canCancel: true,
|
||||
});
|
||||
},
|
||||
handleClickDomainsExcluded() {
|
||||
this.$buefy.modal.open({
|
||||
parent: this,
|
||||
@@ -673,15 +565,19 @@ export default {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.left-border select {
|
||||
border-radius: 4px 0 0 4px !important;
|
||||
}
|
||||
|
||||
.right-extra-button {
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
.no-border-radius {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.modal-setting {
|
||||
.b-checkbox.checkbox {
|
||||
margin-right: 0;
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<div class="modal-card" style="max-width: 450px; margin: auto">
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">
|
||||
{{ $t("tproxyWhiteIpGroups.title") }}
|
||||
</p>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<b-message type="is-info" class="after-line-dot5">
|
||||
<p>{{ $t("tproxyWhiteIpGroups.messages.0") }}</p>
|
||||
</b-message>
|
||||
<b-field :label="$t('tproxyWhiteIpGroups.formName1')">
|
||||
<b-select multiple v-model="countryCodes" expanded>
|
||||
<option value="CN">{{ $t("tproxyWhiteIpGroups.cn") }}</option>
|
||||
<option value="PRIVATE">{{ $t("tproxyWhiteIpGroups.private") }}</option>
|
||||
<option value="US">{{ $t("tproxyWhiteIpGroups.us") }}</option>
|
||||
<option value="CLOUDFLARE">{{ $t("tproxyWhiteIpGroups.cloudflare") }}</option>
|
||||
</b-select>
|
||||
</b-field>
|
||||
<b-field :label="$t('tproxyWhiteIpGroups.formName2')">
|
||||
<b-input v-model="customIps" type="textarea" :placeholder="$t('tproxyWhiteIpGroups.formPlaceholder2')"
|
||||
custom-class="full-min-height horizon-scroll code-font" />
|
||||
</b-field>
|
||||
<b-message type="is-warning" class="after-line-dot5">
|
||||
<p>{{ $t("tproxyWhiteIpGroups.messages.1") }}</p>
|
||||
</b-message>
|
||||
</section>
|
||||
<footer class="modal-card-foot flex-end">
|
||||
<button class="button" @click="$emit('close')">
|
||||
{{ $t("operations.cancel") }}
|
||||
</button>
|
||||
<button class="button is-primary" @click="handleClickSubmit">
|
||||
{{ $t("operations.save") }}
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { handleResponse } from "@/assets/js/utils";
|
||||
|
||||
export default {
|
||||
name: "modalTproxyWhiteIpGroups",
|
||||
data: () => ({
|
||||
countryCodes: [],
|
||||
customIps: "",
|
||||
}),
|
||||
created() {
|
||||
this.$axios({
|
||||
url: apiRoot + "/tproxyWhiteIpGroups",
|
||||
}).then((res) => {
|
||||
handleResponse(res, this, () => {
|
||||
if (res.data.data.countryCodes) {
|
||||
this.countryCodes = res.data.data.countryCodes;
|
||||
}
|
||||
if (res.data.data.customIps) {
|
||||
this.customIps = res.data.data.customIps.join("\n");
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
validateCIDRArray(arr) {
|
||||
const ipv4Cidr = /^(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)){3}\/(?:[0-9]|[12]\d|3[0-2])$/;
|
||||
|
||||
const ipv6Cidr = /^(?:(?:[A-Fa-f0-9]{1,4}:){7}[A-Fa-f0-9]{1,4}|(?:[A-Fa-f0-9]{1,4}:){1,7}:|(?:[A-Fa-f0-9]{1,4}:){1,6}:[A-Fa-f0-9]{1,4}|(?:[A-Fa-f0-9]{1,4}:){1,5}(?::[A-Fa-f0-9]{1,4}){1,2}|(?:[A-Fa-f0-9]{1,4}:){1,4}(?::[A-Fa-f0-9]{1,4}){1,3}|(?:[A-Fa-f0-9]{1,4}:){1,3}(?::[A-Fa-f0-9]{1,4}){1,4}|(?:[A-Fa-f0-9]{1,4}:){1,2}(?::[A-Fa-f0-9]{1,4}){1,5}|[A-Fa-f0-9]{1,4}:(?:(?::[A-Fa-f0-9]{1,4}){1,6})|:(?:(?::[A-Fa-f0-9]{1,4}){1,7}|:))\/(?:12[0-8]|1[01]\d|[1-9]?\d)$/;
|
||||
|
||||
const invalid = arr
|
||||
.map(s => (typeof s === 'string' ? s.trim() : ''))
|
||||
.filter(s => s.length === 0 || !(ipv4Cidr.test(s) || ipv6Cidr.test(s)));
|
||||
return invalid.length === 0;
|
||||
},
|
||||
handleClickSubmit() {
|
||||
if (!this.validateCIDRArray(this.customIps.split("\n").filter(line => line.trim() !== ''))) {
|
||||
this.$buefy.toast.open({
|
||||
message: this.$t("tproxyWhiteIpGroups.invalidCustomIps"),
|
||||
type: "is-danger",
|
||||
position: "is-top",
|
||||
queue: false,
|
||||
duration: 10000,
|
||||
});
|
||||
return
|
||||
}
|
||||
this.$axios({
|
||||
url: apiRoot + "/tproxyWhiteIpGroups",
|
||||
method: "put",
|
||||
data: {
|
||||
countryCodes: this.countryCodes.length ? this.countryCodes : ['NONE'],
|
||||
customIps: this.customIps.split("\n").filter(line => line.trim() !== ''),
|
||||
},
|
||||
}).then((res) => {
|
||||
handleResponse(res, this, () => {
|
||||
this.$emit("close");
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -64,6 +64,7 @@ export default {
|
||||
},
|
||||
operations: {
|
||||
name: "Operations",
|
||||
tproxyWhiteIpGroups: "Direct Whitelist IP Groups",
|
||||
update: "Update",
|
||||
autoUpdate: "Auto Update",
|
||||
manualUpdate: "Manual Update",
|
||||
@@ -91,7 +92,7 @@ export default {
|
||||
no: "No",
|
||||
switchSite: "Switch to alternate site",
|
||||
addOutbound: "Add an outbound",
|
||||
domainsExcluded:"Domains Excluded"
|
||||
domainsExcluded: "Domains Excluded"
|
||||
},
|
||||
register: {
|
||||
title: "Create an admin account first",
|
||||
@@ -328,6 +329,21 @@ export default {
|
||||
seconds: "seconds",
|
||||
autoScoll: "Auto Scroll",
|
||||
},
|
||||
tproxyWhiteIpGroups: {
|
||||
title: "White IP Groups",
|
||||
messages: [
|
||||
"The selected IP group will bypass the XRay/V2Ray core and go directly outbound (through Nftables/Iptables). Please ensure your DNS server is reliable and free of contamination so that clients can resolve the correct IPs.",
|
||||
"It's best to use this feature when your system is using Nftables, as iptables may experience performance issues when adding a large number of IPs."
|
||||
],
|
||||
formName1: "Hold down Ctrl to select multiple items.",
|
||||
formName2: "Custom IPs (one per line, standard CIDR format)",
|
||||
formPlaceholder2: "172.30.0.0/16\nfd00:aaaa:bbbb::/48",
|
||||
invalidCustomIps:"Invalid Custom IPs",
|
||||
cn: 'China Mainland',
|
||||
private: 'Private',
|
||||
us: 'United States',
|
||||
cloudflare: 'Cloudflare',
|
||||
},
|
||||
domainsExcluded: {
|
||||
title: "Domains Excluded",
|
||||
messages: [
|
||||
|
||||
@@ -62,6 +62,7 @@ export default {
|
||||
subscription: "订阅",
|
||||
},
|
||||
operations: {
|
||||
tproxyWhiteIpGroups: "直通白名单IP组",
|
||||
name: "操作",
|
||||
update: "更新",
|
||||
autoUpdate: "自动更新",
|
||||
@@ -330,6 +331,22 @@ export default {
|
||||
seconds: "秒",
|
||||
autoScoll: "自动滚动",
|
||||
},
|
||||
|
||||
tproxyWhiteIpGroups: {
|
||||
title: "直通白名单IP组",
|
||||
messages: [
|
||||
"选中的IP组将会不经过XRay/V2Ray核心直接出站(通过Nftables/Iptables直接转发),请确保你的DNS服务器足够可靠无污染能使客户端能解析到正确的IP",
|
||||
"最好系统使用Nftables时使用此功能,Iptables可能在添加大量IP时存在性能问题"
|
||||
],
|
||||
formName1: "按住Ctrl可以多选",
|
||||
formName2: "自定义IP(一行一个,标准CIDR格式)",
|
||||
formPlaceholder2: "172.30.0.0/16\nfd00:dead:beef::/48",
|
||||
invalidCustomIps:"自定义IP格式错误",
|
||||
cn: '中国大陆',
|
||||
private: '私网网段',
|
||||
us: '美国',
|
||||
cloudflare: 'Cloudflare',
|
||||
},
|
||||
domainsExcluded: {
|
||||
title: "排除域名",
|
||||
messages: [
|
||||
|
||||
@@ -1294,6 +1294,7 @@ export default {
|
||||
let cancel;
|
||||
if (!row.connected) {
|
||||
//该节点并未处于连接状态,因此进行连接
|
||||
let loading = this.$buefy.loading.open();
|
||||
waitingConnected(
|
||||
this.$axios({
|
||||
url: apiRoot + "/connection",
|
||||
@@ -1308,6 +1309,7 @@ export default {
|
||||
cancel = c;
|
||||
}),
|
||||
}).then((res) => {
|
||||
loading.close();
|
||||
if (res.data.code === "SUCCESS") {
|
||||
Object.assign(this.runningState, {
|
||||
running: res.data.data.running
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.10
|
||||
// protoc v3.21.12
|
||||
// source: service/common/parseGeoIP/geoip.proto
|
||||
|
||||
package parseGeoIP
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type CIDR struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// IP address, should be either 4 or 16 bytes.
|
||||
Ip []byte `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
|
||||
// Number of leading ones in the network mask.
|
||||
Prefix uint32 `protobuf:"varint,2,opt,name=prefix,proto3" json:"prefix,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *CIDR) Reset() {
|
||||
*x = CIDR{}
|
||||
mi := &file_service_common_parseGeoIP_geoip_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *CIDR) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CIDR) ProtoMessage() {}
|
||||
|
||||
func (x *CIDR) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_service_common_parseGeoIP_geoip_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CIDR.ProtoReflect.Descriptor instead.
|
||||
func (*CIDR) Descriptor() ([]byte, []int) {
|
||||
return file_service_common_parseGeoIP_geoip_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *CIDR) GetIp() []byte {
|
||||
if x != nil {
|
||||
return x.Ip
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *CIDR) GetPrefix() uint32 {
|
||||
if x != nil {
|
||||
return x.Prefix
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GeoIP struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
|
||||
Cidr []*CIDR `protobuf:"bytes,2,rep,name=cidr,proto3" json:"cidr,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GeoIP) Reset() {
|
||||
*x = GeoIP{}
|
||||
mi := &file_service_common_parseGeoIP_geoip_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GeoIP) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GeoIP) ProtoMessage() {}
|
||||
|
||||
func (x *GeoIP) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_service_common_parseGeoIP_geoip_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GeoIP.ProtoReflect.Descriptor instead.
|
||||
func (*GeoIP) Descriptor() ([]byte, []int) {
|
||||
return file_service_common_parseGeoIP_geoip_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *GeoIP) GetCountryCode() string {
|
||||
if x != nil {
|
||||
return x.CountryCode
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GeoIP) GetCidr() []*CIDR {
|
||||
if x != nil {
|
||||
return x.Cidr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GeoIPList struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Entry []*GeoIP `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GeoIPList) Reset() {
|
||||
*x = GeoIPList{}
|
||||
mi := &file_service_common_parseGeoIP_geoip_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GeoIPList) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GeoIPList) ProtoMessage() {}
|
||||
|
||||
func (x *GeoIPList) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_service_common_parseGeoIP_geoip_proto_msgTypes[2]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GeoIPList.ProtoReflect.Descriptor instead.
|
||||
func (*GeoIPList) Descriptor() ([]byte, []int) {
|
||||
return file_service_common_parseGeoIP_geoip_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *GeoIPList) GetEntry() []*GeoIP {
|
||||
if x != nil {
|
||||
return x.Entry
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_service_common_parseGeoIP_geoip_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_service_common_parseGeoIP_geoip_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"%service/common/parseGeoIP/geoip.proto\".\n" +
|
||||
"\x04CIDR\x12\x0e\n" +
|
||||
"\x02ip\x18\x01 \x01(\fR\x02ip\x12\x16\n" +
|
||||
"\x06prefix\x18\x02 \x01(\rR\x06prefix\"E\n" +
|
||||
"\x05GeoIP\x12!\n" +
|
||||
"\fcountry_code\x18\x01 \x01(\tR\vcountryCode\x12\x19\n" +
|
||||
"\x04cidr\x18\x02 \x03(\v2\x05.CIDRR\x04cidr\")\n" +
|
||||
"\tGeoIPList\x12\x1c\n" +
|
||||
"\x05entry\x18\x01 \x03(\v2\x06.GeoIPR\x05entryB\x1dZ\x1b./service/common/parseGeoIPb\x06proto3"
|
||||
|
||||
var (
|
||||
file_service_common_parseGeoIP_geoip_proto_rawDescOnce sync.Once
|
||||
file_service_common_parseGeoIP_geoip_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_service_common_parseGeoIP_geoip_proto_rawDescGZIP() []byte {
|
||||
file_service_common_parseGeoIP_geoip_proto_rawDescOnce.Do(func() {
|
||||
file_service_common_parseGeoIP_geoip_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_service_common_parseGeoIP_geoip_proto_rawDesc), len(file_service_common_parseGeoIP_geoip_proto_rawDesc)))
|
||||
})
|
||||
return file_service_common_parseGeoIP_geoip_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_service_common_parseGeoIP_geoip_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||
var file_service_common_parseGeoIP_geoip_proto_goTypes = []any{
|
||||
(*CIDR)(nil), // 0: CIDR
|
||||
(*GeoIP)(nil), // 1: GeoIP
|
||||
(*GeoIPList)(nil), // 2: GeoIPList
|
||||
}
|
||||
var file_service_common_parseGeoIP_geoip_proto_depIdxs = []int32{
|
||||
0, // 0: GeoIP.cidr:type_name -> CIDR
|
||||
1, // 1: GeoIPList.entry:type_name -> GeoIP
|
||||
2, // [2:2] is the sub-list for method output_type
|
||||
2, // [2:2] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_service_common_parseGeoIP_geoip_proto_init() }
|
||||
func file_service_common_parseGeoIP_geoip_proto_init() {
|
||||
if File_service_common_parseGeoIP_geoip_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_service_common_parseGeoIP_geoip_proto_rawDesc), len(file_service_common_parseGeoIP_geoip_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 3,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_service_common_parseGeoIP_geoip_proto_goTypes,
|
||||
DependencyIndexes: file_service_common_parseGeoIP_geoip_proto_depIdxs,
|
||||
MessageInfos: file_service_common_parseGeoIP_geoip_proto_msgTypes,
|
||||
}.Build()
|
||||
File_service_common_parseGeoIP_geoip_proto = out.File
|
||||
file_service_common_parseGeoIP_geoip_proto_goTypes = nil
|
||||
file_service_common_parseGeoIP_geoip_proto_depIdxs = nil
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "./service/common/parseGeoIP";
|
||||
|
||||
message CIDR {
|
||||
// IP address, should be either 4 or 16 bytes.
|
||||
bytes ip = 1;
|
||||
|
||||
// Number of leading ones in the network mask.
|
||||
uint32 prefix = 2;
|
||||
}
|
||||
|
||||
message GeoIP {
|
||||
string country_code = 1;
|
||||
repeated CIDR cidr = 2;
|
||||
}
|
||||
|
||||
message GeoIPList {
|
||||
repeated GeoIP entry = 1;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package parseGeoIP
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/v2rayA/v2rayA/core/v2ray/asset"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func Parser(filename string, countryCode string) ([]string, []string, error) {
|
||||
var ipv4List []string
|
||||
var ipv6List []string
|
||||
var geoIpProto GeoIPList
|
||||
|
||||
realpath, err := asset.GetV2rayLocationAsset(filename)
|
||||
if err != nil {
|
||||
return ipv4List, ipv6List, err
|
||||
}
|
||||
data, err := os.ReadFile(realpath)
|
||||
if err != nil {
|
||||
return ipv4List, ipv6List, err
|
||||
}
|
||||
|
||||
if err := proto.Unmarshal(data, &geoIpProto); err != nil {
|
||||
return ipv4List, ipv6List, err
|
||||
}
|
||||
|
||||
for _, geo := range geoIpProto.Entry {
|
||||
if geo.CountryCode == countryCode {
|
||||
for _, c := range geo.Cidr {
|
||||
ip := net.IP(c.Ip)
|
||||
if strings.Contains(ip.String(), ":") {
|
||||
ipv6List = append(ipv6List, fmt.Sprintf("%s/%d", ip.String(), c.Prefix))
|
||||
} else {
|
||||
if strings.Contains(ip.String(), "198.18.0.0") {
|
||||
// 跳过fakeip
|
||||
continue
|
||||
}
|
||||
ipv4List = append(ipv4List, fmt.Sprintf("%s/%d", ip.String(), c.Prefix))
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return ipv4List, ipv6List, nil
|
||||
}
|
||||
@@ -56,6 +56,7 @@ type Sniffing struct {
|
||||
DestOverride []string `json:"destOverride,omitempty"`
|
||||
MetadataOnly bool `json:"metadataOnly"`
|
||||
DomainsExcluded []string `json:"domainsExcluded"`
|
||||
RouteOnly bool `json:"routeOnly"`
|
||||
}
|
||||
type Inbound struct {
|
||||
Port int `json:"port"`
|
||||
|
||||
@@ -2,12 +2,13 @@ package iptables
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/v2rayA/v2rayA/common/cmds"
|
||||
"github.com/v2rayA/v2rayA/core/v2ray/asset"
|
||||
"github.com/v2rayA/v2rayA/db/configure"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/v2rayA/v2rayA/common/cmds"
|
||||
"github.com/v2rayA/v2rayA/core/v2ray/asset"
|
||||
"github.com/v2rayA/v2rayA/db/configure"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -106,23 +107,14 @@ iptables -w 2 -t mangle -A TP_RULE -p tcp --dport 53 -j TP_MARK
|
||||
iptables -w 2 -t mangle -A TP_RULE -m mark --mark 0x40/0xc0 -j RETURN
|
||||
`
|
||||
}
|
||||
|
||||
if IsEnabledTproxyWhiteIpGroups() {
|
||||
whiteIpv4List, _ := GetWhiteListIPs()
|
||||
for _, v := range whiteIpv4List {
|
||||
commands += fmt.Sprintf("iptables -w 2 -t mangle -A TP_RULE -d %s -j RETURN\n", v)
|
||||
}
|
||||
}
|
||||
commands += `
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 0.0.0.0/32 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 10.0.0.0/8 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 100.64.0.0/10 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 127.0.0.0/8 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 169.254.0.0/16 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 172.16.0.0/12 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 192.0.0.0/24 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 192.0.2.0/24 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 192.88.99.0/24 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 192.168.0.0/16 -j RETURN
|
||||
# fakedns
|
||||
# iptables -w 2 -t mangle -A TP_RULE -d 198.18.0.0/15 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 198.51.100.0/24 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 203.0.113.0/24 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 224.0.0.0/4 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -d 240.0.0.0/4 -j RETURN
|
||||
iptables -w 2 -t mangle -A TP_RULE -j TP_MARK
|
||||
|
||||
iptables -w 2 -t mangle -A TP_MARK -p tcp -m tcp --syn -j MARK --set-xmark 0x40/0x40
|
||||
@@ -170,15 +162,13 @@ ip6tables -w 2 -t mangle -A TP_RULE -p tcp --dport 53 -j TP_MARK
|
||||
ip6tables -w 2 -t mangle -A TP_RULE -m mark --mark 0x40/0xc0 -j RETURN
|
||||
`
|
||||
}
|
||||
if IsEnabledTproxyWhiteIpGroups() {
|
||||
_, whiteIpv6List := GetWhiteListIPs()
|
||||
for _, v := range whiteIpv6List {
|
||||
commands += fmt.Sprintf("ip6tables -w 2 -t mangle -A TP_RULE -d %s -j RETURN\n", v)
|
||||
}
|
||||
}
|
||||
commands += `
|
||||
ip6tables -w 2 -t mangle -A TP_RULE -d ::/128 -j RETURN
|
||||
ip6tables -w 2 -t mangle -A TP_RULE -d ::1/128 -j RETURN
|
||||
ip6tables -w 2 -t mangle -A TP_RULE -d 64:ff9b::/96 -j RETURN
|
||||
ip6tables -w 2 -t mangle -A TP_RULE -d 100::/64 -j RETURN
|
||||
ip6tables -w 2 -t mangle -A TP_RULE -d 2001::/32 -j RETURN
|
||||
ip6tables -w 2 -t mangle -A TP_RULE -d 2001:20::/28 -j RETURN
|
||||
ip6tables -w 2 -t mangle -A TP_RULE -d fe80::/10 -j RETURN
|
||||
ip6tables -w 2 -t mangle -A TP_RULE -d ff00::/8 -j RETURN
|
||||
ip6tables -w 2 -t mangle -A TP_RULE -j TP_MARK
|
||||
|
||||
ip6tables -w 2 -t mangle -A TP_MARK -p tcp -m tcp --syn -j MARK --set-xmark 0x40/0x40
|
||||
@@ -246,28 +236,20 @@ func (t *nftTproxy) RemoveIPWhitelist(cidr string) {
|
||||
}
|
||||
|
||||
func (t *nftTproxy) GetSetupCommands() Setter {
|
||||
// 198.18.0.0/15 and fc00::/7 are reserved for private use but used by fakedns
|
||||
table := `
|
||||
table inet v2raya {
|
||||
table inet v2raya {
|
||||
`
|
||||
if IsEnabledTproxyWhiteIpGroups() {
|
||||
whiteIpv4List, whiteIpv6List := GetWhiteListIPs()
|
||||
table += `
|
||||
set whitelist {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
auto-merge
|
||||
elements = {
|
||||
0.0.0.0/32,
|
||||
10.0.0.0/8,
|
||||
100.64.0.0/10,
|
||||
127.0.0.0/8,
|
||||
169.254.0.0/16,
|
||||
172.16.0.0/12,
|
||||
192.0.0.0/24,
|
||||
192.0.2.0/24,
|
||||
192.88.99.0/24,
|
||||
192.168.0.0/16,
|
||||
198.51.100.0/24,
|
||||
203.0.113.0/24,
|
||||
224.0.0.0/4,
|
||||
240.0.0.0/4
|
||||
`
|
||||
table += strings.Join(whiteIpv4List, ",")
|
||||
table += `
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,17 +258,17 @@ table inet v2raya {
|
||||
flags interval
|
||||
auto-merge
|
||||
elements = {
|
||||
::/128,
|
||||
::1/128,
|
||||
64:ff9b::/96,
|
||||
100::/64,
|
||||
2001::/32,
|
||||
2001:20::/28,
|
||||
fe80::/10,
|
||||
ff00::/8
|
||||
`
|
||||
table += strings.Join(whiteIpv6List, ",")
|
||||
table += `
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
// 198.18.0.0/15 and fc00::/7 are reserved for private use but used by fakedns
|
||||
|
||||
table += `
|
||||
set interface {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
@@ -335,9 +317,15 @@ table inet v2raya {
|
||||
iifname "ppp*" return
|
||||
# anti-pollution
|
||||
ip daddr @interface return
|
||||
`
|
||||
if IsEnabledTproxyWhiteIpGroups() {
|
||||
table += `
|
||||
ip daddr @whitelist return
|
||||
ip6 daddr @interface6 return
|
||||
ip6 daddr @whitelist6 return
|
||||
`
|
||||
}
|
||||
table += `
|
||||
ip6 daddr @interface6 return
|
||||
jump tp_mark
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,9 @@ import (
|
||||
|
||||
"github.com/v2rayA/v2rayA/common"
|
||||
"github.com/v2rayA/v2rayA/common/cmds"
|
||||
"github.com/v2rayA/v2rayA/common/parseGeoIP"
|
||||
"github.com/v2rayA/v2rayA/conf"
|
||||
"github.com/v2rayA/v2rayA/db/configure"
|
||||
"golang.org/x/net/nettest"
|
||||
)
|
||||
|
||||
@@ -89,3 +91,28 @@ func IsNftablesSupported() bool {
|
||||
}
|
||||
return strings.Contains(string(out), "nf_tables")
|
||||
}
|
||||
|
||||
func GetWhiteListIPs() ([]string, []string) {
|
||||
dataModal := configure.GetTproxyWhiteIpGroups()
|
||||
|
||||
var ipv4List []string
|
||||
var ipv6List []string
|
||||
for _, cc := range dataModal.CountryCodes {
|
||||
ipv4s, ipv6s, _ := parseGeoIP.Parser("geoip.dat", cc)
|
||||
ipv4List = append(ipv4List, ipv4s...)
|
||||
ipv6List = append(ipv6List, ipv6s...)
|
||||
}
|
||||
for _, v := range dataModal.CustomIps {
|
||||
if strings.Contains(v, ":") {
|
||||
ipv6List = append(ipv6List, v)
|
||||
} else {
|
||||
ipv4List = append(ipv4List, v)
|
||||
}
|
||||
}
|
||||
return ipv4List, ipv6List
|
||||
}
|
||||
|
||||
func IsEnabledTproxyWhiteIpGroups() bool {
|
||||
ipv4List, ipv6List := GetWhiteListIPs()
|
||||
return len(ipv4List) > 0 && len(ipv6List) > 0
|
||||
}
|
||||
|
||||
@@ -668,6 +668,7 @@ func parseRoutingA(t *Template, routingInboundTags []string) error {
|
||||
Sniffing: coreObj.Sniffing{
|
||||
Enabled: false,
|
||||
DestOverride: []string{"http", "tls"},
|
||||
RouteOnly: false,
|
||||
},
|
||||
}
|
||||
if sniffing := proto.NamedParams["sniffing"]; len(sniffing) > 0 {
|
||||
@@ -1117,6 +1118,7 @@ func (t *Template) setInbound(setting *configure.Setting) error {
|
||||
|
||||
// 设置域名嗅探
|
||||
if setting.InboundSniffing != configure.InboundSniffingDisable && setting.InboundSniffing != "" {
|
||||
enableSniffingRouteOnly := configure.GetSettingNotNil().RouteOnly
|
||||
domainsExcludedText := configure.GetDomainsExcluded()
|
||||
for i := len(t.Inbounds) - 1; i >= 0; i-- {
|
||||
if setting.InboundSniffing == configure.InboundSniffingHttpTLS {
|
||||
@@ -1126,7 +1128,9 @@ func (t *Template) setInbound(setting *configure.Setting) error {
|
||||
}
|
||||
t.Inbounds[i].Sniffing.DomainsExcluded = strings.Split(domainsExcludedText, "\n")
|
||||
t.Inbounds[i].Sniffing.Enabled = true
|
||||
t.Inbounds[i].Sniffing.RouteOnly = enableSniffingRouteOnly
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -16,16 +16,17 @@ import (
|
||||
)
|
||||
|
||||
type Configure struct {
|
||||
Servers []*ServerRaw `json:"servers"`
|
||||
Subscriptions []*SubscriptionRaw `json:"subscriptions"`
|
||||
ConnectedServers []*Which `json:"connectedServers"`
|
||||
Setting *Setting `json:"setting"`
|
||||
Accounts map[string]string `json:"accounts"`
|
||||
Ports Ports `json:"ports"`
|
||||
InternalDnsList *string `json:"internalDnsList"`
|
||||
ExternalDnsList *string `json:"externalDnsList"`
|
||||
RoutingA *string `json:"routingA"`
|
||||
DomainsExcluded *string `json:"domainsExcluded"`
|
||||
Servers []*ServerRaw `json:"servers"`
|
||||
Subscriptions []*SubscriptionRaw `json:"subscriptions"`
|
||||
ConnectedServers []*Which `json:"connectedServers"`
|
||||
Setting *Setting `json:"setting"`
|
||||
Accounts map[string]string `json:"accounts"`
|
||||
Ports Ports `json:"ports"`
|
||||
InternalDnsList *string `json:"internalDnsList"`
|
||||
ExternalDnsList *string `json:"externalDnsList"`
|
||||
RoutingA *string `json:"routingA"`
|
||||
DomainsExcluded *string `json:"domainsExcluded"`
|
||||
TproxyWhiteIpGroups TproxyWhiteIpGroups `json:"tproxyWhiteIpGroups"`
|
||||
}
|
||||
|
||||
func New() *Configure {
|
||||
@@ -275,10 +276,20 @@ func GetRoutingA() (r string) {
|
||||
func SetDomainsExcluded(domains string) (err error) {
|
||||
return db.Set("system", "domainsExcluded", domains)
|
||||
}
|
||||
func SetTproxyWhiteIpGroups(countryCodes []string, customIps []string) (err error) {
|
||||
return db.Set("system", "tproxyWhiteIpGroups", TproxyWhiteIpGroups{
|
||||
CountryCodes: countryCodes,
|
||||
CustomIps: customIps,
|
||||
})
|
||||
}
|
||||
func GetDomainsExcluded() (r string) {
|
||||
db.Get("system", "domainsExcluded", &r)
|
||||
return r
|
||||
}
|
||||
func GetTproxyWhiteIpGroups() (r TproxyWhiteIpGroups) {
|
||||
db.Get("system", "tproxyWhiteIpGroups", &r)
|
||||
return r
|
||||
}
|
||||
func GetConnectedServers() (wts *Whiches) {
|
||||
outbounds := GetOutbounds()
|
||||
for _, outbound := range outbounds {
|
||||
|
||||
@@ -19,6 +19,7 @@ type Setting struct {
|
||||
InboundSniffing InboundSniffing `json:"inboundSniffing"`
|
||||
Transparent TransparentMode `json:"transparent"`
|
||||
IpForward bool `json:"ipforward"`
|
||||
RouteOnly bool `json:"routeOnly"`
|
||||
PortSharing bool `json:"portSharing"`
|
||||
SpecialMode SpecialMode `json:"specialMode"`
|
||||
TransparentType TransparentType `json:"transparentType"`
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package configure
|
||||
|
||||
type TproxyWhiteIpGroups struct {
|
||||
CountryCodes []string `json:"countryCodes"`
|
||||
CustomIps []string `json:"customIps"`
|
||||
}
|
||||
@@ -157,11 +157,17 @@ func initConfigure() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Warn("Migration is done")
|
||||
} else {
|
||||
initDBValue()
|
||||
}
|
||||
}
|
||||
|
||||
if len(configure.GetTproxyWhiteIpGroups().CountryCodes) == 0 {
|
||||
configure.SetTproxyWhiteIpGroups([]string{"PRIVATE"}, []string{})
|
||||
}
|
||||
|
||||
//检查config.json是否存在
|
||||
if _, err := os.Stat(asset.GetV2rayConfigPath()); err != nil {
|
||||
//不存在就建一个。多数情况发生于docker模式挂载volume时覆盖了/etc/v2ray
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/v2rayA/v2rayA/common"
|
||||
"github.com/v2rayA/v2rayA/db/configure"
|
||||
)
|
||||
|
||||
func GetTproxyWhiteIpGroups(ctx *gin.Context) {
|
||||
resp := configure.GetTproxyWhiteIpGroups()
|
||||
common.ResponseSuccess(ctx, gin.H{
|
||||
"countryCodes": resp.CountryCodes,
|
||||
"customIps": resp.CustomIps,
|
||||
})
|
||||
}
|
||||
|
||||
func PutTproxyWhiteIpGroups(ctx *gin.Context) {
|
||||
var data struct {
|
||||
CountryCodes []string `json:"countryCodes"`
|
||||
CustomIps []string `json:"customIps"`
|
||||
}
|
||||
err := ctx.ShouldBindJSON(&data)
|
||||
if err != nil {
|
||||
common.ResponseError(ctx, logError("bad request"))
|
||||
return
|
||||
}
|
||||
configure.SetTproxyWhiteIpGroups(data.CountryCodes, data.CustomIps)
|
||||
common.ResponseSuccess(ctx, nil)
|
||||
}
|
||||
@@ -197,7 +197,9 @@ func Run() error {
|
||||
auth.GET("message", controller.WsMessage)
|
||||
auth.GET("logger", controller.GetLogger)
|
||||
auth.GET("domainsExcluded", controller.GetDomainsExcluded)
|
||||
auth.GET("tproxyWhiteIpGroups", controller.GetTproxyWhiteIpGroups)
|
||||
auth.PUT("domainsExcluded", controller.PutDomainsExcluded)
|
||||
auth.PUT("tproxyWhiteIpGroups", controller.PutTproxyWhiteIpGroups)
|
||||
}
|
||||
|
||||
ServeGUI(engine)
|
||||
|
||||
@@ -12,8 +12,8 @@ android {
|
||||
applicationId = "com.v2ray.ang"
|
||||
minSdk = 21
|
||||
targetSdk = 35
|
||||
versionCode = 677
|
||||
versionName = "1.10.26"
|
||||
versionCode = 678
|
||||
versionName = "1.10.27"
|
||||
multiDexEnabled = true
|
||||
|
||||
val abiFilterList = (properties["ABI_FILTERS"] as? String)?.split(';')
|
||||
|
||||
@@ -560,6 +560,13 @@ class FFmpegFD(ExternalFD):
|
||||
elif isinstance(conn, str):
|
||||
args += ['-rtmp_conn', conn]
|
||||
|
||||
elif protocol == 'http_dash_segments' and info_dict.get('is_live'):
|
||||
# ffmpeg may try to read past the latest available segments for
|
||||
# live DASH streams unless we pass `-re`. In modern ffmpeg, this
|
||||
# is an alias of `-readrate 1`, but `-readrate` was not added
|
||||
# until ffmpeg 5.0, so we must stick to using `-re`
|
||||
args += ['-re']
|
||||
|
||||
url = fmt['url']
|
||||
if self.params.get('enable_file_urls') and url.startswith('file:'):
|
||||
# The default protocol_whitelist is 'file,crypto,data' when reading local m3u8 URLs,
|
||||
|
||||
@@ -340,8 +340,9 @@ class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor):
|
||||
thumbnails=self._extract_thumbnails(view_model, (
|
||||
'contentImage', *thumb_keys, 'thumbnailViewModel', 'image'), final_key='sources'),
|
||||
duration=traverse_obj(view_model, (
|
||||
'contentImage', 'thumbnailViewModel', 'overlays', ..., 'thumbnailOverlayBadgeViewModel',
|
||||
'thumbnailBadges', ..., 'thumbnailBadgeViewModel', 'text', {parse_duration}, any)),
|
||||
'contentImage', 'thumbnailViewModel', 'overlays', ...,
|
||||
(('thumbnailBottomOverlayViewModel', 'badges'), ('thumbnailOverlayBadgeViewModel', 'thumbnailBadges')),
|
||||
..., 'thumbnailBadgeViewModel', 'text', {parse_duration}, any)),
|
||||
timestamp=(traverse_obj(view_model, (
|
||||
'metadata', 'lockupMetadataViewModel', 'metadata', 'contentMetadataViewModel', 'metadataRows',
|
||||
..., 'metadataParts', ..., 'text', 'content', {lambda t: self._parse_time_text(t, report_failure=False)}, any))
|
||||
|
||||
@@ -1556,6 +1556,46 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
'view_count': int,
|
||||
},
|
||||
'params': {'skip_download': True},
|
||||
}, {
|
||||
# Youtube Music Auto-generated description with dot in artist name
|
||||
'url': 'https://music.youtube.com/watch?v=DbCvuSGfR3Y',
|
||||
'info_dict': {
|
||||
'id': 'DbCvuSGfR3Y',
|
||||
'ext': 'mp4',
|
||||
'title': 'Back Around',
|
||||
'artists': ['half·alive'],
|
||||
'track': 'Back Around',
|
||||
'album': 'Conditions Of A Punk',
|
||||
'release_date': '20221202',
|
||||
'release_year': 2021,
|
||||
'alt_title': 'Back Around',
|
||||
'description': 'md5:bfc0e2b3cc903a608d8a85a13cb50f95',
|
||||
'media_type': 'video',
|
||||
'uploader': 'half•alive',
|
||||
'channel': 'half•alive',
|
||||
'channel_id': 'UCYQrYophdVI3nVDPOnXyIng',
|
||||
'channel_url': 'https://www.youtube.com/channel/UCYQrYophdVI3nVDPOnXyIng',
|
||||
'channel_is_verified': True,
|
||||
'channel_follower_count': int,
|
||||
'comment_count': int,
|
||||
'view_count': int,
|
||||
'like_count': int,
|
||||
'age_limit': 0,
|
||||
'duration': 223,
|
||||
'thumbnail': 'https://i.ytimg.com/vi_webp/DbCvuSGfR3Y/maxresdefault.webp',
|
||||
'heatmap': 'count:100',
|
||||
'categories': ['Music'],
|
||||
'tags': ['half·alive', 'Conditions Of A Punk', 'Back Around'],
|
||||
'creators': ['half·alive'],
|
||||
'timestamp': 1669889281,
|
||||
'upload_date': '20221201',
|
||||
'playable_in_embed': True,
|
||||
'availability': 'public',
|
||||
'live_status': 'not_live',
|
||||
},
|
||||
'params': {
|
||||
'skip_download': True,
|
||||
},
|
||||
}]
|
||||
_WEBPAGE_TESTS = [{
|
||||
# <object>
|
||||
@@ -3023,8 +3063,12 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
|
||||
def _extract_formats_and_subtitles(self, video_id, player_responses, player_url, live_status, duration):
|
||||
CHUNK_SIZE = 10 << 20
|
||||
PREFERRED_LANG_VALUE = 10
|
||||
original_language = None
|
||||
ORIGINAL_LANG_VALUE = 10
|
||||
DEFAULT_LANG_VALUE = 5
|
||||
language_map = {
|
||||
ORIGINAL_LANG_VALUE: None,
|
||||
DEFAULT_LANG_VALUE: None,
|
||||
}
|
||||
itags, stream_ids = collections.defaultdict(set), []
|
||||
itag_qualities, res_qualities = {}, {0: None}
|
||||
subtitles = {}
|
||||
@@ -3064,6 +3108,22 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
# For handling potential pre-playback required waiting period
|
||||
playback_wait = int_or_none(self._configuration_arg('playback_wait', [None])[0], default=6)
|
||||
|
||||
def get_language_code_and_preference(fmt_stream):
|
||||
audio_track = fmt_stream.get('audioTrack') or {}
|
||||
display_name = audio_track.get('displayName') or ''
|
||||
language_code = audio_track.get('id', '').split('.')[0] or None
|
||||
if 'descriptive' in display_name.lower():
|
||||
return join_nonempty(language_code, 'desc'), -10
|
||||
if 'original' in display_name.lower():
|
||||
if language_code and not language_map.get(ORIGINAL_LANG_VALUE):
|
||||
language_map[ORIGINAL_LANG_VALUE] = language_code
|
||||
return language_code, ORIGINAL_LANG_VALUE
|
||||
if audio_track.get('audioIsDefault'):
|
||||
if language_code and not language_map.get(DEFAULT_LANG_VALUE):
|
||||
language_map[DEFAULT_LANG_VALUE] = language_code
|
||||
return language_code, DEFAULT_LANG_VALUE
|
||||
return language_code, -1
|
||||
|
||||
for pr in player_responses:
|
||||
streaming_data = traverse_obj(pr, 'streamingData')
|
||||
if not streaming_data:
|
||||
@@ -3079,7 +3139,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
return str_or_none(fmt_stream.get('itag')), traverse_obj(fmt_stream, 'audioTrack', 'id'), fmt_stream.get('isDrc')
|
||||
|
||||
def process_format_stream(fmt_stream, proto, missing_pot):
|
||||
nonlocal original_language
|
||||
itag = str_or_none(fmt_stream.get('itag'))
|
||||
audio_track = fmt_stream.get('audioTrack') or {}
|
||||
quality = fmt_stream.get('quality')
|
||||
@@ -3096,13 +3155,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
if height:
|
||||
res_qualities[height] = quality
|
||||
|
||||
display_name = audio_track.get('displayName') or ''
|
||||
is_original = 'original' in display_name.lower()
|
||||
is_descriptive = 'descriptive' in display_name.lower()
|
||||
is_default = audio_track.get('audioIsDefault')
|
||||
language_code = audio_track.get('id', '').split('.')[0]
|
||||
if language_code and (is_original or (is_default and not original_language)):
|
||||
original_language = language_code
|
||||
language_code, language_preference = get_language_code_and_preference(fmt_stream)
|
||||
|
||||
has_drm = bool(fmt_stream.get('drmFamilies'))
|
||||
|
||||
@@ -3138,7 +3191,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
'filesize': int_or_none(fmt_stream.get('contentLength')),
|
||||
'format_id': f'{itag}{"-drc" if fmt_stream.get("isDrc") else ""}',
|
||||
'format_note': join_nonempty(
|
||||
join_nonempty(display_name, is_default and ' (default)', delim=''),
|
||||
join_nonempty(audio_track.get('displayName'), audio_track.get('audioIsDefault') and '(default)', delim=' '),
|
||||
name, fmt_stream.get('isDrc') and 'DRC',
|
||||
try_get(fmt_stream, lambda x: x['projectionType'].replace('RECTANGULAR', '').lower()),
|
||||
try_get(fmt_stream, lambda x: x['spatialAudioType'].replace('SPATIAL_AUDIO_TYPE_', '').lower()),
|
||||
@@ -3155,8 +3208,8 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
'tbr': tbr,
|
||||
'filesize_approx': filesize_from_tbr(tbr, format_duration),
|
||||
'width': int_or_none(fmt_stream.get('width')),
|
||||
'language': join_nonempty(language_code, 'desc' if is_descriptive else '') or None,
|
||||
'language_preference': PREFERRED_LANG_VALUE if is_original else 5 if is_default else -10 if is_descriptive else -1,
|
||||
'language': language_code,
|
||||
'language_preference': language_preference,
|
||||
# Strictly de-prioritize damaged and 3gp formats
|
||||
'preference': -10 if is_damaged else -2 if itag == '17' else None,
|
||||
}
|
||||
@@ -3206,6 +3259,9 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
fmt_url = fmt_stream.get('url')
|
||||
encrypted_sig, sc = None, None
|
||||
if not fmt_url:
|
||||
# We still need to register original/default language information
|
||||
# See: https://github.com/yt-dlp/yt-dlp/issues/14883
|
||||
get_language_code_and_preference(fmt_stream)
|
||||
sc = urllib.parse.parse_qs(fmt_stream.get('signatureCipher'))
|
||||
fmt_url = url_or_none(try_get(sc, lambda x: x['url'][0]))
|
||||
encrypted_sig = try_get(sc, lambda x: x['s'][0])
|
||||
@@ -3391,9 +3447,13 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
elif itag:
|
||||
f['format_id'] = itag
|
||||
|
||||
if original_language and f.get('language') == original_language:
|
||||
lang_code = f.get('language')
|
||||
if lang_code and lang_code == language_map[ORIGINAL_LANG_VALUE]:
|
||||
f['format_note'] = join_nonempty(f.get('format_note'), '(original)', delim=' ')
|
||||
f['language_preference'] = ORIGINAL_LANG_VALUE
|
||||
elif lang_code and lang_code == language_map[DEFAULT_LANG_VALUE]:
|
||||
f['format_note'] = join_nonempty(f.get('format_note'), '(default)', delim=' ')
|
||||
f['language_preference'] = PREFERRED_LANG_VALUE
|
||||
f['language_preference'] = DEFAULT_LANG_VALUE
|
||||
|
||||
if itag in ('616', '235'):
|
||||
f['format_note'] = join_nonempty(f.get('format_note'), 'Premium', delim=' ')
|
||||
@@ -3988,20 +4048,14 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
|
||||
# Youtube Music Auto-generated description
|
||||
if (video_description or '').strip().endswith('\nAuto-generated by YouTube.'):
|
||||
# XXX: Causes catastrophic backtracking if description has "·"
|
||||
# E.g. https://www.youtube.com/watch?v=DoPaAxMQoiI
|
||||
# Simulating atomic groups: (?P<a>[^xy]+)x => (?=(?P<a>[^xy]+))(?P=a)x
|
||||
# reduces it, but does not fully fix it. https://regex101.com/r/8Ssf2h/2
|
||||
mobj = re.search(
|
||||
r'''(?xs)
|
||||
(?=(?P<track>[^\n·]+))(?P=track)·
|
||||
(?=(?P<artist>[^\n]+))(?P=artist)\n+
|
||||
(?=(?P<album>[^\n]+))(?P=album)\n
|
||||
(?:.+?℗\s*(?P<release_year>\d{4})(?!\d))?
|
||||
(?:.+?Released\ on\s*:\s*(?P<release_date>\d{4}-\d{2}-\d{2}))?
|
||||
(.+?\nArtist\s*:\s*
|
||||
(?=(?P<clean_artist>[^\n]+))(?P=clean_artist)\n
|
||||
)?.+\nAuto-generated\ by\ YouTube\.\s*$
|
||||
(?:\n|^)(?P<track>[^\n·]+)\ ·\ (?P<artist>[^\n]+)\n+
|
||||
(?P<album>[^\n]+)\n+
|
||||
(?:℗\s*(?P<release_year>\d{4}))?
|
||||
(?:.+?\nReleased\ on\s*:\s*(?P<release_date>\d{4}-\d{2}-\d{2}))?
|
||||
(?:.+?\nArtist\s*:\s*(?P<clean_artist>[^\n]+)\n)?
|
||||
.+\nAuto-generated\ by\ YouTube\.\s*$
|
||||
''', video_description)
|
||||
if mobj:
|
||||
release_year = mobj.group('release_year')
|
||||
@@ -4013,7 +4067,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
info.update({
|
||||
'album': mobj.group('album'.strip()),
|
||||
'artists': ([a] if (a := mobj.group('clean_artist'))
|
||||
else [a.strip() for a in mobj.group('artist').split('·')]),
|
||||
else [a.strip() for a in mobj.group('artist').split(' · ')]),
|
||||
'track': mobj.group('track').strip(),
|
||||
'release_date': release_date,
|
||||
'release_year': int_or_none(release_year),
|
||||
|
||||
Reference in New Issue
Block a user