package main import ( "embed" "fmt" "io/fs" "log" "net" "net/http" "os" "os/exec" "os/signal" "syscall" "github.com/muyue/muyue/internal/api" "github.com/muyue/muyue/internal/config" "github.com/muyue/muyue/internal/version" ) //go:embed frontend/dist/* var frontendFS embed.FS func main() { if len(os.Args) > 1 && os.Args[1] == "--help" { fmt.Printf("%s Desktop v%s\n", version.Name, version.Version) fmt.Println("Usage: muyue-desktop [options]") fmt.Println() fmt.Println("Options:") fmt.Println(" --help Show this help") fmt.Println(" --port Specify port (default: auto)") fmt.Println(" --no-open Don't open browser") return } cfg := loadConfig() srv := api.NewServer(cfg) listener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { log.Fatalf("Failed to bind: %v", err) } addr := listener.Addr().(*net.TCPAddr) port := addr.Port frontendDist, err := fs.Sub(frontendFS, "frontend/dist") if err != nil { log.Fatalf("Failed to load frontend: %v", err) } fileServer := http.FileServer(http.FS(frontendDist)) mux := http.NewServeMux() mux.Handle("/api/", srv) mux.Handle("/", fileServer) go func() { log.Printf("%s Desktop v%s", version.Name, version.Version) log.Printf("Listening on http://127.0.0.1:%d", port) if err := http.Serve(listener, mux); err != nil { log.Fatalf("Server error: %v", err) } }() noOpen := false for _, arg := range os.Args[1:] { if arg == "--no-open" { noOpen = true } } if !noOpen { url := fmt.Sprintf("http://127.0.0.1:%d", port) openBrowser(url) log.Printf("Opened %s in browser", url) } quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit log.Println("Shutting down...") } func loadConfig() *config.MuyueConfig { if !config.Exists() { fmt.Println("No config found. Run `muyue setup` first.") os.Exit(1) } cfg, err := config.Load() if err != nil { fmt.Fprintf(os.Stderr, "Config error: %v\n", err) os.Exit(1) } return cfg } func openBrowser(url string) { var cmd *exec.Cmd switch { case commandExists("xdg-open"): cmd = exec.Command("xdg-open", url) case commandExists("open"): cmd = exec.Command("open", url) case commandExists("cmd"): cmd = exec.Command("cmd", "/c", "start", url) default: fmt.Printf("Open manually: %s\n", url) return } cmd.Start() } func commandExists(name string) bool { _, err := exec.LookPath(name) return err == nil }