Initial Navis client with NaiveProxy, profiles, ping and git updates
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ProfileInfo is a safe summary for UI lists (no secrets beyond proxy URI the user already owns).
|
||||
type ProfileInfo struct {
|
||||
Name string `json:"name"`
|
||||
Protocol string `json:"protocol"`
|
||||
Proxy string `json:"proxy"`
|
||||
Host string `json:"host"`
|
||||
Active bool `json:"active"`
|
||||
}
|
||||
|
||||
// ListProfiles returns UI-friendly profile summaries.
|
||||
func (c *Config) ListProfiles() []ProfileInfo {
|
||||
out := make([]ProfileInfo, 0, len(c.Profiles))
|
||||
for _, p := range c.Profiles {
|
||||
out = append(out, ProfileInfo{
|
||||
Name: p.Name,
|
||||
Protocol: string(p.Protocol),
|
||||
Proxy: p.Proxy,
|
||||
Host: proxyHost(p.Proxy),
|
||||
Active: p.Name == c.Active,
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func proxyHost(proxy string) string {
|
||||
proxy = strings.TrimSpace(proxy)
|
||||
if proxy == "" {
|
||||
return ""
|
||||
}
|
||||
if i := strings.Index(proxy, "://"); i >= 0 {
|
||||
proxy = proxy[i+3:]
|
||||
}
|
||||
if at := strings.LastIndex(proxy, "@"); at >= 0 {
|
||||
proxy = proxy[at+1:]
|
||||
}
|
||||
if i := strings.IndexAny(proxy, "/?#"); i >= 0 {
|
||||
proxy = proxy[:i]
|
||||
}
|
||||
return proxy
|
||||
}
|
||||
|
||||
// SetActive switches the active profile name.
|
||||
func (c *Config) SetActive(name string) error {
|
||||
name = strings.TrimSpace(name)
|
||||
for _, p := range c.Profiles {
|
||||
if p.Name == name {
|
||||
c.Active = name
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("profile %q not found", name)
|
||||
}
|
||||
|
||||
// UpsertProfile creates or updates a profile by name.
|
||||
func (c *Config) UpsertProfile(name, proxy string) error {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return fmt.Errorf("имя профиля пустое")
|
||||
}
|
||||
proxy = strings.TrimSpace(proxy)
|
||||
|
||||
for i := range c.Profiles {
|
||||
if c.Profiles[i].Name == name {
|
||||
c.Profiles[i].Proxy = proxy
|
||||
if c.Profiles[i].Protocol == "" {
|
||||
c.Profiles[i].Protocol = ProtocolNaive
|
||||
}
|
||||
if len(c.Profiles[i].Listen) == 0 {
|
||||
c.Profiles[i].Listen = defaultListen()
|
||||
}
|
||||
c.Active = name
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
c.Profiles = append(c.Profiles, Profile{
|
||||
Name: name,
|
||||
Protocol: ProtocolNaive,
|
||||
Proxy: proxy,
|
||||
Listen: defaultListen(),
|
||||
})
|
||||
c.Active = name
|
||||
return nil
|
||||
}
|
||||
|
||||
// RenameProfile renames a profile and keeps active pointer in sync.
|
||||
func (c *Config) RenameProfile(oldName, newName string) error {
|
||||
oldName = strings.TrimSpace(oldName)
|
||||
newName = strings.TrimSpace(newName)
|
||||
if oldName == "" || newName == "" {
|
||||
return fmt.Errorf("имя профиля пустое")
|
||||
}
|
||||
if oldName == newName {
|
||||
return nil
|
||||
}
|
||||
for _, p := range c.Profiles {
|
||||
if p.Name == newName {
|
||||
return fmt.Errorf("профиль %q уже существует", newName)
|
||||
}
|
||||
}
|
||||
for i := range c.Profiles {
|
||||
if c.Profiles[i].Name == oldName {
|
||||
c.Profiles[i].Name = newName
|
||||
if c.Active == oldName {
|
||||
c.Active = newName
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("profile %q not found", oldName)
|
||||
}
|
||||
|
||||
// DeleteProfile removes a profile. Keeps at least one profile.
|
||||
func (c *Config) DeleteProfile(name string) error {
|
||||
name = strings.TrimSpace(name)
|
||||
if len(c.Profiles) <= 1 {
|
||||
return fmt.Errorf("нельзя удалить последний профиль")
|
||||
}
|
||||
idx := -1
|
||||
for i, p := range c.Profiles {
|
||||
if p.Name == name {
|
||||
idx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if idx < 0 {
|
||||
return fmt.Errorf("profile %q not found", name)
|
||||
}
|
||||
c.Profiles = append(c.Profiles[:idx], c.Profiles[idx+1:]...)
|
||||
if c.Active == name {
|
||||
c.Active = c.Profiles[0].Name
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func defaultListen() []string {
|
||||
return []string{
|
||||
"socks://127.0.0.1:1080",
|
||||
"http://127.0.0.1:1081",
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user