Server changes/Sonarr
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
_ "time/tzdata"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -33,6 +34,8 @@ type Config struct {
|
||||
SessionTTL time.Duration
|
||||
// SessionIdleExpiry retires gateway tokens that go unused for this long.
|
||||
SessionIdleExpiry time.Duration
|
||||
// MaxClientsPerUser is enforced transactionally when a new TV signs in.
|
||||
MaxClientsPerUser int
|
||||
|
||||
// RecommendTTL is how long computed recommendation rows stay warm. Long, because
|
||||
// taste moves slowly and each rebuild costs several Emby queries.
|
||||
@@ -47,6 +50,14 @@ type Config struct {
|
||||
// unconfigured deployment cannot leave it exposed.
|
||||
AdminToken string
|
||||
|
||||
// PublicURL is the externally reachable Memby gateway address used in update links.
|
||||
PublicURL string
|
||||
// ReleaseDir persists signed APKs published by CI.
|
||||
ReleaseDir string
|
||||
// ReleasePublishToken authorizes the CI-only release upload endpoint. It is separate
|
||||
// from AdminToken so a compromised build runner cannot change maintenance settings.
|
||||
ReleasePublishToken string
|
||||
|
||||
// SyncInterval is how often the library import runs. Zero disables the schedule.
|
||||
SyncInterval time.Duration
|
||||
// SyncTimeout bounds one import; a full pass over a large library is slow.
|
||||
@@ -60,6 +71,13 @@ type Config struct {
|
||||
|
||||
// AnalyticsRetention is how long raw row events are kept before being pruned.
|
||||
AnalyticsRetention time.Duration
|
||||
|
||||
// Sonarr is optional. When configured, its local calendar supplies the informational
|
||||
// "Shows airing today" home row. The API key never leaves this server.
|
||||
SonarrURL string
|
||||
SonarrAPIKey string
|
||||
SonarrTTL time.Duration
|
||||
SonarrLocation *time.Location
|
||||
}
|
||||
|
||||
func Load() (Config, error) {
|
||||
@@ -76,10 +94,16 @@ func Load() (Config, error) {
|
||||
ScreensaverTTL: duration("MEMBY_SCREENSAVER_TTL", 10*time.Minute),
|
||||
SessionTTL: duration("MEMBY_SESSION_CACHE_TTL", 5*time.Minute),
|
||||
SessionIdleExpiry: duration("MEMBY_SESSION_IDLE_EXPIRY", 90*24*time.Hour),
|
||||
MaxClientsPerUser: integer("MEMBY_MAX_CLIENTS_PER_USER", 1),
|
||||
RecommendTTL: duration("MEMBY_RECOMMEND_TTL", 2*time.Hour),
|
||||
RecommendTimeout: duration("MEMBY_RECOMMEND_TIMEOUT", 60*time.Second),
|
||||
|
||||
AdminToken: strings.TrimSpace(os.Getenv("MEMBY_ADMIN_TOKEN")),
|
||||
AdminToken: strings.TrimSpace(os.Getenv("MEMBY_ADMIN_TOKEN")),
|
||||
PublicURL: strings.TrimRight(strings.TrimSpace(os.Getenv("MEMBY_PUBLIC_URL")), "/"),
|
||||
ReleaseDir: env("MEMBY_RELEASE_DIR", "/data/releases"),
|
||||
ReleasePublishToken: strings.TrimSpace(
|
||||
os.Getenv("MEMBY_RELEASE_PUBLISH_TOKEN"),
|
||||
),
|
||||
SyncInterval: duration("MEMBY_SYNC_INTERVAL", time.Hour),
|
||||
SyncTimeout: duration("MEMBY_SYNC_TIMEOUT", 30*time.Minute),
|
||||
SyncOnStart: boolean("MEMBY_SYNC_ON_START", false),
|
||||
@@ -87,6 +111,9 @@ func Load() (Config, error) {
|
||||
SyncAPIKey: strings.TrimSpace(os.Getenv("MEMBY_SYNC_API_KEY")),
|
||||
AnalyticsRetention: duration("MEMBY_ANALYTICS_RETENTION", 90*24*time.Hour),
|
||||
UpstreamTimeout: duration("MEMBY_UPSTREAM_TIMEOUT", 20*time.Second),
|
||||
SonarrURL: strings.TrimRight(strings.TrimSpace(os.Getenv("MEMBY_SONARR_URL")), "/"),
|
||||
SonarrAPIKey: strings.TrimSpace(os.Getenv("MEMBY_SONARR_API_KEY")),
|
||||
SonarrTTL: duration("MEMBY_SONARR_TTL", 5*time.Minute),
|
||||
}
|
||||
|
||||
if c.EmbyURL == "" {
|
||||
@@ -95,9 +122,23 @@ func Load() (Config, error) {
|
||||
if c.DatabaseURL == "" {
|
||||
return c, fmt.Errorf("MEMBY_DATABASE_URL is required")
|
||||
}
|
||||
if c.MaxClientsPerUser < 1 {
|
||||
return c, fmt.Errorf("MEMBY_MAX_CLIENTS_PER_USER must be at least 1")
|
||||
}
|
||||
if c.EmbyPublicURL == "" {
|
||||
c.EmbyPublicURL = c.EmbyURL
|
||||
}
|
||||
if c.ReleasePublishToken != "" && c.PublicURL == "" {
|
||||
return c, fmt.Errorf("MEMBY_PUBLIC_URL is required when release publishing is enabled")
|
||||
}
|
||||
if (c.SonarrURL == "") != (c.SonarrAPIKey == "") {
|
||||
return c, fmt.Errorf("MEMBY_SONARR_URL and MEMBY_SONARR_API_KEY must be set together")
|
||||
}
|
||||
location, err := time.LoadLocation(env("MEMBY_TIMEZONE", "Pacific/Auckland"))
|
||||
if err != nil {
|
||||
return c, fmt.Errorf("MEMBY_TIMEZONE: %w", err)
|
||||
}
|
||||
c.SonarrLocation = location
|
||||
return c, nil
|
||||
}
|
||||
|
||||
@@ -134,3 +175,15 @@ func duration(key string, fallback time.Duration) time.Duration {
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func integer(key string, fallback int) int {
|
||||
raw := strings.TrimSpace(os.Getenv(key))
|
||||
if raw == "" {
|
||||
return fallback
|
||||
}
|
||||
value, err := strconv.Atoi(raw)
|
||||
if err != nil {
|
||||
return fallback
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user