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 FindMediaFile(dir string) (string, error)
- 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 NormalizeTitle(s string) string
- 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) 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 FindMediaFile ¶
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 ¶
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 NormalizeTitle ¶
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 ¶
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. 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 ¶
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: |