Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNoEligibleRelease = errors.New("rss: no eligible release for movie")
ErrNoEligibleRelease is returned by SearchOne when no indexer result passes the quality filter. last_search_at is still bumped so the cooldown counter advances.
Functions ¶
This section is empty.
Types ¶
type Downloader ¶
type Downloader interface {
Grab(
ctx context.Context,
result indexer.SearchResult,
movieID uint32,
) (*ent.DownloadRecord, error)
}
Downloader is the subset of download.Manager that rss.MissingSearcher needs.
type EpisodeGrabber ¶
type EpisodeGrabber interface {
GrabEpisode(
ctx context.Context,
result indexer.SearchResult,
episodeID uint32,
) (*ent.DownloadRecord, error)
}
EpisodeGrabber is the subset of download.Downloader that rss.EpisodeMissingSearcher needs.
type EpisodeMissingSearcher ¶
type EpisodeMissingSearcher struct {
// contains filtered or unexported fields
}
EpisodeMissingSearcher scans wanted episodes, searches indexers, and grabs the best matching release per season. When a whole season is wanted it prefers a single season pack over per-episode grabs.
func NewEpisodeMissingSearcher ¶
func NewEpisodeMissingSearcher( store WantedEpisodeLister, indexers TVIndexerSearcher, downloads EpisodeGrabber, ) (*EpisodeMissingSearcher, error)
NewEpisodeMissingSearcher builds the searcher from the default quality profile plus the global library knobs. Returns an error when the cooldown duration fails to parse.
func (*EpisodeMissingSearcher) Run ¶
func (s *EpisodeMissingSearcher) Run(ctx context.Context) error
Run performs one pass over every show with wanted episodes. Per-season errors are logged and never abort the pass; only a failure to list wanted shows is returned. Satisfies the MissingSearchRunner contract used by jobs.
func (*EpisodeMissingSearcher) SearchShow ¶
func (s *EpisodeMissingSearcher) SearchShow( ctx context.Context, showID uint32, ) error
SearchShow runs one search-and-grab pass scoped to a single series. It reuses the wanted-episode query and processes only the matching show, so a show with no wanted episodes is a no-op. Powers POST /series/{id}/search.
type FeedRunner ¶
FeedRunner is the consumer-facing surface for triggering one feed scan. jobs.RSSFeed accepts it.
type FeedScanner ¶
type FeedScanner struct {
// contains filtered or unexported fields
}
FeedScanner pulls each indexer's RSS forward-feed once per tick, matches items against wanted movies by title+year, and grabs anything that passes the quality filter. Opportunistic — bypasses the missing-search cooldown.
func NewFeedScanner ¶
func NewFeedScanner( store db.Store, indexers IndexerFeeder, grabber Downloader, ) (*FeedScanner, error)
NewFeedScanner builds a FeedScanner using library.default_quality from the config singleton. Returns an error if the cooldown duration fails to parse.
type IndexerFeeder ¶
type IndexerFeeder interface {
Feed(ctx context.Context, indexerName string) ([]indexer.SearchResult, error)
}
IndexerFeeder is the subset of indexer.Manager that rss.FeedScanner needs. The enabled-indexer set is read from config; this only fetches a feed by name.
type IndexerSearcher ¶
type IndexerSearcher interface {
SearchMovie(
ctx context.Context,
titles []string,
tmdbID uint32,
) ([]indexer.SearchResult, error)
}
IndexerSearcher is the subset of indexer.Service that rss.MissingSearcher needs.
type MissingSearchRunner ¶
MissingSearchRunner is the consumer-facing surface for triggering one missing-search pass. jobs.RSSSync accepts it so it can be driven by a fake in tests without standing up the full MissingSearcher.
type MissingSearcher ¶
type MissingSearcher struct {
// contains filtered or unexported fields
}
MissingSearcher periodically scans wanted movies, searches indexers, and grabs the best matching release via the download manager.
func NewMissingSearcher ¶
func NewMissingSearcher( store db.Store, indexers IndexerSearcher, downloads Downloader, ) (*MissingSearcher, error)
NewMissingSearcher builds a MissingSearcher using library.default_quality from the config singleton. Returns an error if the NoMatchCooldown duration fails to parse.
func (*MissingSearcher) Run ¶
func (s *MissingSearcher) Run(ctx context.Context) error
Run performs one sync pass over all eligible wanted movies. Returns a non-nil error only for ctx cancellation; per-movie errors are logged and counted but do not abort the run.
func (*MissingSearcher) SearchOne ¶
SearchOne runs one indexer query for movie m, applies the quality filter, and dispatches a grab on the first acceptable result.
Returns nil on a successful grab, ErrNoEligibleRelease when nothing matches the quality bar, or a wrapped error on indexer / downloader failure. last_search_at is bumped whenever the indexer responds (success or no match) so cooldown counters advance.
type QualityConfig ¶
type QualityConfig struct {
PreferredResolution string
MinResolution string
UpgradeAllowed bool
NoMatchCooldown time.Duration
MaxGrabFailures uint8
}
QualityConfig drives result filtering in MissingSearcher. Built from config.QualityConfig (string fields) or from a per-movie DB QualityProfile.
func (QualityConfig) Accepts ¶
func (q QualityConfig) Accepts(releaseTitle string) bool
Accepts reports whether a release title meets the quality bar. Unparseable titles are rejected (conservative).
type TVIndexerSearcher ¶
type TVIndexerSearcher interface {
SearchSeason(
ctx context.Context,
titles []string,
tvdbID uint32,
season uint16,
) ([]indexer.SearchResult, error)
SearchEpisode(
ctx context.Context,
titles []string,
tvdbID uint32,
season, episode uint16,
) ([]indexer.SearchResult, error)
}
TVIndexerSearcher is the subset of indexer.Manager that rss.EpisodeMissingSearcher needs.
type WantedEpisodeLister ¶
type WantedEpisodeLister interface {
ListWantedEpisodes(ctx context.Context) ([]*ent.TVShow, error)
SetEpisodeStatus(ctx context.Context, id uint32, status episode.Status) error
SetEpisodeLastSearchAt(ctx context.Context, id uint32, when time.Time) error
IncrementEpisodeGrabFailures(ctx context.Context, id uint32) error
ResetEpisodeGrabFailures(ctx context.Context, id uint32) error
}
WantedEpisodeLister is the subset of db.Store that rss.EpisodeMissingSearcher needs.