package app import ( "errors" "flag" "fmt" "io" "os" "path/filepath" "runtime" "strings" "time" "github.com/AlexxIT/go2rtc/pkg/shell" "github.com/AlexxIT/go2rtc/pkg/yaml" "github.com/rs/zerolog" "github.com/rs/zerolog/log" ) var Version = "1.8.4" var UserAgent = "go2rtc/" + Version var ConfigPath string var Info = map[string]any{ "version": Version, } func Init() { var confs Config var version bool flag.Var(&confs, "config", "go2rtc config (path to file or raw text), support multiple") flag.BoolVar(&version, "version", false, "Print the version of the application and exit") flag.Parse() if version { fmt.Println("Current version: ", Version) os.Exit(0) } if confs == nil { confs = []string{"go2rtc.yaml"} } for _, conf := range confs { if conf[0] != '{' { // config as file if ConfigPath == "" { ConfigPath = conf } data, _ := os.ReadFile(conf) if data == nil { continue } data = []byte(shell.ReplaceEnvVars(string(data))) configs = append(configs, data) } else { // config as raw YAML configs = append(configs, []byte(conf)) } } if ConfigPath != "" { if !filepath.IsAbs(ConfigPath) { if cwd, err := os.Getwd(); err == nil { ConfigPath = filepath.Join(cwd, ConfigPath) } } Info["config_path"] = ConfigPath } var cfg struct { Mod map[string]string `yaml:"log"` } LoadConfig(&cfg) log.Logger = NewLogger(cfg.Mod["format"], cfg.Mod["level"]) modules = cfg.Mod log.Info().Msgf("go2rtc version %s %s/%s", Version, runtime.GOOS, runtime.GOARCH) migrateStore() } func NewLogger(format string, level string) zerolog.Logger { var writer io.Writer = os.Stdout if format != "json" { writer = zerolog.ConsoleWriter{ Out: writer, TimeFormat: "15:04:05.000", NoColor: writer != os.Stdout || format == "text", } } zerolog.TimeFieldFormat = time.RFC3339Nano lvl, err := zerolog.ParseLevel(level) if err != nil || lvl == zerolog.NoLevel { lvl = zerolog.InfoLevel } return zerolog.New(writer).With().Timestamp().Logger().Level(lvl) } func LoadConfig(v any) { for _, data := range configs { if err := yaml.Unmarshal(data, v); err != nil { log.Warn().Err(err).Msg("[app] read config") } } } func GetLogger(module string) zerolog.Logger { if s, ok := modules[module]; ok { lvl, err := zerolog.ParseLevel(s) if err == nil { return log.Level(lvl) } log.Warn().Err(err).Caller().Send() } return log.Logger } func PatchConfig(key string, value any, path ...string) error { if ConfigPath == "" { return errors.New("config file disabled") } // empty config is OK b, _ := os.ReadFile(ConfigPath) b, err := yaml.Patch(b, key, value, path...) if err != nil { return err } return os.WriteFile(ConfigPath, b, 0644) } // internal type Config []string func (c *Config) String() string { return strings.Join(*c, " ") } func (c *Config) Set(value string) error { *c = append(*c, value) return nil } var configs [][]byte // modules log levels var modules map[string]string