filenamebuilder

package module
v0.0.0-...-206b7cc Latest Latest
Warning

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

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

README ΒΆ

filenamebuilder

The filenamebuilder package provides utilities for constructing, cleaning, and tokenizing media filenames in the Ovrlord media management system. It is designed to generate consistent, human-readable, and metadata-rich filenames for movies and TV series, supporting a wide range of naming conventions and quality indicators.

This implementation mirrors the FileNameBuilder logic from Radarr and Sonarr's C# codebases.

Features

  • Filename Construction: Build standardized filenames for movies and series based on metadata (title, year, season, episode, quality, etc.).
  • Cleaning Utilities: Remove unwanted characters, normalize whitespace, and sanitize filenames for filesystem compatibility.
  • Tokenization: Break down filenames into tokens for easier parsing and manipulation.
  • Quality and Language Tags: Support for embedding quality, language, and release group information in filenames.
  • Extensible Patterns: Easily adapt to new naming conventions or custom requirements.

πŸ“š Guides & Documentation

Usage

Import the package:

import "github.com/ovrlord-app/filenamebuilder"
Example: Building a Movie Filename
movie := filenamebuilder.Movie{
    Title:         "Titanic",
    OriginalTitle: "Titanic (1997) [1080p][EN][RARBG]",
    Year:          1997,
    TmdbId:        597,
}
movieFile := filenamebuilder.MovieFile{
    ReleaseGroup: "releasegroup",
    Path:         "downloads/titanic.releasegroup.mkv",
    RelativePath: "titanic.relasegroup.mkv",
}
movieConfig := filenamebuilder.DefaultMovieNamingConfig()
fileNameBuilder := filenamebuilder.NewMovieFileNameBuilder(movieConfig)
// e.g., "Titanic (1997) [1080p][EN][RARBG]"
Example: Cleaning a Filename
clean := filenamebuilder.CleanFilename("Inception.2010.1080p.BluRay.x264-RARBG.mkv")
// e.g., "Inception 2010 1080p BluRay x264 RARBG.mkv"

License

This project follows the same license as Sonarr/Radarr (GPL-3.0). See LICENSE for details.

  • Sonarr - The original C# TV series implementation
  • Radarr - The original C# movie implementation

Credits

Based on the FileNameBuilder logic from Sonarr and Radarr projects.

Documentation ΒΆ

Overview ΒΆ

Package filenamebuilder provides file naming template functionality mirroring Radarr and Sonarr's FileNameBuilder implementations.

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

View Source
var BadCharacters = []string{"\\", "/", "<", ">", "?", "*", "|", "\""}

BadCharacters are characters that are not allowed in file names

View Source
var GoodCharacters = []string{"+", "+", "", "", "!", "-", "", ""}

GoodCharacters are replacement characters for bad characters

View Source
var Iso639BTMap = map[string]string{
	"alb": "sqi",
	"arm": "hye",
	"baq": "eus",
	"bur": "mya",
	"chi": "zho",
	"cze": "ces",
	"dut": "nld",
	"fre": "fra",
	"geo": "kat",
	"ger": "deu",
	"gre": "ell",
	"gsw": "deu",
	"ice": "isl",
	"mac": "mkd",
	"mao": "mri",
	"may": "msa",
	"per": "fas",
	"rum": "ron",
	"slo": "slk",
	"tib": "bod",
	"wel": "cym",
	"khk": "mon",
	"mvf": "mon",
}

Iso639BTMap maps ISO 639-2/B codes to ISO 639-2/T codes

View Source
var Iso639ToTwoLetter = map[string]string{
	"sqi": "SQ", "hye": "HY", "eus": "EU", "mya": "MY",
	"zho": "ZH", "ces": "CS", "nld": "NL", "fra": "FR",
	"kat": "KA", "deu": "DE", "ell": "EL", "isl": "IS",
	"mkd": "MK", "mri": "MI", "msa": "MS", "fas": "FA",
	"ron": "RO", "slk": "SK", "bod": "BO", "cym": "CY",
	"mon": "MN",

	"eng": "EN", "spa": "ES", "ita": "IT", "por": "PT",
	"jpn": "JA", "kor": "KO", "ara": "AR", "hin": "HI",
	"rus": "RU", "pol": "PL", "tur": "TR", "vie": "VI",
	"tha": "TH", "swe": "SV", "nor": "NO", "dan": "DA",
	"fin": "FI", "hun": "HU", "bul": "BG", "hrv": "HR",
	"srp": "SR", "slv": "SL", "lit": "LT", "lav": "LV",
	"est": "ET", "heb": "HE", "ukr": "UK", "cat": "CA",
	"glg": "GL", "ind": "ID", "tam": "TA", "tel": "TE",
	"mal": "ML", "kan": "KN", "ben": "BN", "guj": "GU",
	"mar": "MR", "pan": "PA", "nob": "NB", "nno": "NN",
}

Iso639ToTwoLetter maps 3-letter ISO 639 codes to 2-letter ISO 639-1 codes

View Source
var RadarrTitleRegex = MustCompile2(`(?<tag>\{(?<tagprefix>[-{ ._\[(]*)(?:imdb(?:id)?-|edition-))?\{(?<prefix>[-{ ._\[(]*)(?<token>(?:[a-z0-9]+)(?:(?<separator>[- ._]+)(?:[a-z0-9]+))?)(?::(?<customFormat>[ ,a-z0-9|+-]+(?<![- ])))?(?<suffix>[-} ._)\]]*)\}`)

RadarrTitleRegex matches tokens with tag support ({imdb-{...}}, {edition-{...}}) Supports { in prefix and } in suffix for wrapping resolved values in literal braces

View Source
var SonarrTitleRegex = MustCompile2(`(?<escaped>\{\{|\}\})|\{(?<prefix>[- ._\[(]*)(?<token>(?:[a-z0-9]+)(?:(?<separator>[- ._]+)(?:[a-z0-9]+))?)(?::(?<customFormat>[ ,a-z0-9|+-]+(?<![- ])))?(?<suffix>[- ._)\]]*)\}`)

SonarrTitleRegex matches tokens with escaped braces support ({{ β†’ {, }} β†’ })

View Source
var TitleRegex = RadarrTitleRegex

TitleRegex is an alias to RadarrTitleRegex for backward compatibility

Functions ΒΆ

func CleanFileName ΒΆ

func CleanFileName(name string, config NamingConfig) string

CleanFileName cleans a file name by removing/replacing illegal characters

func CleanFolderName ΒΆ

func CleanFolderName(name string) string

CleanFolderName cleans a folder name

func CleanTitle ΒΆ

func CleanTitle(title string) string

CleanTitle cleans a title for scene-style naming (matches C# FileNameBuilder.CleanTitle)

func CleanTitleThe ΒΆ

func CleanTitleThe(title string) string

CleanTitleThe cleans a title and moves articles to the end Matches C#: title.CleanTitle() + ", " + prefix + " " + suffix.CleanTitle()

func CleanTitleTheYear ΒΆ

func CleanTitleTheYear(title string, year int) string

CleanTitleTheYear returns a clean title-the with year appended (no parens), matching C# FileNameBuilder.CleanTitleTheYear.

func CleanTitleYear ΒΆ

func CleanTitleYear(title string, year int) string

CleanTitleYear returns a clean title with year appended (no parens)

func FormatCustomFormats ΒΆ

func FormatCustomFormats(customFormats []CustomFormat, filter string) string

FormatCustomFormats formats custom format names with optional filtering

func GetEditionToken ΒΆ

func GetEditionToken(edition string) string

GetEditionToken formats an edition string with proper casing Matches C# FileNameBuilder.GetEditionToken: TitleCase, lowercase ordinals, uppercase keywords

func GetLanguagesToken ΒΆ

func GetLanguagesToken(languages []string, filter string, skipEnglishOnly bool, quoted bool) string

GetLanguagesToken formats a list of language codes for display Matches C# FileNameBuilder.GetLanguagesToken

func GroupByName ΒΆ

func GroupByName(m *regexp2.Match, name string) string

GroupByName returns the value of a named group from a match

func GroupByNumber ΒΆ

func GroupByNumber(m *regexp2.Match, num int) string

GroupByNumber returns the value of a numbered group from a match

func RemoveDiacritics ΒΆ

func RemoveDiacritics(s string) string

RemoveDiacritics removes accent marks from characters, including expanding Latin ligatures (Γ¦β†’ae, Ε“β†’oe, etc.) that have no Unicode decomposition. Matches the behavior of the Diacritical.Net library used by C#.

func ReplaceReservedDeviceNames ΒΆ

func ReplaceReservedDeviceNames(input string) string

ReplaceReservedDeviceNames replaces Windows reserved device names

func ReplaceTokens ΒΆ

func ReplaceTokens(pattern string, handlers TokenHandlers, config NamingConfig) string

ReplaceTokens replaces all tokens in a pattern (Radarr mode with tag support)

func ReplaceTokensSonarr ΒΆ

func ReplaceTokensSonarr(pattern string, handlers TokenHandlers, config NamingConfig) string

ReplaceTokensSonarr replaces all tokens in a pattern (Sonarr mode with escaped braces)

func TitleFirstCharacter ΒΆ

func TitleFirstCharacter(title string) string

TitleFirstCharacter returns the first alphanumeric character of a title, checking only the first two runes. Matches C# behavior which checks index 0 then index 1 and returns "_" if neither is a letter or digit. Letters are uppercased and diacritics/ligatures are expanded to match the Diacritical.Net library: e.g. Γ† β†’ AE (first char A), Ü β†’ U.

func TitleThe ΒΆ

func TitleThe(title string) string

TitleThe moves "The", "An", "A" articles to the end

func TitleWithoutYear ΒΆ

func TitleWithoutYear(title string) string

TitleWithoutYear removes the year from a title. NOTE: Does NOT trim trailing space, matching C# behavior where the trailing space affects downstream CleanTitle apostrophe removal (e.g., "'s " matches the scenify regex when followed by a space but not at end-of-string).

func TitleYear ΒΆ

func TitleYear(title string, year int) string

TitleYear appends the year to a title if not already present

func Truncate ΒΆ

func Truncate(input string, maxLength int) string

Truncate truncates a string to a maximum length with ellipsis

Types ΒΆ

type ColonReplacementFormat ΒΆ

type ColonReplacementFormat int

ColonReplacementFormat defines how colons should be replaced in file names

const (
	ColonReplacementDelete ColonReplacementFormat = iota
	ColonReplacementDash
	ColonReplacementSpaceDash
	ColonReplacementSpaceDashSpace
	ColonReplacementSmart
	ColonReplacementCustom
)

type CustomFormat ΒΆ

type CustomFormat struct {
	Name                            string
	IncludeCustomFormatWhenRenaming bool
}

CustomFormat represents a custom format

type Episode ΒΆ

type Episode struct {
	Title                 string
	SeasonNumber          int
	EpisodeNumber         int
	AbsoluteEpisodeNumber *int
	AirDate               *time.Time
}

Episode represents a TV episode (Sonarr)

type EpisodeFile ΒΆ

type EpisodeFile struct {
	Id           int // database id; 0 means the file has not yet been persisted
	RelativePath string
	Path         string
	SceneName    string
	ReleaseGroup string
	ReleaseHash  string
	Quality      QualityModel
	MediaInfo    *MediaInfo
}

EpisodeFile represents an episode file (Sonarr)

type MediaInfo ΒΆ

type MediaInfo struct {
	VideoCodec            string
	VideoBitDepth         int
	VideoMultiViewCount   int
	VideoDynamicRange     string
	VideoDynamicRangeType string
	AudioCodec            string
	AudioChannels         float64
	AudioLanguages        []string
	Subtitles             []string
	SchemaRevision        int
}

MediaInfo represents media information for a file

type Movie ΒΆ

type Movie struct {
	Title            string
	OriginalTitle    string
	CleanTitle       string
	Year             int
	ImdbId           string
	TmdbId           int
	Certification    string
	CollectionTitle  string
	CollectionTmdbId int
	Path             string
	Translations     []MovieTranslation
}

Movie represents a movie entity (Radarr)

type MovieFile ΒΆ

type MovieFile struct {
	RelativePath string
	Path         string
	SceneName    string
	ReleaseGroup string
	Quality      QualityModel
	MediaInfo    *MediaInfo
	Edition      string
}

MovieFile represents a movie file (Radarr)

type MovieFileNameBuilder ΒΆ

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

MovieFileNameBuilder builds file names for movies (Radarr-style)

func NewMovieFileNameBuilder ΒΆ

func NewMovieFileNameBuilder(config NamingConfig) *MovieFileNameBuilder

NewMovieFileNameBuilder creates a new movie file name builder

func (*MovieFileNameBuilder) BuildFileName ΒΆ

func (b *MovieFileNameBuilder) BuildFileName(movie Movie, movieFile MovieFile, customFormats []CustomFormat) string

BuildFileName builds a file name for a movie

func (*MovieFileNameBuilder) BuildFilePath ΒΆ

func (b *MovieFileNameBuilder) BuildFilePath(movie Movie, fileName, extension string) string

BuildFilePath builds a full file path for a movie

func (*MovieFileNameBuilder) GetMovieFolder ΒΆ

func (b *MovieFileNameBuilder) GetMovieFolder(movie Movie) string

GetMovieFolder gets the folder name for a movie

type MovieTranslation ΒΆ

type MovieTranslation struct {
	Language string // ISO 639-1 code (e.g., "de", "fr")
	Title    string
}

MovieTranslation represents a translated movie title

type MultiEpisodeStyle ΒΆ

type MultiEpisodeStyle int

MultiEpisodeStyle defines how multiple episodes in a single file are formatted

const (
	MultiEpisodeStyleExtend MultiEpisodeStyle = iota
	MultiEpisodeStyleDuplicate
	MultiEpisodeStyleRepeat
	MultiEpisodeStyleScene
	MultiEpisodeStyleRange
	MultiEpisodeStylePrefixedRange
)

type NamingConfig ΒΆ

type NamingConfig struct {
	// Common settings
	ReplaceIllegalCharacters bool
	ColonReplacementFormat   ColonReplacementFormat
	CustomColonReplacement   string

	// Movie settings (Radarr)
	RenameMovies        bool
	StandardMovieFormat string
	MovieFolderFormat   string

	// Series settings (Sonarr)
	RenameEpisodes        bool
	MultiEpisodeStyle     MultiEpisodeStyle
	StandardEpisodeFormat string
	DailyEpisodeFormat    string
	AnimeEpisodeFormat    string
	SeriesFolderFormat    string
	SeasonFolderFormat    string
	SpecialsFolderFormat  string
}

NamingConfig holds the naming configuration for file name building

func DefaultMovieNamingConfig ΒΆ

func DefaultMovieNamingConfig() NamingConfig

DefaultMovieNamingConfig returns the default naming configuration for movies

func DefaultSeriesNamingConfig ΒΆ

func DefaultSeriesNamingConfig() NamingConfig

DefaultSeriesNamingConfig returns the default naming configuration for series

type QualityModel ΒΆ

type QualityModel struct {
	Quality  string
	Revision QualityRevision
}

QualityModel represents quality information for a media file

type QualityRevision ΒΆ

type QualityRevision struct {
	Version int
	Real    int
}

QualityRevision represents quality revision information

type Regexp2 ΒΆ

type Regexp2 struct {
	*regexp2.Regexp
}

Regexp2 wraps regexp2.Regexp for convenient usage

func MustCompile2 ΒΆ

func MustCompile2(pattern string) *Regexp2

MustCompile2 compiles a regexp2 pattern with case-insensitive flag and panics on error

func MustCompile2WithOptions ΒΆ

func MustCompile2WithOptions(pattern string, opts regexp2.RegexOptions) *Regexp2

MustCompile2WithOptions compiles a regexp2 pattern with custom options and panics on error

func (*Regexp2) FindAllString ΒΆ

func (r *Regexp2) FindAllString(s string, n int) []string

FindAllString returns all matches as strings

func (*Regexp2) FindAllStringIndex ΒΆ

func (r *Regexp2) FindAllStringIndex(s string, n int) [][]int

FindAllStringIndex returns start/end indices of all matches

func (*Regexp2) FindAllStringSubmatchIndex ΒΆ

func (r *Regexp2) FindAllStringSubmatchIndex(s string, n int) [][]int

FindAllStringSubmatchIndex returns submatch indices for all matches

func (*Regexp2) FindString ΒΆ

func (r *Regexp2) FindString(s string) string

FindString returns the text of the leftmost match of the regular expression

func (*Regexp2) FindStringMatch ΒΆ

func (r *Regexp2) FindStringMatch(s string) (*regexp2.Match, error)

FindStringMatch returns the leftmost match with all groups

func (*Regexp2) GroupNames ΒΆ

func (r *Regexp2) GroupNames() []string

GroupNames returns the names of all named groups

func (*Regexp2) MatchString ΒΆ

func (r *Regexp2) MatchString(s string) bool

MatchString reports whether the string s contains any match of the regular expression

func (*Regexp2) ReplaceAllString ΒΆ

func (r *Regexp2) ReplaceAllString(s, repl string) string

ReplaceAllString replaces all matches with replacement string

func (*Regexp2) ReplaceAllStringFunc ΒΆ

func (r *Regexp2) ReplaceAllStringFunc(s string, replFunc func(string) string) string

ReplaceAllStringFunc replaces all matches using the provided function

func (*Regexp2) ReplaceAllStringFuncWithTimeout ΒΆ

func (r *Regexp2) ReplaceAllStringFuncWithTimeout(s string, replFunc func(string) string, timeout time.Duration) (string, error)

ReplaceAllStringFuncWithTimeout replaces with timeout support

type Series ΒΆ

type Series struct {
	Title        string
	CleanTitle   string
	Year         int
	TvdbId       int
	TvMazeId     int
	TmdbId       int
	ImdbId       string
	Path         string
	SeasonFolder bool
	SeriesType   SeriesType
}

Series represents a TV series (Sonarr)

type SeriesFileNameBuilder ΒΆ

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

SeriesFileNameBuilder builds file names for TV series episodes (Sonarr-style)

func NewSeriesFileNameBuilder ΒΆ

func NewSeriesFileNameBuilder(config NamingConfig) *SeriesFileNameBuilder

NewSeriesFileNameBuilder creates a new series file name builder

func (*SeriesFileNameBuilder) BuildFileName ΒΆ

func (b *SeriesFileNameBuilder) BuildFileName(episodes []Episode, series Series, episodeFile EpisodeFile, extension string, customFormats []CustomFormat) string

BuildFileName builds a file name for an episode or multiple episodes

func (*SeriesFileNameBuilder) BuildFilePath ΒΆ

func (b *SeriesFileNameBuilder) BuildFilePath(episodes []Episode, series Series, episodeFile EpisodeFile, extension string, customFormats []CustomFormat) string

BuildFilePath builds a full file path for an episode

func (*SeriesFileNameBuilder) BuildSeasonPath ΒΆ

func (b *SeriesFileNameBuilder) BuildSeasonPath(series Series, seasonNumber int) string

BuildSeasonPath builds the season folder path

func (*SeriesFileNameBuilder) GetSeasonFolder ΒΆ

func (b *SeriesFileNameBuilder) GetSeasonFolder(series Series, seasonNumber int) string

GetSeasonFolder gets the folder name for a season

func (*SeriesFileNameBuilder) GetSeriesFolder ΒΆ

func (b *SeriesFileNameBuilder) GetSeriesFolder(series Series) string

GetSeriesFolder gets the folder name for a series

func (*SeriesFileNameBuilder) RequiresAbsoluteEpisodeNumber ΒΆ

func (b *SeriesFileNameBuilder) RequiresAbsoluteEpisodeNumber() bool

RequiresAbsoluteEpisodeNumber reports whether the anime naming pattern includes an absolute token.

func (*SeriesFileNameBuilder) RequiresEpisodeTitle ΒΆ

func (b *SeriesFileNameBuilder) RequiresEpisodeTitle(series Series, episodes []Episode) bool

RequiresEpisodeTitle reports whether the effective naming pattern includes an episode title token.

type SeriesType ΒΆ

type SeriesType int

SeriesType defines the type of series

const (
	SeriesTypeStandard SeriesType = iota
	SeriesTypeDaily
	SeriesTypeAnime
)

type TokenHandler ΒΆ

type TokenHandler func(match TokenMatch) string

TokenHandler is a function that resolves a token to its value

type TokenHandlers ΒΆ

type TokenHandlers map[string]TokenHandler

TokenHandlers maps token names to their handlers

type TokenMatch ΒΆ

type TokenMatch struct {
	FullMatch    string
	Tag          string
	Prefix       string
	Token        string
	Separator    string
	CustomFormat string
	Suffix       string
}

TokenMatch represents a parsed token from a naming pattern

func ParseTokens ΒΆ

func ParseTokens(pattern string) []TokenMatch

ParseTokens parses all tokens from a pattern string (Radarr mode)

func ParseTokensSonarr ΒΆ

func ParseTokensSonarr(pattern string) []TokenMatch

ParseTokensSonarr parses tokens using the Sonarr escaped-braces regex

func (TokenMatch) DefaultValue ΒΆ

func (m TokenMatch) DefaultValue(defaultVal string) string

DefaultValue returns the default value if the token has no prefix/suffix

Jump to

Keyboard shortcuts

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