package global import ( "errors" "fmt" "os" "strconv" "strings" "github.com/jmoiron/sqlx" "github.com/pelletier/go-toml/v2" ) type ( dbConfig struct { Host string `toml:"host"` Name string `toml:"name"` User string `toml:"user"` Pass string `toml:"pass"` } discordConfig struct { AdminID string `toml:"admin_id" comment:"NOTE: admin_id to be deprecated in favour of local accounts and SSO."` ClientID string `toml:"client_id"` Secret string `toml:"secret"` } config struct { BaseUrl string `toml:"base_url" comment:"Used for OAuth redirects."` Port int64 `toml:"port"` DataDirectory string `toml:"data_dir"` DB dbConfig `toml:"db"` Discord discordConfig `toml:"discord"` } ) var Config = func() config { configFile := os.Getenv("ARIMELODY_CONFIG") if configFile == "" { configFile = "config.toml" } config := config{ BaseUrl: "https://arimelody.me", Port: 8080, } data, err := os.ReadFile(configFile) if err != nil { configOut, _ := toml.Marshal(&config) os.WriteFile(configFile, configOut, os.ModePerm) fmt.Printf( "A default config.toml has been created. " + "Please configure before running again!\n") os.Exit(0) } err = toml.Unmarshal([]byte(data), &config) if err != nil { fmt.Fprintf(os.Stderr, "FATAL: Failed to parse configuration file: %s\n", err.Error()) os.Exit(1) } err = handleConfigOverrides(&config) if err != nil { fmt.Fprintf(os.Stderr, "FATAL: Failed to parse environment variable %s\n", err.Error()) os.Exit(1) } return config }() func handleConfigOverrides(config *config) error { var err error if env, has := os.LookupEnv("ARIMELODY_BASE_URL"); has { config.BaseUrl = env } if env, has := os.LookupEnv("ARIMELODY_PORT"); has { config.Port, err = strconv.ParseInt(env, 10, 0) if err != nil { return errors.New("ARIMELODY_PORT: " + err.Error()) } } if env, has := os.LookupEnv("ARIMELODY_DATA_DIR"); has { config.DataDirectory = env } if env, has := os.LookupEnv("ARIMELODY_DB_HOST"); has { config.DB.Host = env } if env, has := os.LookupEnv("ARIMELODY_DB_NAME"); has { config.DB.Name = env } if env, has := os.LookupEnv("ARIMELODY_DB_USER"); has { config.DB.User = env } if env, has := os.LookupEnv("ARIMELODY_DB_PASS"); has { config.DB.Pass = env } if env, has := os.LookupEnv("ARIMELODY_DISCORD_ADMIN_ID"); has { config.Discord.AdminID = env } if env, has := os.LookupEnv("ARIMELODY_DISCORD_CLIENT_ID"); has { config.Discord.ClientID = env } if env, has := os.LookupEnv("ARIMELODY_DISCORD_SECRET"); has { config.Discord.Secret = env } return nil } var Args = func() map[string]string { args := map[string]string{} index := 0 for index < len(os.Args[1:]) { arg := os.Args[index + 1] if !strings.HasPrefix(arg, "-") { fmt.Printf("FATAL: Parameters must follow an argument (%s).\n", arg) os.Exit(1) } if index + 3 > len(os.Args) || strings.HasPrefix(os.Args[index + 2], "-") { args[arg[1:]] = "true" index += 1 continue } val := os.Args[index + 2] args[arg[1:]] = val // fmt.Printf("%s: %s\n", arg[1:], val) index += 2 } return args }() var DB *sqlx.DB