Skip to content

Commit

Permalink
feat: add disableConfig variabe
Browse files Browse the repository at this point in the history
  • Loading branch information
s0up4200 committed Jan 16, 2025
1 parent 984e051 commit ad5ec18
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 21 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Afterwards you need to make the binary executable by running the following comma
chmod +x /usr/bin/seasonpackarr
```

Note: If the commands fail, prefix them with `sudo ` and run them again.
Note: If the commands fail, prefix them with `sudo` and run them again.

#### Systemd (Recommended)

Expand Down Expand Up @@ -142,7 +142,7 @@ of this clearer:

- Announce name: `Show.S01.1080p.WEB-DL.DDPA5.1.H.264-RlsGrp`
- Folder name: `Show.S01.1080p.WEB-DL.DDP5.1.H.264-RlsGrp`

Using the announce name would create the wrong folder and would lead to all the files in the torrent being downloaded
again. The issue in the given example is the additional `A` after `DDP` which is not present in the folder name. By
using the parsed folder name the files will be hardlinked into the exact folder that is being used in the torrent.
Expand Down Expand Up @@ -252,11 +252,14 @@ along in the `HTTP Request Headers` of your autobrr request; if not, the request
headers to pass the API token, but I'll explain both options here.

1. **Header**: Edit the `HTTP Request Headers` field and replace `api_token` with the token you set in your config.

```
X-API-Token=api_token
```

2. **Query Parameter**: Append `?apikey=api_token` at the end of your `Endpoint` field and replace `api_token` with the
token you've set in your config.

```
http://host:port/api/pack?apikey=api_token
```
Expand Down Expand Up @@ -305,7 +308,7 @@ Navigate to the `Actions` tab, click on `Add new` and change the `Action type` o
Depending on whether you intend to only send to qBittorrent or also integrate with Sonarr, you'll need to fill out different fields.

1. **Only qBittorrent**: Fill in the `Save Path` field with the directory where your torrent data resides, for instance
`/data/torrents`, or the `Category` field with a qBittorrent category that saves to your desired location.
`/data/torrents`, or the `Category` field with a qBittorrent category that saves to your desired location.
2. **Sonarr Integration**: Fill in the `Category` field with the category that Sonarr utilizes for all its downloads,
such as `tv-hd` or `tv-uhd`.

Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ services:
- "127.0.0.1:42069:42069"
environment:
# Core settings
- SEASONPACKARR__DISABLE_CONFIG_FILE=false # set to true to not rely on config.yaml
- SEASONPACKARR__HOST=0.0.0.0
- SEASONPACKARR__PORT=42069
- SEASONPACKARR__API_TOKEN=
Expand Down
66 changes: 48 additions & 18 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ func New(configPath string, version string) *AppConfig {
c := &AppConfig{
m: new(sync.Mutex),
}
c.defaults()

c.Config = &domain.Config{
Version: version,
ConfigPath: configPath,
Expand All @@ -299,15 +299,23 @@ func New(configPath string, version string) *AppConfig {
Notifications: domain.Notifications{},
}

// Load environment variables first
// check config file mode first
c.Config.DisableConfigFile = os.Getenv("SEASONPACKARR__DISABLE_CONFIG_FILE") == "true"

// set defaults unless config file is disabled
if !c.Config.DisableConfigFile {
c.defaults()
}

// always load environment variables
c.loadFromEnv()

// Only try to load config file if no clients were configured via env vars
if len(c.Config.Clients) == 0 {
// load config file if not disabled
if !c.Config.DisableConfigFile {
c.load(configPath)
}

// Validate client configuration regardless of source
// validate client configuration regardless of source
for clientName, client := range c.Config.Clients {
if client.PreImportPath == "" {
log.Fatalf("preImportPath for client %q can't be empty, please provide a valid path to the directory you want seasonpacks to be hardlinked to", clientName)
Expand Down Expand Up @@ -342,14 +350,34 @@ func (c *AppConfig) defaults() {
func (c *AppConfig) loadFromEnv() {
prefix := "SEASONPACKARR__"

logLevel := "DEBUG" // default
if envLogLevel := os.Getenv(prefix + "LOG_LEVEL"); envLogLevel != "" {
logLevel = envLogLevel
}

// create a temporary logger with the detected log level
tempConfig := &domain.Config{
LogLevel: logLevel,
Version: "dev",
}
log := logger.New(tempConfig)

envs := os.Environ()
for _, env := range envs {
if strings.HasPrefix(env, prefix) {
envPair := strings.SplitN(env, "=", 2)

logValue := envPair[1]
if strings.Contains(envPair[0], "PASSWORD") ||
strings.Contains(envPair[0], "TOKEN") ||
strings.Contains(envPair[0], "API_KEY") {
logValue = "**REDACTED**"
}

log.Trace().Msgf("Processing environment variable: %s=%s", envPair[0], logValue)

if envPair[1] != "" {
switch envPair[0] {
// Core settings
case prefix + "HOST":
c.Config.Host = envPair[1]
case prefix + "PORT":
Expand All @@ -359,7 +387,6 @@ func (c *AppConfig) loadFromEnv() {
case prefix + "API_TOKEN":
c.Config.APIToken = envPair[1]

// Logging settings
case prefix + "LOG_LEVEL":
c.Config.LogLevel = envPair[1]
case prefix + "LOG_PATH":
Expand All @@ -373,7 +400,6 @@ func (c *AppConfig) loadFromEnv() {
c.Config.LogMaxBackups = int(i)
}

// Feature settings
case prefix + "SMART_MODE":
if b, err := strconv.ParseBool(envPair[1]); err == nil {
c.Config.SmartMode = b
Expand All @@ -387,7 +413,6 @@ func (c *AppConfig) loadFromEnv() {
c.Config.ParseTorrentFile = b
}

// Fuzzy matching settings
case prefix + "FUZZY_MATCHING_SKIP_REPACK_COMPARE":
if b, err := strconv.ParseBool(envPair[1]); err == nil {
c.Config.FuzzyMatching.SkipRepackCompare = b
Expand All @@ -397,32 +422,33 @@ func (c *AppConfig) loadFromEnv() {
c.Config.FuzzyMatching.SimplifyHdrCompare = b
}

// Notification settings
case prefix + "NOTIFICATIONS_DISCORD":
c.Config.Notifications.Discord = envPair[1]
case prefix + "NOTIFICATIONS_NOTIFICATION_LEVEL":
// Expect comma-separated list
levels := strings.Split(envPair[1], ",")
// Trim spaces from each level
for i, level := range levels {
levels[i] = strings.TrimSpace(level)
}
c.Config.Notifications.NotificationLevel = levels

case prefix + "DISABLE_CONFIG_FILE":
if b, err := strconv.ParseBool(envPair[1]); err == nil {
c.Config.DisableConfigFile = b
}
}

// Client settings - handle dynamic client names
// client settings - handle dynamic client names
if strings.HasPrefix(envPair[0], prefix+"CLIENTS_") {
parts := strings.Split(strings.TrimPrefix(envPair[0], prefix+"CLIENTS_"), "_")
if len(parts) == 2 {
clientName := strings.ToLower(parts[0])
setting := parts[1]

// Initialize client if it doesn't exist
// initialize client if it doesn't exist
if c.Config.Clients[clientName] == nil {
c.Config.Clients[clientName] = &domain.Client{}
}

// Apply setting
switch setting {
case "HOST":
c.Config.Clients[clientName].Host = envPair[1]
Expand Down Expand Up @@ -452,7 +478,7 @@ func (c *AppConfig) load(configPath string) {
if configPath != "" {
configFile := path.Join(configPath, "config.yaml")

// Only create config file if it doesn't exist
// only create config file if it doesn't exist
if err := c.writeConfig(configPath, "config.yaml"); err != nil {
log.Printf("config write error: %q", err)
}
Expand All @@ -461,7 +487,7 @@ func (c *AppConfig) load(configPath string) {
} else {
viper.SetConfigName("config")

// Search config in directories
// search config in directories
viper.AddConfigPath(".")
viper.AddConfigPath("$HOME/.config/seasonpackarr")
viper.AddConfigPath("$HOME/.seasonpackarr")
Expand All @@ -470,7 +496,7 @@ func (c *AppConfig) load(configPath string) {
// read config, but don't fail if file doesn't exist
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
// Only fail on errors other than file not found
// only fail on errors other than file not found
log.Fatalf("config read error: %q", err)
}
return
Expand Down Expand Up @@ -520,6 +546,10 @@ func (c *AppConfig) DynamicReload(log logger.Logger) {
}

func (c *AppConfig) UpdateConfig() error {
if c.Config.DisableConfigFile {
return nil
}

filePath := path.Join(c.Config.ConfigPath, "config.yaml")

f, err := os.ReadFile(filePath)
Expand Down
1 change: 1 addition & 0 deletions internal/domain/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ type Config struct {
FuzzyMatching FuzzyMatching `yaml:"fuzzyMatching"`
APIToken string `yaml:"apiToken"`
Notifications Notifications `yaml:"notifications"`
DisableConfigFile bool
}

0 comments on commit ad5ec18

Please sign in to comment.