Documentation
¶
Index ¶
- Constants
- Variables
- func ApplyTemplate(tpl string, vars map[string]string) string
- func BuildEpisodeVars(showTitle string, year, season, episode uint16, episodeTitle string, ...) map[string]string
- func BuildMovieVars(title string, year uint16, tmdbID uint32, imdbID string, parsed ParseResult) map[string]string
- func IsWholeSeriesPack(name string) bool
- func ListVideoFiles(dir string) ([]string, error)
- func ListVideoFilesRecursive(dir string) ([]string, error)
- func MatchEpisode(parsed ParseResult, seasons []*ent.Season, anime bool) *ent.Episode
- func MatchEpisodeInSeason(parsed ParseResult, seasons []*ent.Season, anime bool) (uint16, *ent.Episode)
- func SanitizePath(s string) string
- func TitleMatches(a, b string) bool
- type ImportService
- func (s *ImportService) ImportEpisode(ctx context.Context, srcFile string, show *ent.TVShow, season uint16, ...) (ImportedFile, error)
- func (s *ImportService) ImportEpisodeWithMode(ctx context.Context, srcFile string, show *ent.TVShow, season uint16, ...) (ImportedFile, error)
- func (s *ImportService) ImportMovie(ctx context.Context, srcDir string, m *ent.Movie, imdbID string) (ImportedFile, error)
- func (s *ImportService) ImportMovieWithMode(ctx context.Context, srcDir string, m *ent.Movie, imdbID string, ...) (ImportedFile, error)
- type ImportedFile
- type Importer
- type ParseResult
- type RenameOperation
- type RenamePlan
- type Renamer
Constants ¶
const MinMediaSize = 50 * 1024 * 1024
MinMediaSize is the minimum file size to consider a candidate media file (50 MiB).
Variables ¶
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") )
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.
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 ¶
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 IsWholeSeriesPack ¶
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 ¶
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 ¶
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 ¶
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 MatchEpisodeInSeason ¶ added in v1.2.0
func MatchEpisodeInSeason( parsed ParseResult, seasons []*ent.Season, anime bool, ) (uint16, *ent.Episode)
MatchEpisodeInSeason is MatchEpisode plus the number of the season the match lives in — episodes don't carry it, and callers rendering a destination path need it. Returns (0, nil) when nothing matches.
func SanitizePath ¶
SanitizePath removes characters that are invalid in filenames.
func TitleMatches ¶
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. Does not touch the DB.
func (*ImportService) ImportEpisodeWithMode ¶ added in v1.2.0
func (s *ImportService) ImportEpisodeWithMode( ctx context.Context, srcFile string, show *ent.TVShow, season uint16, ep *ent.Episode, modeOverride string, ) (ImportedFile, error)
ImportEpisodeWithMode is ImportEpisode with an explicit transfer-mode override. Empty mode falls back to s.config.ImportMode. Valid values: hardlink, copy, move.
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 ¶
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.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package hygiene runs two periodic library jobs:
|
Package hygiene runs two periodic library jobs: |