library

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: 19 Imported by: 0

Documentation

Index

Constants

View Source
const MinMediaSize = 50 * 1024 * 1024

MinMediaSize is the minimum file size to consider a candidate media file (50 MiB).

Variables

View Source
var (
	ErrNoMedia       = errors.New("no media file found")
	ErrMultipleMedia = errors.New("multiple media files require manual handling")
	ErrSampleOnly    = errors.New("only sample files present")
	ErrDestExists    = errors.New("destination already exists")
	ErrUnsafePath    = errors.New("template output escapes library root")
)
View Source
var MediaExts = map[string]bool{
	".mkv": true, ".mp4": true, ".avi": true, ".wmv": true,
	".mov": true, ".m4v": true, ".ts": true, ".webm": true,
}

MediaExts is the set of file extensions treated as candidate media files. Extension comparison should be lowercase: callers must `strings.ToLower(filepath.Ext(path))` before lookup.

View Source
var SampleRe = regexp.MustCompile(`(?i)\bsample\b`)

SampleRe matches scene-release sample/preview clips so they can be filtered out. Word-boundary match skips `sample.mkv`, `Movie.Sample.mkv` without catching `samplesheet.mkv`.

Functions

func ApplyTemplate

func ApplyTemplate(tpl string, vars map[string]string) string

ApplyTemplate replaces {key} and {key:02} tokens in a template string with values from the provided map. Format spec {key:02} zero-pads numeric values to the given width. Unknown tokens render as empty — keeps optional segments like {imdb_id} clean when not populated.

func BuildEpisodeVars

func BuildEpisodeVars(
	showTitle string,
	year, season, episode uint16,
	episodeTitle string,
	parsed ParseResult,
) map[string]string

BuildEpisodeVars creates template variables for TV episode naming.

func BuildMovieVars

func BuildMovieVars(
	title string,
	year uint16,
	tmdbID uint32,
	imdbID string,
	parsed ParseResult,
) map[string]string

BuildMovieVars creates template variables from a movie's metadata and parsed release info. Empty fields are omitted so ApplyTemplate's unknown-token policy can drop unpopulated optional segments cleanly.

func FindMediaFile

func FindMediaFile(dir string) (string, error)

FindMediaFile scans dir for video files above 50MB, skipping any whose basename matches \bsample\b. Returns the absolute path to the sole candidate. Errors: ErrNoMedia (none found, none filtered), ErrSampleOnly (all candidates were samples), ErrMultipleMedia (>1 candidate after filtering). When dir is a single file, it is returned directly provided it passes the same filters.

func IsWholeSeriesPack

func IsWholeSeriesPack(name string) bool

IsWholeSeriesPack reports whether a release name denotes a complete-series or multi-season pack (e.g. "COMPLETE", "INTEGRALE", "S01-S05") that spans more than one season. A season-scoped search filters these out since grabbing one imports every season it contains.

func ListVideoFiles

func ListVideoFiles(dir string) ([]string, error)

ListVideoFiles returns every video file directly under dir that passes the size + sample filters (same rules as FindMediaFile). Used by the importer to enumerate a season pack's individual episode files.

func ListVideoFilesRecursive

func ListVideoFilesRecursive(dir string) ([]string, error)

ListVideoFilesRecursive returns every importable video file under dir and its subdirectories, applying the same ext / min-size / sample filters as ListVideoFiles. Unlike ListVideoFiles it descends into season folders, so it handles the Show/Season NN/episode layout. Unreadable descendants are skipped; only an unreadable root produces an error.

func MatchEpisode

func MatchEpisode(
	parsed ParseResult,
	seasons []*ent.Season,
	anime bool,
) *ent.Episode

MatchEpisode resolves a parsed release to an episode within the show's seasons. Anime packs match on absolute number; everything else on season+episode number. Returns nil when nothing matches.

func NormalizeTitle

func NormalizeTitle(s string) string

NormalizeTitle lowercases, strips non-alphanumerics, and strips a leading article ("the"/"a"/"an") for tolerant title comparison (e.g. "The Batman" vs "the.batman" vs "Batman").

func SanitizePath

func SanitizePath(s string) string

SanitizePath removes characters that are invalid in filenames.

func TitleMatches

func TitleMatches(a, b string) bool

TitleMatches reports whether two titles are equal after normalization.

Types

type ImportService

type ImportService struct {
	// contains filtered or unexported fields
}

func NewImportService

func NewImportService(cfg *config.LibraryConfig) *ImportService

func (*ImportService) ImportEpisode

func (s *ImportService) ImportEpisode(
	ctx context.Context,
	srcFile string,
	show *ent.TVShow,
	season uint16,
	ep *ent.Episode,
) (ImportedFile, error)

ImportEpisode places a single episode file into the series library. srcFile is a concrete file path (resolved by the caller — for a season pack the caller matches each file to its episode before calling this). The dest path is rendered from SeriesNaming + SeriesPath. Mirrors ImportMovieWithMode; does not touch the DB.

func (*ImportService) ImportMovie

func (s *ImportService) ImportMovie(
	ctx context.Context,
	srcDir string,
	m *ent.Movie,
	imdbID string,
) (ImportedFile, error)

ImportMovie finds the media file under srcDir (or uses srcDir if it is already a file), renders the destination path from the naming template, transfers the file with the configured mode, and returns ImportedFile. Does not touch the DB. Errors from FindMediaFile pass through as-is so the worker can classify them.

func (*ImportService) ImportMovieWithMode

func (s *ImportService) ImportMovieWithMode(
	ctx context.Context,
	srcDir string,
	m *ent.Movie,
	imdbID string,
	modeOverride string,
) (ImportedFile, error)

ImportMovieWithMode is ImportMovie with an explicit transfer-mode override. Empty mode falls back to s.config.ImportMode. Valid values: hardlink, copy, move.

type ImportedFile

type ImportedFile struct {
	Path   string
	Size   int64
	Parsed ParseResult
}

ImportedFile describes a placed media file. Returned by ImportMovie so the caller (importer.Worker) can persist the MediaFile row in the same atomic DB transaction as the DownloadRecord + Movie status transitions.

type Importer

type Importer interface {
	ImportMovieWithMode(
		ctx context.Context,
		srcDir string,
		m *ent.Movie,
		imdbID string,
		modeOverride string,
	) (ImportedFile, error)
}

Importer is the consumer-facing surface needed by callers that import a movie file into the managed library (e.g. internal/library/hygiene's orphan auto-import path). *ImportService implements it.

type ParseResult

type ParseResult struct {
	Title          string
	Year           uint16
	Season         uint16
	Episode        uint16
	SeasonPack     bool
	AbsoluteNumber uint16
	AirDate        *time.Time
	Resolution     string
	Source         string
	Codec          string
	Group          string
	Extension      string
}

func Parse

func Parse(filename string) ParseResult

type RenameOperation

type RenameOperation struct {
	MediaFileID uint32
	From        string
	To          string
}

RenameOperation is one rename in a plan: move `From` to `To` on disk.

type RenamePlan

type RenamePlan struct {
	Operations []RenameOperation
}

RenamePlan is the set of file moves needed to bring a title's media files in line with the library naming pattern. Empty Operations means every file already matches its target.

type Renamer

type Renamer interface {
	Preview(ctx context.Context, id uint32) (RenamePlan, error)
	Apply(ctx context.Context, id uint32) (RenamePlan, error)
}

Renamer computes and applies media-file rename plans for one title (movie or series), keyed by its numeric ID. Backs the manual "rename files" UI action.

Directories

Path Synopsis
Package hygiene runs two periodic library jobs:
Package hygiene runs two periodic library jobs:

Jump to

Keyboard shortcuts

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