From 2e072224651f302873d0af57bdc607623a30e32a Mon Sep 17 00:00:00 2001 From: Vibe Kanban Date: Wed, 14 Jan 2026 20:31:32 +0300 Subject: [PATCH] =?UTF-8?q?1.=20=D0=9F=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=8F=D0=B4=D1=80=D0=B0=20Sing-box=20(vib?= =?UTF-8?q?e-kanban=2079e12836)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Создай папку `bin` в корне проекта. 2. Напиши логику на Go, которая проверяет наличие `bin/sing-box.exe`. 3. Напиши функцию `runSingBox(configPath string)`, которая запускает `sing-box.exe` как скрытый фоновый процесс (`os/exec`). 4. Реализуй корректное завершение процесса (Kill) при нажатии кнопки "Отключить". --- main.go | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 91383e6..4a6e6d9 100644 --- a/main.go +++ b/main.go @@ -1,28 +1,114 @@ package main import ( + "os" + "os/exec" + "path/filepath" + "syscall" + "fyne.io/fyne/v2/app" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/widget" "fyne.io/fyne/v2" ) +var currentProcess *exec.Cmd + +// checkSingBox checks if sing-box.exe exists in the bin folder +func checkSingBox() bool { + singBoxPath := filepath.Join("bin", "sing-box.exe") + if _, err := os.Stat(singBoxPath); os.IsNotExist(err) { + return false + } + return true +} + +// runSingBox starts the sing-box process with the given config path +func runSingBox(configPath string) error { + singBoxPath := filepath.Join("bin", "sing-box.exe") + + if !checkSingBox() { + return nil + } + + cmd := exec.Command(singBoxPath, "run", "-c", configPath) + + // Make the process run as hidden + cmd.SysProcAttr = &syscall.SysProcAttr{ + HideWindow: true, + } + + err := cmd.Start() + if err != nil { + return err + } + + currentProcess = cmd + return nil +} + +// killCurrentProcess terminates the current sing-box process if running +func killCurrentProcess() { + if currentProcess != nil && currentProcess.Process != nil { + currentProcess.Process.Kill() + currentProcess = nil + } +} + func main() { myApp := app.New() myWindow := myApp.NewWindow("Hamy VPN Client") myWindow.Resize(fyne.NewSize(200, 300)) var connectButton *widget.Button - connectButton = widget.NewButton("Подключить", func() { - connectLabel := widget.NewLabel("Подключение...") + var disconnectButton *widget.Button + + disconnectButton = widget.NewButton("Отключить", func() { + killCurrentProcess() + + statusLabel := widget.NewLabel("Отключено") myWindow.SetContent(container.NewVBox( connectButton, + disconnectButton, + statusLabel, + )) + }) + + connectButton = widget.NewButton("Подключить", func() { + // Check if sing-box exists + if !checkSingBox() { + errorLabel := widget.NewLabel("Файл bin/sing-box.exe не найден") + myWindow.SetContent(container.NewVBox( + connectButton, + disconnectButton, + errorLabel, + )) + return + } + + // Run sing-box with a sample config file + err := runSingBox("config.json") // Replace with actual config path + if err != nil { + errorLabel := widget.NewLabel("Ошибка подключения: " + err.Error()) + myWindow.SetContent(container.NewVBox( + connectButton, + disconnectButton, + errorLabel, + )) + return + } + + connectLabel := widget.NewLabel("Подключено") + myWindow.SetContent(container.NewVBox( + connectButton, + disconnectButton, connectLabel, )) }) myWindow.SetContent(container.NewVBox( connectButton, + disconnectButton, )) myWindow.ShowAndRun()