1. Подготовка ядра Sing-box (vibe-kanban 79e12836)

1. Создай папку `bin` в корне проекта.
2. Напиши логику на Go, которая проверяет наличие `bin/sing-box.exe`.
3. Напиши функцию `runSingBox(configPath string)`, которая запускает `sing-box.exe` как скрытый фоновый процесс (`os/exec`).
4. Реализуй корректное завершение процесса (Kill) при нажатии кнопки "Отключить".
This commit is contained in:
Vibe Kanban
2026-01-14 20:31:32 +03:00
parent ef6bfdf5d6
commit 2e07222465

90
main.go
View File

@@ -1,28 +1,114 @@
package main package main
import ( import (
"os"
"os/exec"
"path/filepath"
"syscall"
"fyne.io/fyne/v2/app" "fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"fyne.io/fyne/v2" "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() { func main() {
myApp := app.New() myApp := app.New()
myWindow := myApp.NewWindow("Hamy VPN Client") myWindow := myApp.NewWindow("Hamy VPN Client")
myWindow.Resize(fyne.NewSize(200, 300)) myWindow.Resize(fyne.NewSize(200, 300))
var connectButton *widget.Button var connectButton *widget.Button
connectButton = widget.NewButton("Подключить", func() { var disconnectButton *widget.Button
connectLabel := widget.NewLabel("Подключение...")
disconnectButton = widget.NewButton("Отключить", func() {
killCurrentProcess()
statusLabel := widget.NewLabel("Отключено")
myWindow.SetContent(container.NewVBox( myWindow.SetContent(container.NewVBox(
connectButton, 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, connectLabel,
)) ))
}) })
myWindow.SetContent(container.NewVBox( myWindow.SetContent(container.NewVBox(
connectButton, connectButton,
disconnectButton,
)) ))
myWindow.ShowAndRun() myWindow.ShowAndRun()