Documentation
¶
Index ¶
- Constants
- func DefaultStreamHeadroom(connections int) int
- func SaveToFile(config *Config, filename string) error
- type APIConfig
- type ArrsConfig
- type ArrsInstanceConfig
- type AuthConfig
- type ChangeCallback
- type Config
- func (c *Config) DeepCopy() *Config
- func (c *Config) GetAcceptableMissingSegmentsPercentage() float64
- func (c *Config) GetCheckAllSegments() bool
- func (c *Config) GetCheckBatchSize() int
- func (c *Config) GetCheckInterval() time.Duration
- func (c *Config) GetDownloadClientBaseURL() string
- func (c *Config) GetFuseMountPath() string
- func (c *Config) GetHealthDeleteOnCorruption() bool
- func (c *Config) GetHealthEnabled() bool
- func (c *Config) GetHealthExcludedCategories() []string
- func (c *Config) GetHealthReadTimeout() time.Duration
- func (c *Config) GetHealthVerifyContent() bool
- func (c *Config) GetHealthVerifyContentTimeout() time.Duration
- func (c *Config) GetImportVerifyContent() bool
- func (c *Config) GetImportVerifyContentTimeout() time.Duration
- func (c *Config) GetIsoAnalyzeTimeout() time.Duration
- func (c *Config) GetLibrarySyncConcurrency() int
- func (c *Config) GetLibrarySyncInterval() time.Duration
- func (c *Config) GetMaxConcurrentImports() int
- func (c *Config) GetMaxConcurrentJobs() int
- func (c *Config) GetMaxConcurrentSegmentChecks() int
- func (c *Config) GetMaxDownloadPrefetch() int
- func (c *Config) GetMaxRepairRetries() int
- func (c *Config) GetMaxRetries() int
- func (c *Config) GetMetadataBackupKeep() int
- func (c *Config) GetReadTimeoutSeconds() int
- func (c *Config) GetRepairAutoSearchWait() time.Duration
- func (c *Config) GetRepairEnabled() bool
- func (c *Config) GetRepairExponentialBackoff() bool
- func (c *Config) GetRepairFileDeleteConfirm() time.Duration
- func (c *Config) GetRepairInterval() time.Duration
- func (c *Config) GetRepairMaxCoolDown() time.Duration
- func (c *Config) GetSegmentSamplePercentage() int
- func (c *Config) GetStreamHeadroomConnections() int
- func (c *Config) GetStreamReadTimeout() time.Duration
- func (c *Config) GetUserAgent() string
- func (c *Config) GetVerifyData() bool
- func (c *Config) GetWebhookBaseURL() string
- func (c *Config) ProviderFingerprint() string
- func (c *Config) ProvidersDiff(other *Config) []ProviderChange
- func (c *Config) ProvidersEqual(other *Config) bool
- func (c *Config) ProvidersOrderChanged(other *Config) bool
- func (c *Config) SoftMemoryLimit(gomemlimit string) int64
- func (c *Config) StatConcurrency() int
- func (c *Config) ToNNTPProviders() []nntppool.Provider
- func (c *Config) TotalProviderConnections() int
- func (c *Config) Validate() error
- func (c *Config) ValidateDirectories() error
- type ConfigGetter
- type DatabaseConfig
- type FailureMaskingConfig
- type FuseConfig
- type HealthConfig
- type IgnoredMessage
- type ImportConfig
- type ImportStrategy
- type LogConfig
- type Manager
- func (m *Manager) ClearLibrarySyncFlag()
- func (m *Manager) GetConfig() *Config
- func (m *Manager) GetConfigGetter() ConfigGetter
- func (m *Manager) GetPreviousMountPath() string
- func (m *Manager) NeedsLibrarySync() bool
- func (m *Manager) OnConfigChange(callback ChangeCallback)
- func (m *Manager) ReloadConfig() error
- func (m *Manager) SaveConfig() error
- func (m *Manager) UpdateConfig(config *Config) error
- func (m *Manager) ValidateConfig(config *Config) error
- func (m *Manager) ValidateConfigUpdate(newConfig *Config) error
- type MetadataBackupConfig
- type MetadataConfig
- type MetadataMigrationConfig
- type MountType
- type NetworkConfig
- type NewsnabIndexerConfig
- type NzblnkConfig
- type Par2RepairConfig
- type ProviderChange
- type ProviderChangeType
- type ProviderConfig
- type ProwlarrConfig
- type RCloneConfig
- type RepairConfig
- type SABnzbdCategory
- type SABnzbdConfig
- type SegmentCacheConfig
- type StreamScoringConfig
- type StreamingConfig
- type StremioConfig
- type StremioDisplayConfig
- type StremioIndexersConfig
- type StuckCleanupRule
- type TrashCustomFormatConfig
- type WebDAVConfig
Constants ¶
const ( // StuckActionRemove removes the item from the queue only (no blocklist, no // re-search) — for transient/environmental errors or already-satisfied files. StuckActionRemove = "remove" // StuckActionBlocklist removes the item and blocklists the release so the same // NZB is not grabbed again, but does NOT trigger a new search. StuckActionBlocklist = "blocklist" // StuckActionBlocklistSearch blocklists the release and triggers the *arr to // search for a replacement. StuckActionBlocklistSearch = "blocklist_search" )
Stuck cleanup actions decide what happens to a matched stuck import.
const DefaultCategoryDir = "complete"
const DefaultCategoryName = "Default"
const DefaultMaxDownloadPrefetch = 10
DefaultMaxDownloadPrefetch is the default number of segments to prefetch ahead during archive analysis and expansion. Must match the value in DefaultConfig.
const DefaultStreamReadTimeout = 120 * time.Second
DefaultStreamReadTimeout bounds a single streaming read when streaming.read_timeout_seconds is unset. A healthy read finishes in seconds; even a pathological one is bounded by the per-segment fetch budget (15s per attempt, 2 attempts). Anything past this is a stall, not slowness.
const DefaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
DefaultUserAgent is the fallback for Config.UserAgent. Browser-like because some public indexers (e.g. nzbking.com) reject non-browser agents.
const MountProvider = "altmount"
const StreamReadAheadBytesCap int64 = 96 << 20
StreamReadAheadBytesCap bounds one reader's read-ahead window in bytes. The usenet reader enforces it; it lives here so the soft memory limit can budget for the windows that are live while files stream.
Variables ¶
This section is empty.
Functions ¶
func DefaultStreamHeadroom ¶
DefaultStreamHeadroom derives the per-stream import reservation from the pool's connection count.
On a saturated link the pool holds slack — connections that are not converting into bytes because the wire, not the pool, is the limit — and handing that slack to playback is close to free. Measured at 100 connections behind a 400 MB/s ceiling: a reservation of 8 cost nothing (import 357 vs 359 MB/s) for stream p50 190ms -> 179ms, and 32 cost 7-13% import throughput during playback only for p50 147ms and p99 245ms -> 170ms.
A quarter of the pool sits between those and, crucially, costs the same share at every pool size. How much slack actually exists depends on the link rate, which cannot be known statically — a small pool on a fast line has little, and will pay something real for this. Set stream_headroom_connections explicitly to override, or 0 to disable.
func SaveToFile ¶
SaveToFile saves a configuration to a YAML file
Types ¶
type APIConfig ¶
type APIConfig struct {
Prefix string `yaml:"prefix" mapstructure:"prefix" json:"prefix"`
KeyOverride string `yaml:"key_override" mapstructure:"key_override" json:"key_override,omitempty"`
AllowedOrigins []string `yaml:"allowed_origins" mapstructure:"allowed_origins" json:"allowed_origins,omitempty"`
}
APIConfig represents REST API configuration
type ArrsConfig ¶
type ArrsConfig struct {
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
MaxWorkers int `yaml:"max_workers" mapstructure:"max_workers" json:"max_workers,omitempty"`
WebhookBaseURL string `yaml:"webhook_base_url" mapstructure:"webhook_base_url" json:"webhook_base_url,omitempty"`
RadarrInstances []ArrsInstanceConfig `yaml:"radarr_instances" mapstructure:"radarr_instances" json:"radarr_instances"`
SonarrInstances []ArrsInstanceConfig `yaml:"sonarr_instances" mapstructure:"sonarr_instances" json:"sonarr_instances"`
LidarrInstances []ArrsInstanceConfig `yaml:"lidarr_instances" mapstructure:"lidarr_instances" json:"lidarr_instances"`
ReadarrInstances []ArrsInstanceConfig `yaml:"readarr_instances" mapstructure:"readarr_instances" json:"readarr_instances"`
WhisparrInstances []ArrsInstanceConfig `yaml:"whisparr_instances" mapstructure:"whisparr_instances" json:"whisparr_instances"`
SportarrInstances []ArrsInstanceConfig `yaml:"sportarr_instances" mapstructure:"sportarr_instances" json:"sportarr_instances"`
QueueCleanupEnabled *bool `yaml:"queue_cleanup_enabled" mapstructure:"queue_cleanup_enabled" json:"queue_cleanup_enabled,omitempty"`
QueueCleanupIntervalSeconds int `` /* 131-byte string literal not displayed */
QueueCleanupGracePeriodMinutes int `` /* 143-byte string literal not displayed */
// QueueCleanupMaxFailures is the per-target failure circuit breaker. After
// AltMount has acted on the same target (a Radarr movie or Sonarr/Whisparr
// episode that keeps failing import) this many times — via queue cleanup,
// health-repair re-searches or the partial-pack reconcile — it gives up:
// it blocklists without re-searching and unmonitors the item in the *arr so it
// stops being automatically re-grabbed. 0 (the default) disables the breaker.
QueueCleanupMaxFailures int `yaml:"queue_cleanup_max_failures" mapstructure:"queue_cleanup_max_failures" json:"queue_cleanup_max_failures,omitempty"`
// QueueCleanupRules matches an *arr status message for a stuck/failed import and
// decides the action (remove / blocklist / blocklist+search). This is the single
// message-rule list for queue cleanup; ghost/empty-folder detection runs alongside
// it in the same pass. Only items owned by AltMount's download client are touched
// (see issue #523).
QueueCleanupRules []StuckCleanupRule `yaml:"queue_cleanup_rules,omitempty" mapstructure:"queue_cleanup_rules" json:"queue_cleanup_rules,omitempty"`
// Deprecated: the fields below are read from existing config files for one-time
// migration into the unified queue-cleanup model (see migrateArrsCleanup) and are
// cleared afterwards. They are hidden from the API (json:"-") and dropped from
// saved YAML once empty (yaml omitempty). Do not use in new code.
QueueCleanupAllowlist []IgnoredMessage `yaml:"queue_cleanup_allowlist,omitempty" mapstructure:"queue_cleanup_allowlist" json:"-"`
StuckCleanupEnabled *bool `yaml:"stuck_cleanup_enabled,omitempty" mapstructure:"stuck_cleanup_enabled" json:"-"`
StuckCleanupGracePeriodMinutes int `yaml:"stuck_cleanup_grace_period_minutes,omitempty" mapstructure:"stuck_cleanup_grace_period_minutes" json:"-"`
StuckCleanupRules []StuckCleanupRule `yaml:"stuck_cleanup_rules,omitempty" mapstructure:"stuck_cleanup_rules" json:"-"`
// Deprecated: the hardcoded "automatic import is not possible" purge has been
// folded into the unified QueueCleanupRules (see migrateArrsCleanup). Read for
// one-time migration only, then cleared. Do not use in new code.
CleanupAutomaticImportFailure *bool `yaml:"cleanup_automatic_import_failure,omitempty" mapstructure:"cleanup_automatic_import_failure" json:"-"`
}
ArrsConfig represents arrs configuration
type ArrsInstanceConfig ¶
type ArrsInstanceConfig struct {
APIVersion string `yaml:"api_version,omitempty" mapstructure:"api_version" json:"api_version,omitempty"`
Name string `yaml:"name" mapstructure:"name" json:"name"`
URL string `yaml:"url" mapstructure:"url" json:"url"`
APIKey string `yaml:"api_key" mapstructure:"api_key" json:"api_key"`
Category string `yaml:"category" mapstructure:"category" json:"category,omitempty"`
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled,omitempty"`
SyncIntervalHours *int `yaml:"sync_interval_hours" mapstructure:"sync_interval_hours" json:"sync_interval_hours,omitempty"`
}
ArrsInstanceConfig represents a single arrs instance configuration
type AuthConfig ¶
type AuthConfig struct {
LoginRequired *bool `yaml:"login_required" mapstructure:"login_required" json:"login_required"`
}
AuthConfig represents authentication configuration
type ChangeCallback ¶
type ChangeCallback func(oldConfig, newConfig *Config)
ChangeCallback represents a function called when configuration changes
type Config ¶
type Config struct {
WebDAV WebDAVConfig `yaml:"webdav" mapstructure:"webdav" json:"webdav"`
API APIConfig `yaml:"api" mapstructure:"api" json:"api"`
Auth AuthConfig `yaml:"auth" mapstructure:"auth" json:"auth"`
Database DatabaseConfig `yaml:"database" mapstructure:"database" json:"database"`
Metadata MetadataConfig `yaml:"metadata" mapstructure:"metadata" json:"metadata"`
Streaming StreamingConfig `yaml:"streaming" mapstructure:"streaming" json:"streaming"`
Health HealthConfig `yaml:"health" mapstructure:"health" json:"health"`
RClone RCloneConfig `yaml:"rclone" mapstructure:"rclone" json:"rclone"`
Import ImportConfig `yaml:"import" mapstructure:"import" json:"import"`
Log LogConfig `yaml:"log" mapstructure:"log" json:"log"`
SABnzbd SABnzbdConfig `yaml:"sabnzbd" mapstructure:"sabnzbd" json:"sabnzbd"`
Arrs ArrsConfig `yaml:"arrs" mapstructure:"arrs" json:"arrs"`
Stremio StremioConfig `yaml:"stremio" mapstructure:"stremio" json:"stremio"`
Fuse FuseConfig `yaml:"fuse" mapstructure:"fuse" json:"fuse"`
SegmentCache SegmentCacheConfig `yaml:"segment_cache" mapstructure:"segment_cache" json:"segment_cache"`
Providers []ProviderConfig `yaml:"providers" mapstructure:"providers" json:"providers"`
Nzblnk NzblnkConfig `yaml:"nzblnk,omitempty" mapstructure:"nzblnk" json:"-"`
Network NetworkConfig `yaml:"network" mapstructure:"network" json:"network"`
// UserAgent is the HTTP User-Agent sent on every outbound HTTP request that
// identifies AltMount (indexer NZB downloads, metadata lookups, nzblnk://
// resolution, GitHub release checks). Defaults to a browser-like string
// because some public indexers reject non-browser agents. Leave empty to
// use the default.
UserAgent string `yaml:"user_agent" mapstructure:"user_agent" json:"user_agent"`
Par2Repair Par2RepairConfig `yaml:"par2_repair" mapstructure:"par2_repair" json:"par2_repair"`
MountPath string `yaml:"mount_path" mapstructure:"mount_path" json:"mount_path"`
MountType MountType `yaml:"mount_type" mapstructure:"mount_type" json:"mount_type"`
ProfilerEnabled bool `yaml:"profiler_enabled" mapstructure:"profiler_enabled" json:"profiler_enabled" default:"false"`
// MemoryLimitMB is the Go soft memory limit. Unset or 0 derives it from
// the budgets that allocate (see SoftMemoryLimit); a positive value pins
// it; a negative value leaves the runtime default. GOMEMLIMIT in the
// environment always takes precedence.
MemoryLimitMB *int `yaml:"memory_limit_mb" mapstructure:"memory_limit_mb" json:"memory_limit_mb"`
}
Config represents the complete application configuration
func DefaultConfig ¶
DefaultConfig returns a config with default values If configDir is provided, it will be used for database and log file paths
func LoadConfig ¶
func (*Config) DeepCopy ¶
DeepCopy returns a deep copy of the configuration using the copier library. This handles all pointer fields, slices, and maps automatically.
func (*Config) GetAcceptableMissingSegmentsPercentage ¶
GetAcceptableMissingSegmentsPercentage returns the missing-segment percentage a health check tolerates before failing a file (and triggering repair) rather than leaving it degraded. Defaults to 2%; set to 0 to disable tolerance entirely (any missing segment fails immediately), or to 100 to disable failing on this basis altogether (always degraded, never repaired for missing segments alone). The value is clamped to [0, 100].
func (*Config) GetCheckAllSegments ¶
GetCheckAllSegments returns whether to check all segments during health checks.
func (*Config) GetCheckBatchSize ¶
GetCheckBatchSize returns how many due files each health cycle fetches and sweeps together in one cross-file StatMany call, with a default fallback. Distinct from HealthStatConcurrency: this bounds how many FILES are batched into one sweep, while that bounds how many segment checks run concurrently within a sweep.
func (*Config) GetCheckInterval ¶
GetCheckInterval returns the health check interval with a default fallback.
func (*Config) GetDownloadClientBaseURL ¶
GetDownloadClientBaseURL returns the configured download client base URL or a default one based on the current port.
func (*Config) GetFuseMountPath ¶
GetFuseMountPath returns the FUSE mount path, falling back to the root mount_path if not set.
func (*Config) GetHealthDeleteOnCorruption ¶
GetHealthDeleteOnCorruption reports whether confirmed corruption should delete the file instead of triggering an Arr repair (health.corruption_action == "delete").
func (*Config) GetHealthEnabled ¶
GetHealthEnabled returns whether health checking is enabled (defaults to true)
func (*Config) GetHealthExcludedCategories ¶
GetHealthExcludedCategories returns the SABnzbd category names whose files must not be registered for health checking by the library-sync pass.
func (*Config) GetHealthReadTimeout ¶
GetHealthReadTimeout returns the health check read timeout as a duration with a default fallback.
func (*Config) GetHealthVerifyContent ¶
GetHealthVerifyContent returns whether health checks should probe media files for a valid container signature.
func (*Config) GetHealthVerifyContentTimeout ¶
GetHealthVerifyContentTimeout returns the per-file content probe timeout for health check verification, defaulting to 15 seconds.
func (*Config) GetImportVerifyContent ¶
GetImportVerifyContent returns whether imported media files should be probed for a valid container signature before the import is reported successful.
func (*Config) GetImportVerifyContentTimeout ¶
GetImportVerifyContentTimeout returns the per-file content probe timeout for import verification, defaulting to 15 seconds.
func (*Config) GetIsoAnalyzeTimeout ¶
GetIsoAnalyzeTimeout returns the per-ISO analyse deadline with a 120s default fallback. This bounds the entire iso.AnalyzeISO walk so a degraded NNTP provider cannot stall the importer indefinitely.
Sentinel handling:
- nil (config field unset) → 120s default
- 0 or negative (explicit "none") → 120s default; users cannot disable the cap — the whole purpose of this knob is to prevent unbounded waits. To approximate "unlimited", set a very large value (e.g. 86400 for a one-day budget).
func (*Config) GetLibrarySyncConcurrency ¶
GetLibrarySyncConcurrency returns the library sync concurrency with a default fallback.
func (*Config) GetLibrarySyncInterval ¶
GetLibrarySyncInterval returns the library sync interval with a default fallback.
func (*Config) GetMaxConcurrentImports ¶
GetMaxConcurrentImports returns the global cap on concurrent NZB imports. 0 means unlimited (the default).
func (*Config) GetMaxConcurrentJobs ¶
GetMaxConcurrentJobs returns max concurrent health check jobs with a default fallback.
func (*Config) GetMaxConcurrentSegmentChecks ¶
GetMaxConcurrentSegmentChecks returns the operator's hard cap on in-flight STAT checks during a health sweep, or 0 meaning "let the pool adapt".
func (*Config) GetMaxDownloadPrefetch ¶
GetMaxDownloadPrefetch returns max download prefetch with a default fallback.
func (*Config) GetMaxRepairRetries ¶
GetMaxRepairRetries returns the maximum number of repair notification retries.
func (*Config) GetMaxRetries ¶
GetMaxRetries returns the maximum number of health check retries.
func (*Config) GetMetadataBackupKeep ¶
GetMetadataBackupKeep returns the number of metadata backups to keep with a default fallback.
func (*Config) GetReadTimeoutSeconds ¶
GetReadTimeoutSeconds returns read timeout in seconds with a default fallback.
func (*Config) GetRepairAutoSearchWait ¶
GetRepairAutoSearchWait returns how long a repair may wait for the ARR's own automatic redownload search to finish. Zero means "do not wait".
func (*Config) GetRepairEnabled ¶
GetRepairEnabled returns whether automatic repair is enabled (defaults to true)
func (*Config) GetRepairExponentialBackoff ¶
GetRepairExponentialBackoff returns whether exponential backoff is enabled for repairs
func (*Config) GetRepairFileDeleteConfirm ¶
GetRepairFileDeleteConfirm returns how long a repair may wait for the ARR to report a deleted file record as unlinked. Zero means "do not wait".
func (*Config) GetRepairInterval ¶
GetRepairInterval returns the repair check interval
func (*Config) GetRepairMaxCoolDown ¶
GetRepairMaxCoolDown returns the maximum cooldown for repairs
func (*Config) GetSegmentSamplePercentage ¶
GetSegmentSamplePercentage returns segment sample percentage with a default fallback. Returns a value between 1 and 100.
func (*Config) GetStreamHeadroomConnections ¶
GetStreamHeadroomConnections returns the per-stream import reservation: an explicit setting when present, otherwise a value derived from the pool size.
func (*Config) GetStreamReadTimeout ¶
GetStreamReadTimeout returns the per-read timeout for streaming reads. Zero configures the default; a negative value disables the timeout entirely and is returned as 0.
func (*Config) GetUserAgent ¶
GetUserAgent returns the configured global User-Agent, falling back to DefaultUserAgent when unset.
func (*Config) GetVerifyData ¶
GetVerifyData returns whether to verify data during health checks.
func (*Config) GetWebhookBaseURL ¶
GetWebhookBaseURL returns the configured webhook base URL or a default one based on the current port.
func (*Config) ProviderFingerprint ¶
TotalProviderConnections returns the pool's total connection capacity: the sum of MaxConnections across enabled, non-backup providers. When no primary providers are configured it falls back to the enabled backup providers' sum so the capacity is not zero while a usable pool exists. Returns 0 when no providers are configured at all. ProviderFingerprint names the set of enabled providers: SHA-1 over the sorted "host:port" list, first 8 bytes hex. Hole records are trusted only under the fingerprint that recorded them, because "missing" is an answer about particular servers.
func (*Config) ProvidersDiff ¶
func (c *Config) ProvidersDiff(other *Config) []ProviderChange
ProvidersDiff computes the set of provider changes between this config and another. Returns nil if providers are identical (same set and same field values).
func (*Config) ProvidersEqual ¶
ProvidersEqual compares the providers in this config with another config for equality
func (*Config) ProvidersOrderChanged ¶
ProvidersOrderChanged returns true if the provider order differs between this config and another, even if the set of providers is unchanged.
func (*Config) SoftMemoryLimit ¶
SoftMemoryLimit is the Go soft memory limit to apply, or 0 to leave the runtime alone. Without a limit the collector lets the heap reach twice the live set, so a 256 MB memory tier costs 600+ MB of RSS. The automatic value adds every budget that holds live heap (memory tier, PAR2 solver per concurrent job, read-ahead windows, connection buffers) plus a base, so the limit stays above the live set and the collector never has to run back to back. A soft limit is only useful while the memory tier is on: with it off the heap is small and bursty.
func (*Config) StatConcurrency ¶
StatConcurrency returns how many STATs to keep in flight during an availability sweep. STAT carries no body, so nntppool pipelines it down a connection to Provider.StatInflight depth rather than spending one connection per check (see NNTPConnection.inflightSem) — connection count is the wrong ceiling.
The value is the deepest stat_inflight_requests among enabled providers, not the sum of connections × depth. A single provider's pipeline depth is the conservative read: it is what one connection alone can sustain, so the sweep stays within reach even when the pool is busy serving streams.
func (*Config) ToNNTPProviders ¶
ToNNTPProviders converts ProviderConfig slice to nntppool.Provider slice (enabled only)
func (*Config) TotalProviderConnections ¶
func (*Config) ValidateDirectories ¶
ValidateDirectories validates that all configured directories are writable This performs actual filesystem checks and may create directories if needed
type ConfigGetter ¶
type ConfigGetter func() *Config
ConfigGetter represents a function that returns the current configuration
type DatabaseConfig ¶
type DatabaseConfig struct {
// Type selects the database backend: "sqlite" (default) or "postgres".
Type string `yaml:"type" mapstructure:"type" json:"type"`
// Path is the SQLite database file path (sqlite only).
Path string `yaml:"path" mapstructure:"path" json:"path"`
// DSN is the PostgreSQL connection string (postgres only).
// Example: "postgres://user:password@localhost:5432/altmount?sslmode=disable"
DSN string `yaml:"dsn" mapstructure:"dsn" json:"dsn,omitempty"`
}
DatabaseConfig represents database configuration
type FailureMaskingConfig ¶
type FailureMaskingConfig struct {
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
Threshold int `yaml:"threshold" mapstructure:"threshold" json:"threshold"`
}
FailureMaskingConfig represents failure masking configuration
type FuseConfig ¶
type FuseConfig struct {
MountPath string `yaml:"mount_path" mapstructure:"mount_path" json:"mount_path"`
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
AllowOther bool `yaml:"allow_other" mapstructure:"allow_other" json:"allow_other"`
Debug bool `yaml:"debug" mapstructure:"debug" json:"debug"`
AttrTimeoutSeconds int `yaml:"attr_timeout_seconds" mapstructure:"attr_timeout_seconds" json:"attr_timeout_seconds"`
EntryTimeoutSeconds int `yaml:"entry_timeout_seconds" mapstructure:"entry_timeout_seconds" json:"entry_timeout_seconds"`
MaxCacheSizeMB int `yaml:"max_cache_size_mb" mapstructure:"max_cache_size_mb" json:"max_cache_size_mb"`
MaxReadAheadMB int `yaml:"max_read_ahead_mb" mapstructure:"max_read_ahead_mb" json:"max_read_ahead_mb"`
// AsyncBufferSizeMB is the per-open-file read-ahead buffer size (MB). A
// background goroutine fills it ahead of the player so reads are served
// from memory instead of blocking on the network, mirroring the buffering
// rclone's VFS provides over WebDAV. 0 disables read-ahead (every read is a
// direct passthrough — the previous behavior).
AsyncBufferSizeMB int `yaml:"async_buffer_size_mb" mapstructure:"async_buffer_size_mb" json:"async_buffer_size_mb"`
// AsyncBufferMaxTotalMB caps total read-ahead memory across all open files
// (MB). Buffers reserve their size only while actively streaming; over the
// cap, additional streams run unbuffered. 0 = unlimited.
AsyncBufferMaxTotalMB int `yaml:"async_buffer_max_total_mb" mapstructure:"async_buffer_max_total_mb" json:"async_buffer_max_total_mb"`
Backend string `yaml:"backend" mapstructure:"backend" json:"backend"` // "hanwen" or "cgo" (empty = platform default)
// NoModTime reports epoch for all timestamps (mtime, ctime, atime); prevents
// media servers re-scanning on unstable VFS mtimes. Note: tools like find -atime
// will not see meaningful access times on this mount.
NoModTime bool `yaml:"no_mod_time" mapstructure:"no_mod_time" json:"no_mod_time"`
}
FuseConfig represents FUSE mount configuration
type HealthConfig ¶
type HealthConfig struct {
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled,omitempty"`
LibraryDir *string `yaml:"library_dir" mapstructure:"library_dir" json:"library_dir,omitempty"`
CleanupOrphanedMetadata *bool `yaml:"cleanup_orphaned_metadata" mapstructure:"cleanup_orphaned_metadata" json:"cleanup_orphaned_metadata,omitempty"`
CheckIntervalSeconds int `yaml:"check_interval_seconds" mapstructure:"check_interval_seconds" json:"check_interval_seconds,omitempty"`
// MaxConcurrentSegmentChecks bounds how many STAT checks a health sweep keeps
// in flight. STAT is bodyless and pipelines many per connection, so connection
// count is the wrong unit — the import path already sizes its sweep by STAT
// pipeline depth (see importer/processor.go).
//
// nil or 0 means "adapt": the pool narrows the sweep to one connection's depth
// while a stream is playing and widens it to the pool's aggregate STAT capacity
// when idle, which measured 24x the sweep throughput on an idle pool.
MaxConcurrentSegmentChecks *int `` /* 128-byte string literal not displayed */
// Deprecated: superseded by MaxConcurrentSegmentChecks, which is named for
// what it actually bounds. Read for one-time migration only (see
// migrateHealthSweepConcurrency), then cleared. Do not use in new code.
MaxConnectionsForHealthChecks int `` /* 150-byte string literal not displayed */
CheckBatchSize int `yaml:"check_batch_size" mapstructure:"check_batch_size" json:"check_batch_size,omitempty"`
MaxConcurrentJobs int `yaml:"max_concurrent_jobs" mapstructure:"max_concurrent_jobs" json:"max_concurrent_jobs,omitempty"`
// SegmentSamplePercentage is the fraction (1-100) of segments randomly sampled
// during health-check sweeps (post-import validation only). Distinct from
// Import.SegmentSamplePercentage, which samples during archive extraction.
// Higher sampling catches more corruption but adds overhead. Default 5%.
SegmentSamplePercentage int `yaml:"segment_sample_percentage" mapstructure:"segment_sample_percentage" json:"segment_sample_percentage,omitempty"`
MaxRetries int `yaml:"max_retries" mapstructure:"max_retries" json:"max_retries"`
LibrarySyncIntervalMinutes int `` /* 128-byte string literal not displayed */
LibrarySyncConcurrency int `yaml:"library_sync_concurrency" mapstructure:"library_sync_concurrency" json:"library_sync_concurrency,omitempty"`
ResolveRepairOnImport *bool `yaml:"resolve_repair_on_import" mapstructure:"resolve_repair_on_import" json:"resolve_repair_on_import,omitempty"`
VerifyData *bool `yaml:"verify_data" mapstructure:"verify_data" json:"verify_data,omitempty"`
CheckAllSegments *bool `yaml:"check_all_segments" mapstructure:"check_all_segments" json:"check_all_segments,omitempty"`
ReadTimeoutSeconds int `yaml:"read_timeout_seconds" mapstructure:"read_timeout_seconds" json:"read_timeout_seconds,omitempty"`
AcceptableMissingSegmentsPercentage float64 `` /* 145-byte string literal not displayed */
// ExcludedCategories lists SABnzbd category names whose files must never be
// registered for health checking by the library-sync discovery pass. Matching
// is by the category's configured directory under CompleteDir and is
// case-insensitive. Empty means no categories are excluded.
ExcludedCategories []string `yaml:"excluded_categories" mapstructure:"excluded_categories" json:"excluded_categories,omitempty"`
Repair RepairConfig `yaml:"repair" mapstructure:"repair" json:"repair"`
// CorruptionAction controls what happens when the health checker or a streaming read
// confirms real (non-degraded) corruption: "repair" (default) triggers an Arr rescan;
// "delete" removes the file's metadata/NZB/health record and cleans up now-empty
// parent directories instead. Degraded files are never affected either way.
CorruptionAction string `yaml:"corruption_action" mapstructure:"corruption_action" json:"corruption_action,omitempty"`
// VerifyContent, when true, probes each eligible video/audio file's
// first bytes through the serving stack during a health check and
// marks the file corrupted if no recognized media container signature
// is found. Distinct from the unrelated, unused VerifyData field above.
VerifyContent *bool `yaml:"verify_content" mapstructure:"verify_content" json:"verify_content,omitempty"`
VerifyContentTimeoutSeconds *int `` /* 131-byte string literal not displayed */
// CorruptedRetentionDays bounds how long the corrupted_metadata safety copies
// created by MoveToCorrupted are kept before the health cycle prunes them.
// nil or 0 means keep forever, which is what every install did before this
// setting existed.
CorruptedRetentionDays *int `yaml:"corrupted_retention_days" mapstructure:"corrupted_retention_days" json:"corrupted_retention_days,omitempty"`
}
HealthConfig represents health checker configuration
type IgnoredMessage ¶
type IgnoredMessage struct {
Message string `yaml:"message" mapstructure:"message" json:"message"`
Enabled bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
}
IgnoredMessage represents an error message to ignore during queue cleanup
type ImportConfig ¶
type ImportConfig struct {
// RSSFeedURL is an optional indexer cart feed; empty disables polling.
RSSFeedURL string `yaml:"rss_feed_url" mapstructure:"rss_feed_url" json:"rss_feed_url"`
// RSSPollIntervalSeconds defaults to 300 when omitted or zero.
RSSPollIntervalSeconds int `yaml:"rss_poll_interval_seconds" mapstructure:"rss_poll_interval_seconds" json:"rss_poll_interval_seconds"`
MaxProcessorWorkers int `yaml:"max_processor_workers" mapstructure:"max_processor_workers" json:"max_processor_workers"`
QueueProcessingIntervalSeconds int `` /* 130-byte string literal not displayed */
AllowedFileExtensions []string `yaml:"allowed_file_extensions" mapstructure:"allowed_file_extensions" json:"allowed_file_extensions"`
// MaxConcurrentImports caps the number of NZB imports that may run
// end-to-end at the same time. 0 = unlimited. NNTP connection use is
// balanced automatically: imports share the pool's full capacity and
// yield to streams (priority lane + adaptive connection budget).
MaxConcurrentImports int `yaml:"max_concurrent_imports" mapstructure:"max_concurrent_imports" json:"max_concurrent_imports"`
// StreamHeadroomConnections is how many connections are held back from
// import per active stream. On a saturated link those connections are slack
// — they are not converting into bytes — so handing them to playback costs
// little and measurably shortens stream latency. Past that point the pool
// can no longer fill the link and import throughput really does fall.
//
// Measured at 100 connections behind a 400 MB/s link: 8 is free (import
// 358 vs 359 MB/s) and takes stream p50 190ms -> 179ms; 32 costs ~13% import
// and takes p50 to 146ms and p99 245ms -> 167ms. The right value depends on
// the link rate and pool size, so it is a knob rather than a constant.
// 0 disables the reservation entirely.
// A nil pointer means "unset, use the default"; an explicit 0 disables the
// reservation. A plain int cannot express that difference, since YAML omits
// and YAML-zero both decode to 0.
StreamHeadroomConnections *int `yaml:"stream_headroom_connections" mapstructure:"stream_headroom_connections" json:"stream_headroom_connections,omitempty"`
MaxDownloadPrefetch int `yaml:"max_download_prefetch" mapstructure:"max_download_prefetch" json:"max_download_prefetch"`
// SegmentSamplePercentage is the fraction (1-100) of segments randomly sampled
// during import-phase validation (RAR extraction, archive integrity). Distinct from
// Health.SegmentSamplePercentage, which samples during post-import health checks.
// Lower defaults faster imports but skips error detection. Default 1%.
SegmentSamplePercentage int `yaml:"segment_sample_percentage" mapstructure:"segment_sample_percentage" json:"segment_sample_percentage"`
ReadTimeoutSeconds int `yaml:"read_timeout_seconds" mapstructure:"read_timeout_seconds" json:"read_timeout_seconds"`
IsoAnalyzeTimeoutSeconds *int `yaml:"iso_analyze_timeout_seconds" mapstructure:"iso_analyze_timeout_seconds" json:"iso_analyze_timeout_seconds,omitempty"`
ImportStrategy ImportStrategy `yaml:"import_strategy" mapstructure:"import_strategy" json:"import_strategy"`
ImportDir *string `yaml:"import_dir" mapstructure:"import_dir" json:"import_dir,omitempty"`
WatchDir *string `yaml:"watch_dir" mapstructure:"watch_dir" json:"watch_dir,omitempty"`
WatchIntervalSeconds *int `yaml:"watch_interval_seconds" mapstructure:"watch_interval_seconds" json:"watch_interval_seconds,omitempty"`
AllowNestedRarExtraction *bool `yaml:"allow_nested_rar_extraction" mapstructure:"allow_nested_rar_extraction" json:"allow_nested_rar_extraction,omitempty"`
ExpandBlurayIso *bool `yaml:"expand_bluray_iso" mapstructure:"expand_bluray_iso" json:"expand_bluray_iso,omitempty"`
RenameToNzbName *bool `yaml:"rename_to_nzb_name" mapstructure:"rename_to_nzb_name" json:"rename_to_nzb_name,omitempty"`
FilterSampleFiles *bool `yaml:"filter_sample_files" mapstructure:"filter_sample_files" json:"filter_sample_files,omitempty"`
FailedItemRetentionHours *int `yaml:"failed_item_retention_hours" mapstructure:"failed_item_retention_hours" json:"failed_item_retention_hours,omitempty"`
HistoryRetentionDays *int `yaml:"history_retention_days" mapstructure:"history_retention_days" json:"history_retention_days,omitempty"`
// VerifyContent, when true, probes each eligible video/audio file's
// first bytes through the serving stack after import and fails the
// import if no recognized media container signature is found.
VerifyContent *bool `yaml:"verify_content" mapstructure:"verify_content" json:"verify_content,omitempty"`
VerifyContentTimeoutSeconds *int `` /* 131-byte string literal not displayed */
}
ImportConfig represents import processing configuration
type ImportStrategy ¶
type ImportStrategy string
ImportStrategy represents the import strategy type
const ( ImportStrategyNone ImportStrategy = "NONE" ImportStrategySYMLINK ImportStrategy = "SYMLINK" ImportStrategySTRM ImportStrategy = "STRM" )
type LogConfig ¶
type LogConfig struct {
File string `yaml:"file" mapstructure:"file" json:"file,omitempty"` // Log file path (empty = console only)
Level string `yaml:"level" mapstructure:"level" json:"level,omitempty"` // Log level (debug, info, warn, error)
MaxSize int `yaml:"max_size" mapstructure:"max_size" json:"max_size,omitempty"` // Max size in MB before rotation
MaxAge int `yaml:"max_age" mapstructure:"max_age" json:"max_age,omitempty"` // Max age in days to keep files
MaxBackups int `yaml:"max_backups" mapstructure:"max_backups" json:"max_backups,omitempty"` // Max number of old files to keep
Compress bool `yaml:"compress" mapstructure:"compress" json:"compress,omitempty"` // Compress old log files
}
LogConfig represents logging configuration with rotation support
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager manages configuration state and persistence
func NewManager ¶
NewManager creates a new configuration manager
func (*Manager) ClearLibrarySyncFlag ¶
func (m *Manager) ClearLibrarySyncFlag()
ClearLibrarySyncFlag clears the library sync needed flag
func (*Manager) GetConfigGetter ¶
func (m *Manager) GetConfigGetter() ConfigGetter
GetConfigGetter returns a function that provides the current configuration
func (*Manager) GetPreviousMountPath ¶
GetPreviousMountPath returns the previous mount path before the last change
func (*Manager) NeedsLibrarySync ¶
NeedsLibrarySync returns whether a library sync is needed due to configuration changes
func (*Manager) OnConfigChange ¶
func (m *Manager) OnConfigChange(callback ChangeCallback)
OnConfigChange registers a callback to be called when configuration changes
func (*Manager) ReloadConfig ¶
ReloadConfig reloads configuration from file
func (*Manager) SaveConfig ¶
SaveConfig saves the current configuration to file
func (*Manager) UpdateConfig ¶
UpdateConfig updates the current configuration (thread-safe)
func (*Manager) ValidateConfig ¶
ValidateConfig validates the configuration using existing validation logic
func (*Manager) ValidateConfigUpdate ¶
ValidateConfigUpdate validates configuration updates with additional restrictions
type MetadataBackupConfig ¶
type MetadataBackupConfig struct {
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
Schedule string `yaml:"schedule" mapstructure:"schedule" json:"schedule"` // cron expression (UTC)
KeepBackups int `yaml:"keep_backups" mapstructure:"keep_backups" json:"keep_backups"`
Path string `yaml:"path" mapstructure:"path" json:"path"`
}
MetadataBackupConfig represents metadata backup configuration
type MetadataConfig ¶
type MetadataConfig struct {
RootPath string `yaml:"root_path" mapstructure:"root_path" json:"root_path"`
Backup MetadataBackupConfig `yaml:"backup" mapstructure:"backup" json:"backup"`
Migration MetadataMigrationConfig `yaml:"migration" mapstructure:"migration" json:"migration"`
}
MetadataConfig represents metadata filesystem configuration
type MetadataMigrationConfig ¶
type MetadataMigrationConfig struct {
// DefaultGroup is the newsgroup written into synthesized NzbStore entries.
// Legacy metas do not retain the original groups, and nzb.BuildNZB renders an
// empty <groups> element without this, which most NZB clients reject.
DefaultGroup string `yaml:"default_group" mapstructure:"default_group" json:"default_group"`
}
MetadataMigrationConfig configures the legacy-metadata → v3 migration.
type NetworkConfig ¶
type NetworkConfig struct {
HTTPProxy string `yaml:"http_proxy" mapstructure:"http_proxy" json:"http_proxy,omitempty"`
HTTPSProxy string `yaml:"https_proxy" mapstructure:"https_proxy" json:"https_proxy,omitempty"`
NoProxy string `yaml:"no_proxy" mapstructure:"no_proxy" json:"no_proxy,omitempty"`
}
NetworkConfig holds outbound HTTP routing options applied to every external client (indexers, arrs, SABnzbd fallback, NZBLNK resolver). Internal endpoints (RC server, self-loopback) are unaffected.
Semantics mirror Go's standard HTTP_PROXY/HTTPS_PROXY/NO_PROXY env vars. Empty strings disable proxying for that scheme.
func (NetworkConfig) GetHTTPProxy ¶
func (n NetworkConfig) GetHTTPProxy() string
GetHTTPProxy returns the configured HTTP proxy URL. Implements the httpclient.NetworkProxyConfig interface to avoid config↔httpclient import cycles.
func (NetworkConfig) GetHTTPSProxy ¶
func (n NetworkConfig) GetHTTPSProxy() string
GetHTTPSProxy returns the configured HTTPS proxy URL.
func (NetworkConfig) GetNoProxy ¶
func (n NetworkConfig) GetNoProxy() string
GetNoProxy returns the comma-separated bypass list.
type NewsnabIndexerConfig ¶
type NewsnabIndexerConfig struct {
ID string `yaml:"id" mapstructure:"id" json:"id"`
Name string `yaml:"name" mapstructure:"name" json:"name"`
URL string `yaml:"url" mapstructure:"url" json:"url"`
APIKey string `yaml:"api_key" mapstructure:"api_key" json:"api_key"`
Categories []int `yaml:"categories" mapstructure:"categories" json:"categories,omitempty"`
Weight int `yaml:"weight" mapstructure:"weight" json:"weight"`
TimeoutSeconds int `yaml:"timeout_seconds" mapstructure:"timeout_seconds" json:"timeout_seconds"`
Enabled bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
}
NewsnabIndexerConfig holds configuration for a direct Newznab indexer.
type NzblnkConfig ¶
type NzblnkConfig struct {
UserAgent string `yaml:"user_agent,omitempty" mapstructure:"user_agent" json:"-"`
}
NzblnkConfig is the legacy scoped user-agent config, retained only so existing YAML files can be migrated into the global user_agent field.
type Par2RepairConfig ¶
type Par2RepairConfig struct {
// RecoveryMargin is the baseline number of spare recovery rows. Nil keeps
// eight; zero minimizes arithmetic but may require another full sweep.
RecoveryMargin *int `yaml:"recovery_margin,omitempty" mapstructure:"recovery_margin" json:"recovery_margin,omitempty"`
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled,omitempty"`
// MaxRepairRatio caps how large a fraction of a file's bytes a repair may
// reconstruct. The release's PAR2 redundancy is always the hard ceiling.
MaxRepairRatio float64 `yaml:"max_repair_ratio" mapstructure:"max_repair_ratio" json:"max_repair_ratio,omitempty"`
// MaxMemoryMB bounds one job's in-heap solver memory; jobs needing more
// still run, backed by memory-mapped scratch files next to the patch store.
MaxMemoryMB int `yaml:"max_memory_mb" mapstructure:"max_memory_mb" json:"max_memory_mb,omitempty"`
// MaxConcurrentJobs bounds simultaneously running repair jobs.
MaxConcurrentJobs int `yaml:"max_concurrent_jobs" mapstructure:"max_concurrent_jobs" json:"max_concurrent_jobs,omitempty"`
// MaxConnections bounds how many NNTP connections repair jobs use for
// article fetches (shared across concurrent jobs). Repair streams the
// whole release once, so this directly sets its download speed on an idle
// pool. Fetches ride the pool's background lane: while anything streams
// or imports, the pool holds repair to a quarter of each provider's
// connections regardless of this value. 0 (default) means 10.
MaxConnections int `yaml:"max_connections" mapstructure:"max_connections" json:"max_connections,omitempty"`
// MinReleaseSizeMB / MaxReleaseSizeMB bound the size of releases repair
// takes on (content bytes, PAR2 files excluded). A repair downloads the
// whole release once, so these let users skip releases too large to be
// worth the bandwidth or too small to bother with. 0 (default) means
// unbounded on that side — all sizes are repaired.
MinReleaseSizeMB int `yaml:"min_release_size_mb" mapstructure:"min_release_size_mb" json:"min_release_size_mb,omitempty"`
MaxReleaseSizeMB int `yaml:"max_release_size_mb" mapstructure:"max_release_size_mb" json:"max_release_size_mb,omitempty"`
// MaxPatchStoreMB bounds the on-disk patch store size; oldest patches are
// evicted first when the cap is exceeded. 0 (default) means unlimited.
MaxPatchStoreMB int `yaml:"max_patch_store_mb" mapstructure:"max_patch_store_mb" json:"max_patch_store_mb,omitempty"`
// PatchDir is where repaired article payloads (and the solver's transient
// scratch files) are stored. Empty (default) means <metadata_root>/patches.
// Applied at startup; changing it does not move existing patches.
PatchDir string `yaml:"patch_dir" mapstructure:"patch_dir" json:"patch_dir,omitempty"`
// ArrFirst makes PAR2 repair the fallback for corrupted files: the health
// worker triggers the ARR rescan first exactly as before, and enqueues a
// PAR2 repair only when nothing is found in the ARRs (no instance
// configured, none tracks the file) or ARR repair is disabled. On by
// default; disable to keep PAR2 out of the corrupted-file flow (degraded
// files, playback holes and repair-on-import still repair via PAR2
// directly).
ArrFirst *bool `yaml:"arr_first" mapstructure:"arr_first" json:"arr_first,omitempty"`
// RepairOnImport queues a repair as soon as an import completes with
// confirmed missing segments, instead of waiting for the first playback or
// a health check. Off by default: every repair costs one full release
// download, so a large damaged backlog would be expensive. Worth enabling
// when your library outlives article retention — a release's PAR2 volumes
// are most likely to still be retrievable close to the post date.
RepairOnImport *bool `yaml:"repair_on_import" mapstructure:"repair_on_import" json:"repair_on_import,omitempty"`
}
Par2RepairConfig configures background PAR2 repair of missing usenet articles. Repaired article payloads are persisted under <metadata_root>/patches and served on the read path's hole branch.
func (Par2RepairConfig) EffectiveArrFirst ¶
func (p Par2RepairConfig) EffectiveArrFirst() bool
EffectiveArrFirst reports whether corrupted files fall back to PAR2 repair after the ARR repair comes up empty. Defaults to true when unset (configs written before the knob existed).
func (Par2RepairConfig) EffectiveMaxConnections ¶
func (p Par2RepairConfig) EffectiveMaxConnections() int
EffectiveMaxConnections resolves the repair fetch connection bound, defaulting to 10 when unset (configs written before the knob existed).
func (Par2RepairConfig) EffectivePatchDir ¶
func (p Par2RepairConfig) EffectivePatchDir(metadataRoot string) string
EffectivePatchDir resolves where repaired article payloads live: the configured PatchDir, or "patches" under the metadata root when unset.
func (Par2RepairConfig) EffectiveRepairOnImport ¶
func (p Par2RepairConfig) EffectiveRepairOnImport() bool
EffectiveRepairOnImport reports whether imports queue PAR2 repairs. Requires the feature itself to be enabled; defaults to false when unset.
type ProviderChange ¶
type ProviderChange struct {
Type ProviderChangeType
ProviderID string
OldProvider *ProviderConfig // nil for Added
NewProvider *ProviderConfig // nil for Removed
}
ProviderChange describes a single provider change between two configurations.
type ProviderChangeType ¶
type ProviderChangeType int
ProviderChangeType describes the kind of provider change detected by ProvidersDiff.
const ( ProviderAdded ProviderChangeType = iota ProviderRemoved ProviderModified )
type ProviderConfig ¶
type ProviderConfig struct {
// ID is a stable public identifier used in pool names, metrics, and errors.
// It must never contain credentials or non-graphic characters.
ID string `yaml:"id" mapstructure:"id" json:"id"`
Name string `yaml:"name" mapstructure:"name" json:"name,omitempty"`
Host string `yaml:"host" mapstructure:"host" json:"host"`
Port int `yaml:"port" mapstructure:"port" json:"port"`
Username string `yaml:"username" mapstructure:"username" json:"username"`
Password string `yaml:"password" mapstructure:"password" json:"-"`
MaxConnections int `yaml:"max_connections" mapstructure:"max_connections" json:"max_connections"`
MinConnectionsAlive int `yaml:"min_connections_alive" mapstructure:"min_connections_alive" json:"min_connections_alive,omitempty"`
// InflightRequests caps concurrent decoded article bodies per connection (memory
// ceiling). In practice, the pool-wide ImportBudget caps total in-flight bodies
// to roughly the connection count, so each connection carries ~1 body. Peak observed
// depth is 3-4 against this cap of 10. Raising it does not improve import throughput.
InflightRequests int `yaml:"inflight_requests" mapstructure:"inflight_requests" json:"inflight_requests"`
// StatInflightRequests caps the per-connection STAT pipeline depth (bodyless
// existence checks). Its pool-wide aggregate (connections × depth, clamped to 4096)
// determines how much an idle-pool health sweep can widen: measured 24x sweep
// throughput improvement. While a stream is active the sweep is capped lower regardless.
StatInflightRequests int `yaml:"stat_inflight_requests" mapstructure:"stat_inflight_requests" json:"stat_inflight_requests"`
// StreamInflightRequests caps streaming (priority-lane) bodies in flight
// per connection, so a playback read never queues behind a connection's
// worth of read-ahead. 0 defaults to 4; values above inflight_requests
// are capped to it.
StreamInflightRequests int `yaml:"stream_inflight_requests" mapstructure:"stream_inflight_requests" json:"stream_inflight_requests,omitempty"`
TLS bool `yaml:"tls" mapstructure:"tls" json:"tls"`
InsecureTLS bool `yaml:"insecure_tls" mapstructure:"insecure_tls" json:"insecure_tls"`
ProxyURL string `yaml:"proxy_url" mapstructure:"proxy_url" json:"proxy_url,omitempty"`
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled,omitempty"`
IsBackupProvider *bool `yaml:"is_backup_provider" mapstructure:"is_backup_provider" json:"is_backup_provider,omitempty"`
StorageGroup string `yaml:"storage_group" mapstructure:"storage_group" json:"storage_group,omitempty"`
SkipPing bool `yaml:"skip_ping" mapstructure:"skip_ping" json:"skip_ping,omitempty"`
KeepaliveIntervalSeconds int `yaml:"keepalive_interval_seconds" mapstructure:"keepalive_interval_seconds" json:"keepalive_interval_seconds,omitempty"`
KeepaliveCommand string `yaml:"keepalive_command" mapstructure:"keepalive_command" json:"keepalive_command,omitempty"`
UserAgent string `yaml:"user_agent" mapstructure:"user_agent" json:"user_agent,omitempty"`
// MaxArticleAgeDays is how far back this provider's retention reaches.
// Articles older than this are fetched from it only after every provider
// that does reach back that far has been tried, so a short-retention
// provider absorbs recent posts and leaves the deep-retention providers'
// connections and quota for the articles that have nowhere else to go.
// 0 (the default) declares no limit.
MaxArticleAgeDays int `yaml:"max_article_age_days" mapstructure:"max_article_age_days" json:"max_article_age_days,omitempty"`
// StrictMaxArticleAge makes MaxArticleAgeDays binding rather than an
// ordering preference: the provider is not contacted at all for an
// article older than its retention. For a metered account whose capacity
// should not be spent on a request that will almost certainly 430.
StrictMaxArticleAge bool `yaml:"strict_max_article_age" mapstructure:"strict_max_article_age" json:"strict_max_article_age,omitempty"`
QuotaBytes int64 `yaml:"quota_bytes" mapstructure:"quota_bytes" json:"quota_bytes,omitempty"`
QuotaPeriodHours int `yaml:"quota_period_hours" mapstructure:"quota_period_hours" json:"quota_period_hours,omitempty"`
LastRTTMs int64 `yaml:"last_rtt_ms" mapstructure:"last_rtt_ms" json:"last_rtt_ms,omitempty"`
LastSpeedTestMbps float64 `yaml:"last_speed_test_mbps" mapstructure:"last_speed_test_mbps" json:"last_speed_test_mbps,omitempty"`
LastSpeedTestTime *time.Time `yaml:"last_speed_test_time" mapstructure:"last_speed_test_time" json:"last_speed_test_time,omitempty"`
AccountExpirationDate string `yaml:"account_expiration_date" mapstructure:"account_expiration_date" json:"account_expiration_date,omitempty"`
}
ProviderConfig represents a single NNTP provider configuration
func (*ProviderConfig) NNTPPoolName ¶
func (p *ProviderConfig) NNTPPoolName() string
NNTPPoolName returns the stable ID nntppool uses to identify this provider.
func (*ProviderConfig) ToNNTPProvider ¶
func (p *ProviderConfig) ToNNTPProvider() nntppool.Provider
ToNNTPProvider converts a single ProviderConfig to an nntppool.Provider. Does not check the Enabled flag — caller is responsible for that.
type ProwlarrConfig ¶
type ProwlarrConfig struct {
// Enabled controls whether Prowlarr search is active for the Stremio addon.
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
// Host is the Prowlarr base URL (e.g. "http://localhost:9696").
Host string `yaml:"host" mapstructure:"host" json:"host,omitempty"`
// APIKey is the Prowlarr API key.
APIKey string `yaml:"api_key" mapstructure:"api_key" json:"api_key,omitempty"`
// Categories filters search results by Newznab category IDs.
// Defaults to 5000 (Movies), 5010 (Movies/Foreign), 5030 (TV), 5040 (TV/HD).
Categories []int `yaml:"categories" mapstructure:"categories" json:"categories,omitempty"`
// Indexers optionally restricts searches to specific Prowlarr indexer IDs.
// Empty = search across all configured indexers.
Indexers []int `yaml:"indexers" mapstructure:"indexers" json:"indexers,omitempty"`
// PreferredIndexers lists Prowlarr indexer IDs to prioritize and rank above others.
PreferredIndexers []int `yaml:"preferred_indexers" mapstructure:"preferred_indexers" json:"preferred_indexers,omitempty"`
// PreferredIndexerNames lists Prowlarr indexer names/keywords to prioritize and rank above others.
PreferredIndexerNames []string `yaml:"preferred_indexer_names" mapstructure:"preferred_indexer_names" json:"preferred_indexer_names,omitempty"`
// Languages is an optional list of keywords; releases must contain at least one to pass.
// Empty = no filtering. Examples: ["Esp", "🇪🇸", "Spanish", "DUAL"]
Languages []string `yaml:"languages" mapstructure:"languages" json:"languages,omitempty"`
// PreferredLanguages lists language keywords to prioritize and rank above others.
PreferredLanguages []string `yaml:"preferred_languages" mapstructure:"preferred_languages" json:"preferred_languages,omitempty"`
// Qualities is an optional list of keywords; releases must contain at least one to pass.
// Empty = no filtering. Examples: ["1080p", "HD", "4K", "3D"]
Qualities []string `yaml:"qualities" mapstructure:"qualities" json:"qualities,omitempty"`
// ExcludeKeywords is an optional list of keywords/patterns; releases containing any are dropped.
// Examples: ["DV", "DoVi", "CAM", "TS", "TeleSync"]
ExcludeKeywords []string `yaml:"exclude_keywords" mapstructure:"exclude_keywords" json:"exclude_keywords,omitempty"`
// CustomScores maps keyword/regex patterns to numeric scores (TRaSH guide style).
// Positive scores promote releases; negative scores demote them.
// Examples: {"2160p": 500, "REMUX": 300, "DV": -1000}
CustomScores map[string]int `yaml:"custom_scores" mapstructure:"custom_scores" json:"custom_scores,omitempty"`
}
ProwlarrConfig configures the Prowlarr indexer integration for Stremio addon searches.
type RCloneConfig ¶
type RCloneConfig struct {
// RClone Path
Path string `yaml:"path" mapstructure:"path" json:"path"`
// Encryption
Password string `yaml:"password" mapstructure:"password" json:"-"`
Salt string `yaml:"salt" mapstructure:"salt" json:"-"`
// RC (Remote Control) Configuration
RCEnabled *bool `yaml:"rc_enabled" mapstructure:"rc_enabled" json:"rc_enabled"`
RCUrl string `yaml:"rc_url" mapstructure:"rc_url" json:"rc_url"`
RCPort int `yaml:"rc_port" mapstructure:"rc_port" json:"rc_port"`
RCUser string `yaml:"rc_user" mapstructure:"rc_user" json:"rc_user"`
RCPass string `yaml:"rc_pass" mapstructure:"rc_pass" json:"rc_pass,omitempty"`
RCOptions map[string]string `yaml:"rc_options" mapstructure:"rc_options" json:"rc_options"`
// Mount Configuration
MountEnabled *bool `yaml:"mount_enabled" mapstructure:"mount_enabled" json:"mount_enabled"`
VFSName string `yaml:"vfs_name" mapstructure:"vfs_name" json:"vfs_name"`
MountOptions map[string]string `yaml:"mount_options" mapstructure:"mount_options" json:"mount_options"`
LogLevel string `yaml:"log_level" mapstructure:"log_level" json:"log_level"`
UID int `yaml:"uid" mapstructure:"uid" json:"uid"`
GID int `yaml:"gid" mapstructure:"gid" json:"gid"`
Umask string `yaml:"umask" mapstructure:"umask" json:"umask"`
BufferSize string `yaml:"buffer_size" mapstructure:"buffer_size" json:"buffer_size"`
AttrTimeout string `yaml:"attr_timeout" mapstructure:"attr_timeout" json:"attr_timeout"`
Transfers int `yaml:"transfers" mapstructure:"transfers" json:"transfers"`
// VFS Cache Settings
CacheDir string `yaml:"cache_dir" mapstructure:"cache_dir" json:"cache_dir"`
VFSCacheMode string `yaml:"vfs_cache_mode" mapstructure:"vfs_cache_mode" json:"vfs_cache_mode"`
VFSCachePollInterval string `yaml:"vfs_cache_poll_interval" mapstructure:"vfs_cache_poll_interval" json:"vfs_cache_poll_interval"`
VFSReadChunkSize string `yaml:"vfs_read_chunk_size" mapstructure:"vfs_read_chunk_size" json:"vfs_read_chunk_size"`
VFSReadChunkSizeLimit string `yaml:"vfs_read_chunk_size_limit" mapstructure:"vfs_read_chunk_size_limit" json:"vfs_read_chunk_size_limit"`
VFSCacheMaxSize string `yaml:"vfs_cache_max_size" mapstructure:"vfs_cache_max_size" json:"vfs_cache_max_size"`
VFSCacheMaxAge string `yaml:"vfs_cache_max_age" mapstructure:"vfs_cache_max_age" json:"vfs_cache_max_age"`
VFSReadAhead string `yaml:"vfs_read_ahead" mapstructure:"vfs_read_ahead" json:"vfs_read_ahead"`
DirCacheTime string `yaml:"dir_cache_time" mapstructure:"dir_cache_time" json:"dir_cache_time"`
VFSCacheMinFreeSpace string `yaml:"vfs_cache_min_free_space" mapstructure:"vfs_cache_min_free_space" json:"vfs_cache_min_free_space"`
VFSDiskSpaceTotal string `yaml:"vfs_disk_space_total" mapstructure:"vfs_disk_space_total" json:"vfs_disk_space_total"`
VFSReadChunkStreams int `yaml:"vfs_read_chunk_streams" mapstructure:"vfs_read_chunk_streams" json:"vfs_read_chunk_streams"`
// Mount-Specific Settings
AllowOther bool `yaml:"allow_other" mapstructure:"allow_other" json:"allow_other"`
AllowNonEmpty bool `yaml:"allow_non_empty" mapstructure:"allow_non_empty" json:"allow_non_empty"`
ReadOnly bool `yaml:"read_only" mapstructure:"read_only" json:"read_only"`
Timeout string `yaml:"timeout" mapstructure:"timeout" json:"timeout"`
Syslog bool `yaml:"syslog" mapstructure:"syslog" json:"syslog"`
// RcdRestartAfter is how long the rcd subprocess must stay unresponsive to
// liveness probes before it is killed and restarted. Empty means the built-in
// default. Restarting is disruptive, because re-establishing the mount
// unmounts it out from under every process reading it, so an install whose
// rcd goes briefly slow under load can raise this to ride the stall out.
RcdRestartAfter string `yaml:"rcd_restart_after" mapstructure:"rcd_restart_after" json:"rcd_restart_after"`
// Advanced Settings
NoModTime bool `yaml:"no_mod_time" mapstructure:"no_mod_time" json:"no_mod_time"`
NoChecksum bool `yaml:"no_checksum" mapstructure:"no_checksum" json:"no_checksum"`
AsyncRead bool `yaml:"async_read" mapstructure:"async_read" json:"async_read"`
VFSFastFingerprint bool `yaml:"vfs_fast_fingerprint" mapstructure:"vfs_fast_fingerprint" json:"vfs_fast_fingerprint"`
UseMmap bool `yaml:"use_mmap" mapstructure:"use_mmap" json:"use_mmap"`
Links bool `yaml:"links" mapstructure:"links" json:"links"`
}
RCloneConfig represents rclone configuration
type RepairConfig ¶
type RepairConfig struct {
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled,omitempty"`
IntervalMinutes int `yaml:"interval_minutes" mapstructure:"interval_minutes" json:"interval_minutes,omitempty"`
MaxCoolDownHours int `yaml:"max_cooldown_hours" mapstructure:"max_cooldown_hours" json:"max_cooldown_hours,omitempty"`
MaxRepairRetries int `yaml:"max_repair_retries" mapstructure:"max_repair_retries" json:"max_repair_retries"`
ExponentialBackoff *bool `yaml:"exponential_backoff" mapstructure:"exponential_backoff" json:"exponential_backoff,omitempty"`
// AutoSearchWaitSeconds bounds how long a repair waits for the ARR's own
// automatic redownload search — queued by the ARR the moment a release is
// blocklisted — to finish before the file record is deleted and AltMount
// issues its own targeted search. 0 disables the wait and restores the
// previous fire-and-forget ordering.
AutoSearchWaitSeconds int `yaml:"auto_search_wait_seconds" mapstructure:"auto_search_wait_seconds" json:"auto_search_wait_seconds"`
// FileDeleteConfirmSeconds bounds how long a repair waits for the ARR to
// report the deleted file record as unlinked before issuing its search.
FileDeleteConfirmSeconds int `yaml:"file_delete_confirm_seconds" mapstructure:"file_delete_confirm_seconds" json:"file_delete_confirm_seconds"`
}
RepairConfig represents repair behavior configuration
type SABnzbdCategory ¶
type SABnzbdCategory struct {
Name string `yaml:"name" mapstructure:"name" json:"name"`
Order int `yaml:"order" mapstructure:"order" json:"order"`
Priority int `yaml:"priority" mapstructure:"priority" json:"priority"`
Dir string `yaml:"dir" mapstructure:"dir" json:"dir"`
Type string `yaml:"type" mapstructure:"type" json:"type"` // "sonarr" or "radarr"
}
SABnzbdCategory represents a SABnzbd category configuration
type SABnzbdConfig ¶
type SABnzbdConfig struct {
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
CompleteDir string `yaml:"complete_dir" mapstructure:"complete_dir" json:"complete_dir"`
DownloadClientBaseURL string `yaml:"download_client_base_url" mapstructure:"download_client_base_url" json:"download_client_base_url,omitempty"`
Categories []SABnzbdCategory `yaml:"categories" mapstructure:"categories" json:"categories"`
// HistoryRetentionMinutes controls how far back the SABnzbd-emulating history
// endpoint looks into import_history when *arr clients poll without a specific
// nzo_id filter. Older entries are still returned when *arr asks for them by
// nzo_id. Defaults to 10080 (7 days).
HistoryRetentionMinutes int `yaml:"history_retention_minutes" mapstructure:"history_retention_minutes" json:"history_retention_minutes,omitempty"`
// Zero uses the default; either negative value disables the delete guard.
DeleteGuardMaxFolders int `yaml:"delete_guard_max_folders" mapstructure:"delete_guard_max_folders" json:"delete_guard_max_folders"`
DeleteGuardWindowMinutes int `yaml:"delete_guard_window_minutes" mapstructure:"delete_guard_window_minutes" json:"delete_guard_window_minutes"`
// Fallback configuration for sending failed imports to external SABnzbd
FallbackHost string `yaml:"fallback_host" mapstructure:"fallback_host" json:"fallback_host"`
FallbackAPIKey string `yaml:"fallback_api_key" mapstructure:"fallback_api_key" json:"fallback_api_key"` // Masked in API responses
}
SABnzbdConfig represents SABnzbd-compatible API configuration
type SegmentCacheConfig ¶
type SegmentCacheConfig struct {
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
CachePath string `yaml:"cache_path" mapstructure:"cache_path" json:"cache_path"`
MaxSizeGB int `yaml:"max_size_gb" mapstructure:"max_size_gb" json:"max_size_gb"`
// ExpiryHours controls how long cached segments are kept before automatic
// eviction. Set to 0 to disable expiry (cache forever, bounded only by
// MaxSizeGB via LRU eviction). Left unset (nil) it defaults to 24 hours.
ExpiryHours *int `yaml:"expiry_hours" mapstructure:"expiry_hours" json:"expiry_hours"`
// MemoryMB bounds the in-memory tier of decoded articles that sits in
// front of the disk cache and is on even when the disk cache is off.
// Left unset (nil) it defaults to 256; an explicit 0 disables it.
MemoryMB *int `yaml:"memory_mb" mapstructure:"memory_mb" json:"memory_mb"`
}
SegmentCacheConfig configures the segment-aligned disk cache shared by FUSE and WebDAV. When enabled, this cache replaces the FUSE VFS disk cache and additionally benefits WebDAV. Cache key: Usenet message ID. Cache unit: ~750KB decoded segment (matches one NNTP article).
func (SegmentCacheConfig) MemoryBytes ¶
func (c SegmentCacheConfig) MemoryBytes() int64
MemoryBytes is the memory tier budget in bytes (0 = disabled).
type StreamScoringConfig ¶
type StreamScoringConfig struct {
Preset string `yaml:"preset" mapstructure:"preset" json:"preset"`
CustomFormats []TrashCustomFormatConfig `yaml:"custom_formats" mapstructure:"custom_formats" json:"custom_formats,omitempty"`
ExcludeKeywords []string `yaml:"exclude_keywords" mapstructure:"exclude_keywords" json:"exclude_keywords,omitempty"`
ExcludeRegex string `yaml:"exclude_regex,omitempty" mapstructure:"exclude_regex" json:"exclude_regex,omitempty"`
PreferredLanguages []string `yaml:"preferred_languages" mapstructure:"preferred_languages" json:"preferred_languages,omitempty"`
RequirePreferredLanguage bool `yaml:"require_preferred_language" mapstructure:"require_preferred_language" json:"require_preferred_language"`
}
StreamScoringConfig holds TRaSH scoring configuration.
type StreamingConfig ¶
type StreamingConfig struct {
MaxPrefetch int `yaml:"max_prefetch" mapstructure:"max_prefetch" json:"max_prefetch"`
// ReadTimeoutSeconds bounds a single streaming read (WebDAV Read and FUSE
// ReadAt alike). Nothing below this layer carries a deadline the caller can
// observe: a segment fetch that stalls without erroring parks the read
// indefinitely, and on FUSE that means an uninterruptible D-state for the
// reading process. On expiry the in-flight reader is interrupted and the
// read fails, so the caller gets an EIO it can act on. 0 uses the built-in
// default; a negative value disables the timeout.
ReadTimeoutSeconds int `yaml:"read_timeout_seconds" mapstructure:"read_timeout_seconds" json:"read_timeout_seconds"`
FailureMasking FailureMaskingConfig `yaml:"failure_masking" mapstructure:"failure_masking" json:"failure_masking"`
}
StreamingConfig represents streaming and chunking configuration
type StremioConfig ¶
type StremioConfig struct {
// Enabled controls whether the endpoint is active. Disabled by default.
// When false, the endpoint returns 404 Not Found.
Enabled *bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
// AddonName is the display name shown in Stremio's addon catalog.
AddonName string `yaml:"addon_name" mapstructure:"addon_name" json:"addon_name,omitempty"`
// AddonDescription is the description shown in Stremio's addon catalog.
AddonDescription string `yaml:"addon_description" mapstructure:"addon_description" json:"addon_description,omitempty"`
// DirectStream when true streams NZB media segments directly.
DirectStream *bool `yaml:"direct_stream" mapstructure:"direct_stream" json:"direct_stream,omitempty"`
// ShowCachedIndicator when true shows cached badges in stream titles.
ShowCachedIndicator *bool `yaml:"show_cached_indicator" mapstructure:"show_cached_indicator" json:"show_cached_indicator,omitempty"`
// FallbackTimeoutMs is the timeout before attempting a fallback release.
FallbackTimeoutMs int `yaml:"fallback_timeout_ms" mapstructure:"fallback_timeout_ms" json:"fallback_timeout_ms,omitempty"`
// MaxRetries is the maximum number of retry attempts for stream fetching.
MaxRetries int `yaml:"max_retries" mapstructure:"max_retries" json:"max_retries,omitempty"`
// StreamTTLSeconds is the stream cache expiration time in seconds.
StreamTTLSeconds int `yaml:"stream_ttl_seconds" mapstructure:"stream_ttl_seconds" json:"stream_ttl_seconds,omitempty"`
// NzbTTLHours controls how long a completed NZB result is cached before
// the same NZB is re-processed on the next request.
// Set to 0 to disable expiry (cache forever). Defaults to 24 hours.
NzbTTLHours int `yaml:"nzb_ttl_hours" mapstructure:"nzb_ttl_hours" json:"nzb_ttl_hours"`
// FailedReleaseTTLHours controls how long a release that failed to import stays
// excluded from the Stremio stream list. Mirrors NzbTTLHours semantics: it filters
// failure records by age rather than deleting them, so it is bounded above by
// Import.FailedItemRetentionHours. Set to 0 to exclude for as long as the record
// survives. Defaults to 24 hours.
FailedReleaseTTLHours int `yaml:"failed_release_ttl_hours" mapstructure:"failed_release_ttl_hours" json:"failed_release_ttl_hours"`
// MaxFallbackReleases caps how many *extra* releases a single play request may try
// after the first one fails. Set to 0 to disable fallback. Defaults to 2.
MaxFallbackReleases int `yaml:"max_fallback_releases" mapstructure:"max_fallback_releases" json:"max_fallback_releases"`
// IncludeLibraryStreams when true checks and presents matching completed files
// from your Altmount library as instant 0s stream options in Stremio. Defaults to true.
IncludeLibraryStreams *bool `yaml:"include_library_streams" mapstructure:"include_library_streams" json:"include_library_streams,omitempty"`
// SkipSearchWhenCached returns matching cached streams without searching indexers.
// Defaults to false; a cache miss always falls back to the normal search.
SkipSearchWhenCached bool `yaml:"skip_search_when_cached" mapstructure:"skip_search_when_cached" json:"skip_search_when_cached"`
// Display controls how releases are labelled in Stremio's stream list.
Display StremioDisplayConfig `yaml:"display" mapstructure:"display" json:"display"`
// FastFailHeaderOnly when true causes Stremio-originated imports to fail fast
// immediately on the release-level probe when missing articles are detected,
// skipping the multi-part RAR per-file Stat sweep. Defaults to true.
FastFailHeaderOnly *bool `yaml:"fast_fail_header_only" mapstructure:"fast_fail_header_only" json:"fast_fail_header_only"`
// SkipRepair when true fails a Stremio-originated import that would need a
// PAR2 repair instead of parking it for one, so playback falls back to the
// next release rather than waiting. Defaults to false.
SkipRepair *bool `yaml:"skip_repair" mapstructure:"skip_repair" json:"skip_repair,omitempty"`
// BaseURL is the public base URL used when building Stremio stream links
// (e.g. "https://altmount.example.com"). Falls back to the auto-detected
// request origin when not set.
BaseURL string `yaml:"base_url" mapstructure:"base_url" json:"base_url,omitempty"`
// Indexers configures Prowlarr and direct Newsnab search providers.
Indexers StremioIndexersConfig `yaml:"indexers" mapstructure:"indexers" json:"indexers"`
// Scoring configures TRaSH format scoring and exclusions.
Scoring StreamScoringConfig `yaml:"scoring" mapstructure:"scoring" json:"scoring"`
// Prowlarr configures the legacy Prowlarr indexer settings (retained for compatibility).
Prowlarr ProwlarrConfig `yaml:"prowlarr" mapstructure:"prowlarr" json:"prowlarr"`
}
StremioConfig configures the Stremio NZB stream endpoint (POST /api/nzb/streams).
func (StremioConfig) EffectiveFastFailHeaderOnly ¶
func (s StremioConfig) EffectiveFastFailHeaderOnly() bool
func (StremioConfig) EffectiveIncludeLibraryStreams ¶
func (s StremioConfig) EffectiveIncludeLibraryStreams() bool
EffectiveIncludeLibraryStreams reports whether Stremio stream responses should include matching completed releases from the local library. Defaults to true.
func (StremioConfig) EffectiveMaxFallbackReleases ¶
func (s StremioConfig) EffectiveMaxFallbackReleases() int
EffectiveMaxFallbackReleases returns MaxFallbackReleases clamped to [0, 4].
func (StremioConfig) EffectiveSkipRepair ¶
func (s StremioConfig) EffectiveSkipRepair() bool
EffectiveSkipRepair reports whether Stremio imports skip PAR2 repair.
type StremioDisplayConfig ¶
type StremioDisplayConfig struct {
// Preset is "default", "full", "minimal" or "custom". Empty means default.
Preset string `yaml:"preset" mapstructure:"preset" json:"preset,omitempty"`
// NameTemplate and DescriptionTemplate are used when Preset is "custom".
NameTemplate string `yaml:"name_template" mapstructure:"name_template" json:"name_template,omitempty"`
DescriptionTemplate string `yaml:"description_template" mapstructure:"description_template" json:"description_template,omitempty"`
}
EffectiveFastFailHeaderOnly reports whether Stremio imports should fast-fail immediately on the release probe when missing articles are found. Defaults to true. StremioDisplayConfig controls how releases are labelled in Stremio's stream list: the stream's name (the left-hand label) and its description.
type StremioIndexersConfig ¶
type StremioIndexersConfig struct {
Provider string `yaml:"provider" mapstructure:"provider" json:"provider"` // "prowlarr", "newsnab", "both"
UserAgentMode string `yaml:"user_agent_mode" mapstructure:"user_agent_mode" json:"user_agent_mode,omitempty"`
CustomUserAgent string `yaml:"custom_user_agent" mapstructure:"custom_user_agent" json:"custom_user_agent,omitempty"`
Prowlarr ProwlarrConfig `yaml:"prowlarr" mapstructure:"prowlarr" json:"prowlarr"`
Newsnab []NewsnabIndexerConfig `yaml:"newsnab" mapstructure:"newsnab" json:"newsnab,omitempty"`
}
StremioIndexersConfig configures search providers for the Stremio addon.
type StuckCleanupRule ¶
type StuckCleanupRule struct {
Message string `yaml:"message" mapstructure:"message" json:"message"`
Enabled bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
Action string `yaml:"action" mapstructure:"action" json:"action"`
}
StuckCleanupRule matches a stuck-import status message and decides the action (one of StuckActionRemove, StuckActionBlocklist, StuckActionBlocklistSearch).
type TrashCustomFormatConfig ¶
type TrashCustomFormatConfig struct {
ID string `yaml:"id" mapstructure:"id" json:"id"`
Name string `yaml:"name" mapstructure:"name" json:"name"`
Category string `yaml:"category" mapstructure:"category" json:"category"`
Pattern string `yaml:"pattern" mapstructure:"pattern" json:"pattern"`
PatternType string `yaml:"pattern_type" mapstructure:"pattern_type" json:"pattern_type"`
Score int `yaml:"score" mapstructure:"score" json:"score"`
Enabled bool `yaml:"enabled" mapstructure:"enabled" json:"enabled"`
IsCustom bool `yaml:"is_custom" mapstructure:"is_custom" json:"is_custom"`
Invert bool `yaml:"invert,omitempty" mapstructure:"invert" json:"invert,omitempty"`
}
TrashCustomFormatConfig defines a format scoring rule in configuration.
type WebDAVConfig ¶
type WebDAVConfig struct {
Port int `yaml:"port" mapstructure:"port" json:"port"`
User string `yaml:"user" mapstructure:"user" json:"user"`
Password string `yaml:"password" mapstructure:"password" json:"password"`
Host string `yaml:"host" mapstructure:"host" json:"host,omitempty"`
}
WebDAVConfig represents WebDAV server configuration