rss

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 12, 2026 License: GPL-3.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
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

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

type FeedRunner interface {
	Run(ctx context.Context) error
}

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.

func (*FeedScanner) Run

func (s *FeedScanner) Run(ctx context.Context) error

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

type MissingSearchRunner interface {
	Run(ctx context.Context) error
}

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

func (s *MissingSearcher) SearchOne(ctx context.Context, m *ent.Movie) error

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.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL