navidrome/conf/configuration.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

264 lines
7.6 KiB
Go
Raw Normal View History

2016-03-30 06:05:57 +02:00
package conf
import (
"fmt"
2016-03-30 06:05:57 +02:00
"os"
"path/filepath"
"strings"
2020-07-02 22:41:54 +02:00
"time"
2016-03-30 06:05:57 +02:00
2020-10-25 03:55:19 +01:00
"github.com/kr/pretty"
2020-01-24 01:44:08 +01:00
"github.com/navidrome/navidrome/consts"
"github.com/navidrome/navidrome/log"
"github.com/robfig/cron/v3"
2020-07-02 22:34:21 +02:00
"github.com/spf13/viper"
2016-03-30 06:05:57 +02:00
)
2020-07-02 23:21:25 +02:00
type configOptions struct {
2020-07-02 22:34:21 +02:00
ConfigFile string
Address string
2020-07-02 22:34:21 +02:00
Port int
MusicFolder string
DataFolder string
DbPath string
LogLevel string
2020-07-02 22:41:54 +02:00
ScanInterval time.Duration
ScanSchedule string
2020-07-02 22:41:54 +02:00
SessionTimeout time.Duration
2020-07-02 22:34:21 +02:00
BaseURL string
UILoginBackgroundURL string
EnableTranscodingConfig bool
EnableDownloads bool
2020-07-02 22:34:21 +02:00
TranscodingCacheSize string
ImageCacheSize string
2020-08-03 05:17:13 +02:00
AutoImportPlaylists bool
SearchFullString bool
RecentlyAddedByModTime bool
IgnoredArticles string
IndexGroups string
ProbeCommand string
CoverArtPriority string
CoverJpegQuality int
UIWelcomeMessage string
EnableGravatar bool
EnableFavourites bool
EnableStarRating bool
EnableUserEditing bool
2021-04-18 19:51:00 +02:00
DefaultTheme string
GATrackingID string
EnableLogRedacting bool
AuthRequestLimit int
AuthWindowLength time.Duration
PasswordEncryptionKey string
ReverseProxyUserHeader string
ReverseProxyWhitelist string
Scanner scannerOptions
2021-02-07 22:46:15 +01:00
Agents string
LastFM lastfmOptions
Spotify spotifyOptions
// DevFlags. These are used to enable/disable debugging and incomplete features
2020-07-02 22:34:21 +02:00
DevLogSourceLine bool
DevAutoCreateAdminPassword string
DevAutoLoginUsername string
DevPreCacheAlbumArtwork bool
DevFastAccessCoverArt bool
2020-11-05 05:25:38 +01:00
DevOldCacheLayout bool
DevActivityPanel bool
DevEnableShare bool
DevEnableScrobble bool
2016-03-30 06:05:57 +02:00
}
type scannerOptions struct {
Extractor string
}
type lastfmOptions struct {
Enabled bool
ApiKey string
Secret string
Language string
}
type spotifyOptions struct {
ID string
Secret string
}
2021-02-07 22:46:15 +01:00
var (
Server = &configOptions{}
hooks []func()
)
2020-01-08 16:25:23 +01:00
2020-07-02 22:34:21 +02:00
func LoadFromFile(confFile string) {
viper.SetConfigFile(confFile)
Load()
}
2020-07-02 22:34:21 +02:00
func Load() {
err := viper.Unmarshal(&Server)
if err != nil {
2020-07-02 22:34:21 +02:00
fmt.Println("Error parsing config:", err)
os.Exit(1)
}
err = os.MkdirAll(Server.DataFolder, os.ModePerm)
if err != nil {
fmt.Println("Error creating data path:", "path", Server.DataFolder, err)
os.Exit(1)
}
2020-07-02 22:34:21 +02:00
Server.ConfigFile = viper.GetViper().ConfigFileUsed()
if Server.DbPath == "" {
Server.DbPath = filepath.Join(Server.DataFolder, consts.DefaultDbPath)
}
2020-07-02 22:34:21 +02:00
log.SetLevelString(Server.LogLevel)
log.SetLogSourceLine(Server.DevLogSourceLine)
log.SetRedacting(Server.EnableLogRedacting)
if err := validateScanSchedule(); err != nil {
os.Exit(1)
}
// Print current configuration if log level is Debug
if log.CurrentLevel() >= log.LevelDebug {
prettyConf := pretty.Sprintf("Loaded configuration from '%s': %# v", Server.ConfigFile, Server)
if Server.EnableLogRedacting {
prettyConf = log.Redact(prettyConf)
}
fmt.Println(prettyConf)
}
2021-02-07 22:46:15 +01:00
// Call init hooks
for _, hook := range hooks {
hook()
}
}
func validateScanSchedule() error {
if Server.ScanInterval != -1 {
log.Warn("ScanInterval is DEPRECATED. Please use ScanSchedule. See docs at https://navidrome.org/docs/usage/configuration-options/")
if Server.ScanSchedule != "@every 1m" {
log.Error("You cannot specify both ScanInterval and ScanSchedule, ignoring ScanInterval")
} else {
if Server.ScanInterval == 0 {
Server.ScanSchedule = ""
} else {
Server.ScanSchedule = fmt.Sprintf("@every %s", Server.ScanInterval)
}
log.Warn("Setting ScanSchedule", "schedule", Server.ScanSchedule)
}
}
2021-05-07 02:49:26 +02:00
if Server.ScanSchedule == "" {
return nil
}
if _, err := time.ParseDuration(Server.ScanSchedule); err == nil {
Server.ScanSchedule = "@every " + Server.ScanSchedule
}
c := cron.New()
_, err := c.AddFunc(Server.ScanSchedule, func() {})
if err != nil {
log.Error("Invalid ScanSchedule. Please read format spec at https://pkg.go.dev/github.com/robfig/cron#hdr-CRON_Expression_Format", "schedule", Server.ScanSchedule, err)
}
2021-05-07 02:49:26 +02:00
return err
}
2021-02-07 22:46:15 +01:00
// AddHook is used to register initialization code that should run as soon as the config is loaded
func AddHook(hook func()) {
hooks = append(hooks, hook)
2016-03-30 06:05:57 +02:00
}
2020-07-02 23:21:25 +02:00
func init() {
2020-07-28 14:49:07 +02:00
viper.SetDefault("musicfolder", filepath.Join(".", "music"))
viper.SetDefault("datafolder", ".")
2020-07-02 22:34:21 +02:00
viper.SetDefault("loglevel", "info")
viper.SetDefault("address", "0.0.0.0")
2020-07-02 22:34:21 +02:00
viper.SetDefault("port", 4533)
2020-07-02 22:41:54 +02:00
viper.SetDefault("sessiontimeout", consts.DefaultSessionTimeout)
viper.SetDefault("scaninterval", -1)
viper.SetDefault("scanschedule", "@every 1m")
2020-07-02 22:34:21 +02:00
viper.SetDefault("baseurl", "")
2021-03-24 15:21:31 +01:00
viper.SetDefault("uiloginbackgroundurl", consts.DefaultUILoginBackgroundURL)
2020-07-02 22:34:21 +02:00
viper.SetDefault("enabletranscodingconfig", false)
viper.SetDefault("transcodingcachesize", "100MB")
viper.SetDefault("imagecachesize", "100MB")
2020-08-03 05:17:13 +02:00
viper.SetDefault("autoimportplaylists", true)
viper.SetDefault("enabledownloads", true)
2020-07-02 22:34:21 +02:00
// Config options only valid for file/env configuration
viper.SetDefault("searchfullstring", false)
viper.SetDefault("recentlyaddedbymodtime", false)
2020-07-02 22:34:21 +02:00
viper.SetDefault("ignoredarticles", "The El La Los Las Le Les Os As O A")
viper.SetDefault("indexgroups", "A B C D E F G H I J K L M N O P Q R S T U V W X-Z(XYZ) [Unknown]([)")
viper.SetDefault("probecommand", "ffmpeg %s -f ffmetadata")
viper.SetDefault("coverartpriority", "embedded, cover.*, folder.*, front.*")
viper.SetDefault("coverjpegquality", 75)
viper.SetDefault("uiwelcomemessage", "")
viper.SetDefault("enablegravatar", false)
viper.SetDefault("enablefavourites", true)
viper.SetDefault("enablestarrating", true)
viper.SetDefault("enableuserediting", true)
2021-04-18 19:51:00 +02:00
viper.SetDefault("defaulttheme", "Dark")
viper.SetDefault("gatrackingid", "")
2021-05-02 22:49:20 +02:00
viper.SetDefault("enablelogredacting", true)
viper.SetDefault("authrequestlimit", 5)
viper.SetDefault("authwindowlength", 20*time.Second)
viper.SetDefault("passwordencryptionkey", "")
2020-07-02 22:34:21 +02:00
viper.SetDefault("reverseproxyuserheader", "Remote-User")
viper.SetDefault("reverseproxywhitelist", "")
viper.SetDefault("scanner.extractor", "taglib")
2021-02-07 22:46:15 +01:00
viper.SetDefault("agents", "lastfm,spotify")
viper.SetDefault("lastfm.enabled", true)
viper.SetDefault("lastfm.language", "en")
viper.SetDefault("lastfm.apikey", "")
viper.SetDefault("lastfm.secret", "")
viper.SetDefault("spotify.id", "")
viper.SetDefault("spotify.secret", "")
2020-07-02 22:34:21 +02:00
// DevFlags. These are used to enable/disable debugging and incomplete features
viper.SetDefault("devlogsourceline", false)
viper.SetDefault("devautocreateadminpassword", "")
viper.SetDefault("devautologinusername", "")
viper.SetDefault("devprecachealbumartwork", false)
2020-11-05 05:25:38 +01:00
viper.SetDefault("devoldcachelayout", false)
viper.SetDefault("devFastAccessCoverArt", false)
viper.SetDefault("devactivitypanel", true)
viper.SetDefault("devenableshare", false)
viper.SetDefault("devenablescrobble", false)
2016-03-30 06:05:57 +02:00
}
2020-07-02 23:21:25 +02:00
2020-07-03 15:39:28 +02:00
func InitConfig(cfgFile string) {
cfgFile = getConfigFile(cfgFile)
2020-07-02 23:21:25 +02:00
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Search config in local directory with name "navidrome" (without extension).
viper.AddConfigPath(".")
viper.SetConfigName("navidrome")
}
2020-07-03 00:17:31 +02:00
_ = viper.BindEnv("port")
2020-07-02 23:21:25 +02:00
viper.SetEnvPrefix("ND")
replacer := strings.NewReplacer(".", "_")
viper.SetEnvKeyReplacer(replacer)
2020-07-02 23:21:25 +02:00
viper.AutomaticEnv()
2020-07-03 16:19:44 +02:00
err := viper.ReadInConfig()
if cfgFile != "" && err != nil {
fmt.Println("Navidrome could not open config file: ", err)
os.Exit(1)
}
2020-07-02 23:21:25 +02:00
}
func getConfigFile(cfgFile string) string {
if cfgFile != "" {
return cfgFile
}
return os.Getenv("ND_CONFIGFILE")
}