Files
Go-VPN-Client/internal/config/config.go
arkonsadter 20d24a3639 feat(cli): add settings menu and VLESS log viewer with core selection
- Add settings menu to switch between Xray and V2Ray cores for VLESS connections
- Implement core type persistence in configuration with LoadSettings/SaveSettings
- Add VLESS error and access log viewer showing last 30 and 20 lines respectively
- Display current core type and system time in main menu
- Update VLESS connection to use selected core dynamically
- Refactor monitor.go to accept 'q' key input for graceful exit instead of signal handling
- Add proxy platform-specific implementations (proxy_unix.go, proxy_windows.go)
- Add downloader module for managing binary resources
- Include V2Ray and Xray configuration files and geodata (geoip.dat, geosite.dat)
- Update CLI imports to include path/filepath and time packages
- Improve user experience with core selection visibility and log diagnostics
2026-04-06 20:06:35 +06:00

213 lines
5.1 KiB
Go

package config
import (
"encoding/json"
"os"
"path/filepath"
)
var (
ConfigDir string
SubscriptionsFile string
ConfigsFile string
StateFile string
SettingsFile string
LogsDir string
XrayDir string
V2RayDir string
)
type WireGuardConfig struct {
Name string `json:"name"`
Config string `json:"config"`
}
type VLESSConfig struct {
Name string `json:"name"`
URL string `json:"url"`
Protocol string `json:"protocol,omitempty"`
Subscription string `json:"subscription,omitempty"`
}
type Configs struct {
WireGuard []WireGuardConfig `json:"wireguard"`
VLESS []VLESSConfig `json:"vless"`
}
type Subscription struct {
Name string `json:"name"`
URL string `json:"url"`
}
type Subscriptions struct {
Subscriptions []Subscription `json:"subscriptions"`
}
type ConnectionState struct {
Connected bool `json:"connected"`
ConfigName string `json:"config_name"`
ConfigType string `json:"config_type"`
StartTime string `json:"start_time"`
Interface string `json:"interface"`
ProcessPID int `json:"process_pid"`
LogFile string `json:"log_file"`
}
type Settings struct {
CoreType string `json:"core_type"` // "xray" или "v2ray"
}
// Init инициализирует конфигурационные директории и файлы
func Init() error {
// Получаем рабочую директорию
workDir, err := os.Getwd()
if err != nil {
return err
}
ConfigDir = filepath.Join(workDir, ".vpn_client")
SubscriptionsFile = filepath.Join(ConfigDir, "subscriptions.json")
ConfigsFile = filepath.Join(ConfigDir, "configs.json")
StateFile = filepath.Join(ConfigDir, "state.json")
SettingsFile = filepath.Join(ConfigDir, "settings.json")
LogsDir = filepath.Join(workDir, "logs")
XrayDir = filepath.Join(workDir, "xray")
V2RayDir = filepath.Join(workDir, "v2ray")
// Создаем директории
if err := os.MkdirAll(ConfigDir, 0755); err != nil {
return err
}
if err := os.MkdirAll(LogsDir, 0755); err != nil {
return err
}
// Инициализируем файлы если их нет
if err := initFileIfNotExists(SubscriptionsFile, Subscriptions{Subscriptions: []Subscription{}}); err != nil {
return err
}
if err := initFileIfNotExists(ConfigsFile, Configs{WireGuard: []WireGuardConfig{}, VLESS: []VLESSConfig{}}); err != nil {
return err
}
if err := initFileIfNotExists(StateFile, ConnectionState{}); err != nil {
return err
}
if err := initFileIfNotExists(SettingsFile, Settings{CoreType: "xray"}); err != nil {
return err
}
return nil
}
func initFileIfNotExists(path string, defaultData interface{}) error {
if _, err := os.Stat(path); os.IsNotExist(err) {
data, err := json.MarshalIndent(defaultData, "", " ")
if err != nil {
return err
}
return os.WriteFile(path, data, 0644)
}
return nil
}
// LoadConfigs загружает конфигурации
func LoadConfigs() (*Configs, error) {
data, err := os.ReadFile(ConfigsFile)
if err != nil {
return nil, err
}
var configs Configs
if err := json.Unmarshal(data, &configs); err != nil {
return nil, err
}
return &configs, nil
}
// SaveConfigs сохраняет конфигурации
func SaveConfigs(configs *Configs) error {
data, err := json.MarshalIndent(configs, "", " ")
if err != nil {
return err
}
return os.WriteFile(ConfigsFile, data, 0644)
}
// LoadSubscriptions загружает подписки
func LoadSubscriptions() (*Subscriptions, error) {
data, err := os.ReadFile(SubscriptionsFile)
if err != nil {
return nil, err
}
var subs Subscriptions
if err := json.Unmarshal(data, &subs); err != nil {
return nil, err
}
return &subs, nil
}
// SaveSubscriptions сохраняет подписки
func SaveSubscriptions(subs *Subscriptions) error {
data, err := json.MarshalIndent(subs, "", " ")
if err != nil {
return err
}
return os.WriteFile(SubscriptionsFile, data, 0644)
}
// LoadState загружает состояние подключения
func LoadState() (*ConnectionState, error) {
data, err := os.ReadFile(StateFile)
if err != nil {
return nil, err
}
var state ConnectionState
if err := json.Unmarshal(data, &state); err != nil {
return nil, err
}
return &state, nil
}
// SaveState сохраняет состояние подключения
func SaveState(state *ConnectionState) error {
data, err := json.MarshalIndent(state, "", " ")
if err != nil {
return err
}
return os.WriteFile(StateFile, data, 0644)
}
// LoadSettings загружает настройки
func LoadSettings() (*Settings, error) {
data, err := os.ReadFile(SettingsFile)
if err != nil {
return nil, err
}
var settings Settings
if err := json.Unmarshal(data, &settings); err != nil {
return nil, err
}
// По умолчанию xray
if settings.CoreType == "" {
settings.CoreType = "xray"
}
return &settings, nil
}
// SaveSettings сохраняет настройки
func SaveSettings(settings *Settings) error {
data, err := json.MarshalIndent(settings, "", " ")
if err != nil {
return err
}
return os.WriteFile(SettingsFile, data, 0644)
}