package main import ( "context" "flag" "fmt" "os" "os/signal" "path/filepath" "syscall" "time" "git.warky.dev/wdevs/whatshooked/pkg/logging" "git.warky.dev/wdevs/whatshooked/pkg/whatshooked" ) var ( configPath = flag.String("config", "", "Path to configuration file (optional, defaults to user home directory)") ) // resolveConfigPath determines the config file path to use // Priority: 1) provided path (if exists), 2) config.json in current dir, 3) .whatshooked/config.json in user home func resolveConfigPath(providedPath string) (string, error) { // If a path was explicitly provided, check if it exists if providedPath != "" { if _, err := os.Stat(providedPath); err == nil { return providedPath, nil } // Directory doesn't exist, fall through to default locations fmt.Fprintf(os.Stderr, "Provided config path directory does not exist, using default locations: %s\n", providedPath) } // Check for config.json in current directory currentDirConfig := "config.json" if _, err := os.Stat(currentDirConfig); err == nil { return currentDirConfig, nil } // Fall back to user home directory homeDir, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("failed to get user home directory: %w", err) } // Create .whatshooked directory if it doesn't exist configDir := filepath.Join(homeDir, ".whatshooked") if err := os.MkdirAll(configDir, 0755); err != nil { return "", fmt.Errorf("failed to create config directory: %w", err) } return filepath.Join(configDir, "config.json"), nil } func main() { flag.Parse() // Resolve config path cfgPath, err := resolveConfigPath(*configPath) if err != nil { fmt.Fprintf(os.Stderr, "Failed to resolve config path: %v\n", err) os.Exit(1) } // Create WhatsHooked instance from config file wh, err := whatshooked.NewFromFile(cfgPath) if err != nil { fmt.Fprintf(os.Stderr, "Failed to initialize WhatsHooked from %s: %v\n", cfgPath, err) os.Exit(1) } logging.Info("Starting WhatsHooked server", "config_path", cfgPath) // Start the built-in HTTP server (non-blocking goroutine) go func() { if err := wh.StartServer(); err != nil { logging.Error("HTTP server error", "error", err) } }() // Wait for interrupt signal sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) <-sigChan logging.Info("Shutting down server") // Graceful shutdown shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() // Stop server if err := wh.StopServer(shutdownCtx); err != nil { logging.Error("Error stopping server", "error", err) } // Close WhatsHooked (disconnects WhatsApp, closes event logger, etc.) if err := wh.Close(); err != nil { logging.Error("Error closing WhatsHooked", "error", err) } logging.Info("Server stopped") }