/* Copyright © 2023 Evan Fiordeliso */ package cmd import ( "errors" "fmt" "os" "github.com/spf13/cobra" "github.com/spf13/viper" "go.fifitido.net/ytdl-web/config" "golang.org/x/exp/slog" ) var ( cfgFile string cfg *config.Config rootCmd = &cobra.Command{ Use: "ytdl-web", Short: "A web frontend for yt-dlp", Long: `YTDL Web is a web application that grabs the links to videos from over a thousand websites using the yt-dlp project under the hood.`, } ) func Execute() error { return rootCmd.Execute() } func init() { cobra.OnInitialize(initConfig) rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $XDG_CONFIG_HOME/ytdl-web/config.yml)") rootCmd.PersistentFlags().IntP("port", "p", 8080, "port to listen on") rootCmd.PersistentFlags().StringP("listen", "l", "", "address to listen on") rootCmd.PersistentFlags().StringP("base-path", "b", "", "the base path, used when behind reverse proxy") rootCmd.PersistentFlags().StringP("ytdlp-path", "y", "", "the path to the yt-dlp binary, used when it is not in $PATH") rootCmd.PersistentFlags().BoolP("cookies-enabled", "C", false, "whether cookies are enabled") rootCmd.PersistentFlags().StringP("cookies", "c", "", "the path to the cookies file") // trunk-ignore-begin(golangci-lint/errcheck): Ignoring errors viper.BindPFlag("http.port", rootCmd.PersistentFlags().Lookup("port")) viper.BindPFlag("http.listen", rootCmd.PersistentFlags().Lookup("listen")) viper.BindPFlag("http.basePath", rootCmd.PersistentFlags().Lookup("base-path")) viper.BindPFlag("ytdlp.binaryPath", rootCmd.PersistentFlags().Lookup("ytdlp-path")) viper.BindPFlag("cookies.enabled", rootCmd.PersistentFlags().Lookup("cookies-enabled")) viper.BindPFlag("cookies.filePath", rootCmd.PersistentFlags().Lookup("cookies")) // trunk-ignore-end(golangci-lint/errcheck) } func initConfig() { var err error if cfgFile != "" { cfg, err = config.LoadConfig(cfgFile) } else { cfg, err = config.LoadConfig() } notFound := &viper.ConfigFileNotFoundError{} switch { case err != nil && !errors.As(err, notFound): cobra.CheckErr(err) case err != nil && errors.As(err, notFound): // The config file is optional, we shouldn't exit when the config is not found break default: fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) } } func initLogging() { var handler slog.Handler if cfg.IsProduction() { handler = slog.HandlerOptions{ AddSource: true, Level: slog.LevelInfo, }.NewJSONHandler(os.Stdout) } else { handler = slog.HandlerOptions{ AddSource: true, Level: slog.LevelDebug, }.NewTextHandler(os.Stdout) } slog.SetDefault(slog.New(handler)) }