refactor: 优化代码质量,遵循 KISS 原则

- 移除自签证书回退逻辑,简化为仅使用 AnyIP 证书
- 删除 internal/tls/generate.go(不再需要)
- 重构 main.go:提取初始化逻辑,main() 从 156 行降至 13 行
- 重构 internal/ws/handler.go:提取消息处理,handleConn() 从 131 行降至 25 行
- 重构 internal/config/load.go:使用 map 驱动消除重复代码
- 优化前端 startRecording():使用标准 AbortController API
- 优化前端 showToast():预定义 DOM 元素,代码减少 50%

代码行数减少 90 行,复杂度显著降低,所有构建通过
This commit is contained in:
2026-03-02 00:25:14 +08:00
parent 8c7b9b45fd
commit b87fead2fd
8 changed files with 316 additions and 371 deletions

142
main.go
View File

@@ -22,99 +22,133 @@ var webFS embed.FS
var version = "dev"
func main() {
initLogger()
slog.Info("VoicePaste", "version", version)
cfg := mustLoadConfig()
config.WatchAndReload("")
initClipboard()
lanIPs := mustDetectLANIPs()
lanIP := lanIPs[0]
tlsResult, scheme := setupTLS(cfg, lanIP)
printBanner(cfg, tlsResult, lanIPs, scheme)
srv := createServer(cfg, lanIP, tlsResult)
runWithGracefulShutdown(srv)
}
func initLogger() {
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
Level: slog.LevelInfo,
})))
}
slog.Info("VoicePaste", "version", version)
// Load config
func mustLoadConfig() config.Config {
cfg, err := config.Load("")
if err != nil {
slog.Error("failed to load config", "error", err)
os.Exit(1)
}
return cfg
}
// Start config hot-reload watcher
config.WatchAndReload("")
// Initialize clipboard
func initClipboard() {
if err := paste.Init(); err != nil {
slog.Warn("clipboard init failed, paste will be unavailable", "err", err)
}
// Detect LAN IPs
}
func mustDetectLANIPs() []string {
lanIPs, err := server.GetLANIPs()
if err != nil {
slog.Error("failed to detect LAN IP", "error", err)
os.Exit(1)
}
lanIP := lanIPs[0] // Use first IP for TLS and server binding
return lanIPs
}
// Read token from config (empty = no auth required)
token := cfg.Security.Token
// TLS setup
var tlsResult *vpTLS.Result
scheme := "http"
host := lanIP
if cfg.Server.TLSAuto {
var err error
tlsResult, err = vpTLS.GetTLSConfig(lanIP)
if err != nil {
slog.Error("TLS setup failed", "error", err)
os.Exit(1)
}
scheme = "https"
host = tlsResult.Host
func setupTLS(cfg config.Config, lanIP string) (*vpTLS.Result, string) {
if !cfg.Server.TLSAuto {
return nil, "http"
}
tlsResult, err := vpTLS.GetTLSConfig(lanIP)
if err != nil {
slog.Error("TLS setup failed", "error", err)
os.Exit(1)
}
return tlsResult, "https"
}
// Print connection info
func printBanner(cfg config.Config, tlsResult *vpTLS.Result, lanIPs []string, scheme string) {
fmt.Println()
fmt.Println("╔══════════════════════════════════════╗")
fmt.Println("║ VoicePaste 就绪 ║")
fmt.Println("╚══════════════════════════════════════╝")
fmt.Println()
// Print all accessible addresses
printAddresses(cfg, tlsResult, lanIPs, scheme)
printCertInfo(tlsResult, cfg.Server.TLSAuto)
printAuthInfo(cfg.Security.Token)
fmt.Println()
fmt.Println(" 在手机浏览器中打开上方地址")
fmt.Println(" 按 Ctrl+C 停止服务")
fmt.Println()
}
func printAddresses(cfg config.Config, tlsResult *vpTLS.Result, lanIPs []string, scheme string) {
token := cfg.Security.Token
if len(lanIPs) == 1 {
host := lanIP(tlsResult, lanIPs[0])
fmt.Printf(" 地址: %s\n", buildURL(scheme, host, cfg.Server.Port, token))
} else {
fmt.Println(" 地址:")
for _, ip := range lanIPs {
h := ip
if tlsResult != nil && tlsResult.AnyIP {
h = vpTLS.AnyIPHost(ip)
}
fmt.Printf(" - %s\n", buildURL(scheme, h, cfg.Server.Port, token))
}
return
}
if tlsResult != nil && tlsResult.AnyIP {
fmt.Println(" 地址:")
for _, ip := range lanIPs {
host := lanIP(tlsResult, ip)
fmt.Printf(" - %s\n", buildURL(scheme, host, cfg.Server.Port, token))
}
}
func lanIP(tlsResult *vpTLS.Result, ip string) string {
if tlsResult != nil {
return vpTLS.AnyIPHost(ip)
}
return ip
}
func printCertInfo(tlsResult *vpTLS.Result, tlsAuto bool) {
if tlsResult != nil {
fmt.Println(" 证书: AnyIP浏览器信任")
} else if cfg.Server.TLSAuto {
fmt.Println(" 证书: 自签名(浏览器会警告")
} else if tlsAuto {
fmt.Println(" 证书: 配置错误TLS 启用但未获取证书")
}
}
func printAuthInfo(token string) {
if token != "" {
fmt.Println(" 认证: 已启用")
} else {
fmt.Println(" 认证: 未启用(无需 token")
}
fmt.Println()
fmt.Println(" 在手机浏览器中打开上方地址")
fmt.Println(" 按 Ctrl+C 停止服务")
fmt.Println()
// Create and start server
}
func createServer(cfg config.Config, lanIP string, tlsResult *vpTLS.Result) *server.Server {
webContent, _ := fs.Sub(webFS, "web/dist")
var serverTLSCfg *crypto_tls.Config
var tlsConfig *crypto_tls.Config
if tlsResult != nil {
serverTLSCfg = tlsResult.Config
tlsConfig = tlsResult.Config
}
srv := server.New(token, lanIP, webContent, serverTLSCfg)
// Build ASR factory from config
srv := server.New(cfg.Security.Token, lanIP, webContent, tlsConfig)
asrFactory := buildASRFactory(cfg)
wsHandler := ws.NewHandler(cfg.Security.Token, paste.Paste, asrFactory)
wsHandler.Register(srv.App())
return srv
}
func buildASRFactory(cfg config.Config) func(chan<- ws.ServerMsg) (func([]byte), func(), error) {
asrCfg := asr.Config{
AppID: cfg.Doubao.AppID,
AccessToken: cfg.Doubao.AccessToken,
ResourceID: cfg.Doubao.ResourceID,
ResourceID: cfg.Doubao.ResourceID,
}
asrFactory := func(resultCh chan<- ws.ServerMsg) (func([]byte), func(), error) {
return func(resultCh chan<- ws.ServerMsg) (func([]byte), func(), error) {
client, err := asr.Dial(asrCfg, resultCh)
if err != nil {
return nil, nil, err
@@ -129,12 +163,9 @@ func main() {
}
return sendAudio, cleanup, nil
}
}
// Register WebSocket handler
wsHandler := ws.NewHandler(token, paste.Paste, asrFactory)
wsHandler.Register(srv.App())
// Graceful shutdown
func runWithGracefulShutdown(srv *server.Server) {
go func() {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
@@ -142,7 +173,6 @@ func main() {
slog.Info("shutting down...")
srv.Shutdown()
}()
if err := srv.Start(); err != nil {
slog.Error("server error", "error", err)
os.Exit(1)