1
0
Fork 0
mirror of https://codeberg.org/june64/mrvc.git synced 2026-01-10 16:06:33 +01:00
mrvc/config/config.go

151 lines
5.5 KiB
Go

package config
import (
"errors"
"flag"
"fmt"
"log"
"os"
"strconv"
"time"
)
type rooms []string
type configOption[T any] struct {
flagName string
flagDefaultValue T
flagHelpBase string
envVarName string
}
type configOptions struct {
userID configOption[string]
token configOption[string]
rooms configOption[rooms]
recursive configOption[bool]
printHomeserverMemberCount configOption[bool]
homeserverVersionInfoTimeout configOption[time.Duration]
}
type Config struct {
UserID string
Token string
Rooms rooms
Recursive bool
PrintHomeserverMemberCount bool
HomeserverVersionInfoTimeout time.Duration
}
var configOpts = configOptions{
userID: configOption[string]{"user-id", "", "The Matrix user ID to use.", "MRVC_USER_ID"},
token: configOption[string]{"token", "", "The Matrix access token to use.", "MRVC_TOKEN"},
rooms: configOption[rooms]{"room", []string{}, "The Matrix room to check. The flag can be set multiple times to check multiple rooms.", "MRVC_ROOM"},
recursive: configOption[bool]{"recursive", false, "Recursively check the child rooms for the given rooms (spaces) as well.", "MRVC_RECURSIVE"},
printHomeserverMemberCount: configOption[bool]{"print-homeserver-member-count", false, "Print the member count for each homeserver.", "MRVC_PRINT_HOMESERVER_MEMBER_COUNT"},
homeserverVersionInfoTimeout: configOption[time.Duration]{"homeserver-version-info-timeout", time.Second * 5, "Timeout for getting the homeservers version information per homeserver.", "MRVC_HOMESERVER_VERSION_INFO_TIMEOUT"},
}
func (r *rooms) String() string {
return fmt.Sprint(*r)
}
func (r *rooms) Set(value string) error {
*r = append(*r, value)
return nil
}
func (configOpt configOption[T]) getFlagHelp() string {
return fmt.Sprintf("%s (EnvVar: %s)", configOpt.flagHelpBase, configOpt.envVarName)
}
func (configOpt configOption[T]) getFlagArgs() (string, T, string) {
return configOpt.flagName, configOpt.flagDefaultValue, configOpt.getFlagHelp()
}
// Functions for getting config values from flags and environment variables.
// Flags take precedence over environment variables.
func (configOpt configOption[T]) getConfigValueWithDefault(configFlag *T, visitedFlags map[string]bool, envVarParser func(string) T) T {
if visitedFlags[configOpt.flagName] {
return *configFlag
} else if envVar, ok := os.LookupEnv(configOpt.envVarName); ok {
return envVarParser(envVar)
} else {
return configOpt.flagDefaultValue
}
}
// This function can be used to ensure some configuration options got explicitly set.
func (configOpt configOption[T]) getConfigValueWithError(configFlag *T, visitedFlags map[string]bool, envVarParser func(string) T) (T, error) {
if visitedFlags[configOpt.flagName] {
return *configFlag, nil
} else if envVar, ok := os.LookupEnv(configOpt.envVarName); ok {
return envVarParser(envVar), nil
} else {
return configOpt.flagDefaultValue, errors.New("no command-line flag or environment variable set")
}
}
var userIdFlag = flag.String(configOpts.userID.getFlagArgs())
var tokenFlag = flag.String(configOpts.token.getFlagArgs())
var recursiveFlag = flag.Bool(configOpts.recursive.getFlagArgs())
var printHomeserverMemberCountFlag = flag.Bool(configOpts.printHomeserverMemberCount.getFlagArgs())
var homeserverVersionInfoTimeoutFlag = flag.Duration(configOpts.homeserverVersionInfoTimeout.getFlagArgs())
var roomsFlag rooms
func init() {
flag.Var(&roomsFlag, configOpts.rooms.flagName, configOpts.rooms.getFlagHelp())
}
func Get() Config {
flag.Parse()
var config Config
visitedFlags := make(map[string]bool)
flag.Visit(func(flag *flag.Flag) {
visitedFlags[flag.Name] = true
})
var err error
config.UserID, err = configOpts.userID.getConfigValueWithError(userIdFlag, visitedFlags, func(envVar string) string { return envVar })
if err != nil {
log.Fatal("A Matrix user ID must be provided.")
}
config.Token, err = configOpts.token.getConfigValueWithError(tokenFlag, visitedFlags, func(envVar string) string { return envVar })
if err != nil {
log.Fatal("A Matrix access token must be provided.")
}
config.Rooms, err = configOpts.rooms.getConfigValueWithError(&roomsFlag, visitedFlags, func(envVar string) rooms { return []string{envVar} })
if err != nil {
log.Fatal("A Matrix room must be provided.")
}
config.Recursive = configOpts.recursive.getConfigValueWithDefault(recursiveFlag, visitedFlags, func(envVar string) bool {
parsedEnvVar, err := strconv.ParseBool(envVar)
if err != nil {
log.Printf("Error parsing %s:\n", configOpts.recursive.envVarName)
log.Fatal(err)
}
return parsedEnvVar
})
config.PrintHomeserverMemberCount = configOpts.printHomeserverMemberCount.getConfigValueWithDefault(printHomeserverMemberCountFlag, visitedFlags, func(envVar string) bool {
parsedEnvVar, err := strconv.ParseBool(envVar)
if err != nil {
log.Printf("Error parsing %s:\n", configOpts.printHomeserverMemberCount.envVarName)
log.Fatal(err)
}
return parsedEnvVar
})
config.HomeserverVersionInfoTimeout = configOpts.homeserverVersionInfoTimeout.getConfigValueWithDefault(homeserverVersionInfoTimeoutFlag, visitedFlags, func(envVar string) time.Duration {
parsedEnvVar, err := time.ParseDuration(envVar)
if err != nil {
log.Printf("Error parsing %s:\n", configOpts.homeserverVersionInfoTimeout.envVarName)
log.Fatal(err)
}
return parsedEnvVar
})
return config
}