mirror of
https://github.com/black-ant/Ant-Browser.git
synced 2026-07-14 18:48:55 +08:00
channel: master version: 1.1.0 source-ref: master published-at-utc: 2026-03-20T14:14:07Z
209 lines
5.7 KiB
Go
209 lines
5.7 KiB
Go
package browser
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func normalizeProxyBindValue(v string) string {
|
|
return strings.ToLower(strings.TrimSpace(v))
|
|
}
|
|
|
|
func (m *Manager) listProxyCatalog() []Proxy {
|
|
if m.ProxyDAO != nil {
|
|
if list, err := m.ProxyDAO.List(); err == nil && len(list) > 0 {
|
|
return append([]Proxy{}, list...)
|
|
}
|
|
}
|
|
return append([]Proxy{}, m.Config.Browser.Proxies...)
|
|
}
|
|
|
|
func findProxyByID(list []Proxy, proxyID string) (Proxy, bool) {
|
|
target := normalizeProxyBindValue(proxyID)
|
|
if target == "" {
|
|
return Proxy{}, false
|
|
}
|
|
for _, item := range list {
|
|
if normalizeProxyBindValue(item.ProxyId) == target {
|
|
return item, true
|
|
}
|
|
}
|
|
return Proxy{}, false
|
|
}
|
|
|
|
func uniqueProxyMatch(list []Proxy, match func(Proxy) bool) (Proxy, bool) {
|
|
var hit Proxy
|
|
matched := 0
|
|
for _, item := range list {
|
|
if !match(item) {
|
|
continue
|
|
}
|
|
hit = item
|
|
matched++
|
|
if matched > 1 {
|
|
return Proxy{}, false
|
|
}
|
|
}
|
|
return hit, matched == 1
|
|
}
|
|
|
|
// GetProxyByID 根据代理 ID 获取代理对象(优先 DAO)。
|
|
func (m *Manager) GetProxyByID(proxyID string) (Proxy, bool) {
|
|
return findProxyByID(m.listProxyCatalog(), proxyID)
|
|
}
|
|
|
|
// BindProfileToProxy 将实例绑定到指定代理并同步绑定快照。
|
|
// syncProxyConfig=true 时会同步更新 profile.ProxyConfig。
|
|
func BindProfileToProxy(profile *Profile, proxy Proxy, syncProxyConfig bool) bool {
|
|
if profile == nil {
|
|
return false
|
|
}
|
|
|
|
changed := false
|
|
if profile.ProxyId != strings.TrimSpace(proxy.ProxyId) {
|
|
profile.ProxyId = strings.TrimSpace(proxy.ProxyId)
|
|
changed = true
|
|
}
|
|
if syncProxyConfig {
|
|
proxyConfig := strings.TrimSpace(proxy.ProxyConfig)
|
|
if proxyConfig != "" && profile.ProxyConfig != proxyConfig {
|
|
profile.ProxyConfig = proxyConfig
|
|
changed = true
|
|
}
|
|
}
|
|
|
|
sourceID := strings.TrimSpace(proxy.SourceID)
|
|
sourceURL := strings.TrimSpace(proxy.SourceURL)
|
|
proxyName := strings.TrimSpace(proxy.ProxyName)
|
|
if profile.ProxyBindSourceID != sourceID {
|
|
profile.ProxyBindSourceID = sourceID
|
|
changed = true
|
|
}
|
|
if profile.ProxyBindSourceURL != sourceURL {
|
|
profile.ProxyBindSourceURL = sourceURL
|
|
changed = true
|
|
}
|
|
if profile.ProxyBindName != proxyName {
|
|
profile.ProxyBindName = proxyName
|
|
changed = true
|
|
}
|
|
if changed {
|
|
profile.ProxyBindUpdatedAt = time.Now().Format(time.RFC3339)
|
|
}
|
|
return changed
|
|
}
|
|
|
|
// ClearProfileProxyBinding 清空实例的代理绑定快照。
|
|
func ClearProfileProxyBinding(profile *Profile) bool {
|
|
if profile == nil {
|
|
return false
|
|
}
|
|
changed := false
|
|
if profile.ProxyBindSourceID != "" {
|
|
profile.ProxyBindSourceID = ""
|
|
changed = true
|
|
}
|
|
if profile.ProxyBindSourceURL != "" {
|
|
profile.ProxyBindSourceURL = ""
|
|
changed = true
|
|
}
|
|
if profile.ProxyBindName != "" {
|
|
profile.ProxyBindName = ""
|
|
changed = true
|
|
}
|
|
if changed {
|
|
profile.ProxyBindUpdatedAt = time.Now().Format(time.RFC3339)
|
|
}
|
|
return changed
|
|
}
|
|
|
|
// ResolveProfileProxyBinding 尝试修复实例代理绑定。
|
|
// 返回值: changed 是否修改实例, boundInPool 是否在代理池成功定位, mode 重关联命中模式
|
|
func (m *Manager) ResolveProfileProxyBinding(profile *Profile) (bool, bool, string) {
|
|
if profile == nil {
|
|
return false, false, ""
|
|
}
|
|
proxies := m.listProxyCatalog()
|
|
if len(proxies) == 0 {
|
|
return false, false, ""
|
|
}
|
|
|
|
if proxy, ok := findProxyByID(proxies, profile.ProxyId); ok {
|
|
changed := BindProfileToProxy(profile, proxy, true)
|
|
return changed, true, "proxy_id"
|
|
}
|
|
|
|
allowConfigFallback := strings.TrimSpace(profile.ProxyId) != "" ||
|
|
strings.TrimSpace(profile.ProxyBindSourceID) != "" ||
|
|
strings.TrimSpace(profile.ProxyBindSourceURL) != "" ||
|
|
strings.TrimSpace(profile.ProxyBindName) != ""
|
|
|
|
if proxy, ok, mode := matchProxyBySnapshot(profile, proxies, allowConfigFallback); ok {
|
|
changed := BindProfileToProxy(profile, proxy, true)
|
|
return changed, true, mode
|
|
}
|
|
|
|
return false, false, ""
|
|
}
|
|
|
|
func matchProxyBySnapshot(profile *Profile, proxies []Proxy, allowConfigFallback bool) (Proxy, bool, string) {
|
|
nameKey := normalizeProxyBindValue(profile.ProxyBindName)
|
|
sourceIDKey := normalizeProxyBindValue(profile.ProxyBindSourceID)
|
|
sourceURLKey := normalizeProxyBindValue(profile.ProxyBindSourceURL)
|
|
cfgKey := normalizeProxyBindValue(profile.ProxyConfig)
|
|
|
|
if sourceIDKey != "" && nameKey != "" {
|
|
if hit, ok := uniqueProxyMatch(proxies, func(item Proxy) bool {
|
|
return normalizeProxyBindValue(item.SourceID) == sourceIDKey &&
|
|
normalizeProxyBindValue(item.ProxyName) == nameKey
|
|
}); ok {
|
|
return hit, true, "source_id+name"
|
|
}
|
|
}
|
|
|
|
if sourceURLKey != "" && nameKey != "" {
|
|
if hit, ok := uniqueProxyMatch(proxies, func(item Proxy) bool {
|
|
return normalizeProxyBindValue(item.SourceURL) == sourceURLKey &&
|
|
normalizeProxyBindValue(item.ProxyName) == nameKey
|
|
}); ok {
|
|
return hit, true, "source_url+name"
|
|
}
|
|
}
|
|
|
|
if nameKey != "" {
|
|
if hit, ok := uniqueProxyMatch(proxies, func(item Proxy) bool {
|
|
return normalizeProxyBindValue(item.ProxyName) == nameKey
|
|
}); ok {
|
|
return hit, true, "name"
|
|
}
|
|
}
|
|
|
|
if sourceIDKey != "" && cfgKey != "" {
|
|
if hit, ok := uniqueProxyMatch(proxies, func(item Proxy) bool {
|
|
return normalizeProxyBindValue(item.SourceID) == sourceIDKey &&
|
|
normalizeProxyBindValue(item.ProxyConfig) == cfgKey
|
|
}); ok {
|
|
return hit, true, "source_id+config"
|
|
}
|
|
}
|
|
|
|
if sourceURLKey != "" && cfgKey != "" {
|
|
if hit, ok := uniqueProxyMatch(proxies, func(item Proxy) bool {
|
|
return normalizeProxyBindValue(item.SourceURL) == sourceURLKey &&
|
|
normalizeProxyBindValue(item.ProxyConfig) == cfgKey
|
|
}); ok {
|
|
return hit, true, "source_url+config"
|
|
}
|
|
}
|
|
|
|
if allowConfigFallback && cfgKey != "" {
|
|
if hit, ok := uniqueProxyMatch(proxies, func(item Proxy) bool {
|
|
return normalizeProxyBindValue(item.ProxyConfig) == cfgKey
|
|
}); ok {
|
|
return hit, true, "config"
|
|
}
|
|
}
|
|
|
|
return Proxy{}, false, ""
|
|
}
|