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
This commit is contained in:
@@ -3,7 +3,8 @@ package cli
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
@@ -25,20 +26,22 @@ func MonitorConnection() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Println("Нажмите Ctrl+C для выхода из мониторинга\n")
|
||||
fmt.Println("Нажмите 'q' или Ctrl+C для выхода из мониторинга\n")
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// Создаем канал для обработки сигналов
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
// Создаем канал для остановки мониторинга
|
||||
stopChan := make(chan bool, 1)
|
||||
|
||||
// Запускаем горутину для обработки сигналов
|
||||
// Запускаем горутину для чтения клавиш
|
||||
go func() {
|
||||
<-sigChan
|
||||
stopChan <- true
|
||||
for {
|
||||
var input string
|
||||
fmt.Scanln(&input)
|
||||
if strings.ToLower(input) == "q" || strings.ToLower(input) == "й" {
|
||||
stopChan <- true
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Запускаем мониторинг
|
||||
@@ -50,9 +53,8 @@ func MonitorConnection() error {
|
||||
case <-ticker.C:
|
||||
clearScreen()
|
||||
displayRealtimeStatus(state)
|
||||
fmt.Printf("\n%s Нажмите 'q' и Enter для выхода\n", cyan("ℹ"))
|
||||
case <-stopChan:
|
||||
// Восстанавливаем обработку сигналов по умолчанию
|
||||
signal.Reset(os.Interrupt, syscall.SIGTERM)
|
||||
fmt.Println("\n\nВыход из мониторинга...")
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
return nil
|
||||
@@ -104,7 +106,7 @@ func displayRealtimeStatus(state *config.ConnectionState) {
|
||||
}
|
||||
|
||||
fmt.Println(strings.Repeat("═", 70))
|
||||
fmt.Printf("\n%s Обновление каждую секунду | Нажмите Ctrl+C для выхода\n",
|
||||
fmt.Printf("\n%s Нажмите 'q' и Enter для выхода\n",
|
||||
cyan("ℹ"))
|
||||
}
|
||||
|
||||
@@ -126,17 +128,39 @@ func displayVLESSStats(state *config.ConnectionState) {
|
||||
}
|
||||
}
|
||||
|
||||
// Проверяем, что процесс еще работает
|
||||
// Проверяем, что процесс еще работает (улучшенная проверка для Windows)
|
||||
if state.ProcessPID > 0 {
|
||||
process, err := os.FindProcess(state.ProcessPID)
|
||||
if err == nil {
|
||||
if err := process.Signal(os.Signal(nil)); err != nil {
|
||||
fmt.Printf("\n%s Процесс Xray не отвечает!\n", red("⚠"))
|
||||
}
|
||||
processRunning := checkProcessRunning(state.ProcessPID)
|
||||
if !processRunning {
|
||||
fmt.Printf("\n%s Процесс Xray не отвечает!\n", red("⚠"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checkProcessRunning проверяет, работает ли процесс
|
||||
func checkProcessRunning(pid int) bool {
|
||||
process, err := os.FindProcess(pid)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// На Windows FindProcess всегда успешен, нужна дополнительная проверка
|
||||
// Пытаемся получить информацию о процессе через tasklist
|
||||
if runtime.GOOS == "windows" {
|
||||
cmd := exec.Command("tasklist", "/FI", fmt.Sprintf("PID eq %d", pid), "/NH")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// Если процесс существует, в выводе будет его PID
|
||||
return strings.Contains(string(output), fmt.Sprintf("%d", pid))
|
||||
}
|
||||
|
||||
// На Unix используем сигнал 0
|
||||
err = process.Signal(syscall.Signal(0))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func displayWireGuardStats(state *config.ConnectionState) {
|
||||
fmt.Println("\n" + bold("WireGuard Туннель"))
|
||||
fmt.Printf("Интерфейс: %s\n", state.Interface)
|
||||
@@ -198,7 +222,8 @@ func ShowQuickStatus() string {
|
||||
duration := time.Since(startTime)
|
||||
hours := int(duration.Hours())
|
||||
minutes := int(duration.Minutes()) % 60
|
||||
timeStr = fmt.Sprintf(" [%02d:%02d]", hours, minutes)
|
||||
seconds := int(duration.Seconds()) % 60
|
||||
timeStr = fmt.Sprintf(" [%02d:%02d:%02d]", hours, minutes, seconds)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user