| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 | using System;using System.Linq;using System.Text.RegularExpressions;using Emby.Naming.Video;namespace Emby.Naming.Common{    public class NamingOptions    {        public string[] AudioFileExtensions { get; set; }        public string[] AlbumStackingPrefixes { get; set; }        public string[] SubtitleFileExtensions { get; set; }        public char[] SubtitleFlagDelimiters { get; set; }        public string[] SubtitleForcedFlags { get; set; }        public string[] SubtitleDefaultFlags { get; set; }        public EpisodeExpression[] EpisodeExpressions { get; set; }        public string[] EpisodeWithoutSeasonExpressions { get; set; }        public string[] EpisodeMultiPartExpressions { get; set; }        public string[] VideoFileExtensions { get; set; }        public string[] StubFileExtensions { get; set; }        public string[] AudioBookPartsExpressions { get; set; }        public StubTypeRule[] StubTypes { get; set; }        public char[] VideoFlagDelimiters { get; set; }        public Format3DRule[] Format3DRules { get; set; }        public string[] VideoFileStackingExpressions { get; set; }        public string[] CleanDateTimes { get; set; }        public string[] CleanStrings { get; set; }        public EpisodeExpression[] MultipleEpisodeExpressions { get; set; }        public ExtraRule[] VideoExtraRules { get; set; }        public NamingOptions()        {            VideoFileExtensions = new string[]            {                ".m4v",                ".3gp",                ".nsv",                ".ts",                ".ty",                ".strm",                ".rm",                ".rmvb",                ".ifo",                ".mov",                ".qt",                ".divx",                ".xvid",                ".bivx",                ".vob",                ".nrg",                ".img",                ".iso",                ".pva",                ".wmv",                ".asf",                ".asx",                ".ogm",                ".m2v",                ".avi",                ".bin",                ".dvr-ms",                ".mpg",                ".mpeg",                ".mp4",                ".mkv",                ".avc",                ".vp3",                ".svq3",                ".nuv",                ".viv",                ".dv",                ".fli",                ".flv",                ".001",                ".tp"            };            VideoFlagDelimiters = new[]            {                '(',                ')',                '-',                '.',                '_',                '[',                ']'            };            StubFileExtensions = new[]            {                ".disc"            };            StubTypes = new[]            {                new StubTypeRule                {                     StubType = "dvd",                     Token = "dvd"                },                new StubTypeRule                {                     StubType = "hddvd",                     Token = "hddvd"                },                new StubTypeRule                {                     StubType = "bluray",                     Token = "bluray"                },                new StubTypeRule                {                     StubType = "bluray",                     Token = "brrip"                },                new StubTypeRule                {                     StubType = "bluray",                     Token = "bd25"                },                new StubTypeRule                {                     StubType = "bluray",                     Token = "bd50"                },                new StubTypeRule                {                     StubType = "vhs",                     Token = "vhs"                },                new StubTypeRule                {                     StubType = "tv",                     Token = "HDTV"                },                new StubTypeRule                {                     StubType = "tv",                     Token = "PDTV"                },                new StubTypeRule                {                     StubType = "tv",                     Token = "DSR"                }            };            VideoFileStackingExpressions = new[]            {                "(.*?)([ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck])[ _.-]*[0-9]+)(.*?)(\\.[^.]+)$",                "(.*?)([ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck])[ _.-]*[a-d])(.*?)(\\.[^.]+)$",                "(.*?)([ ._-]*[a-d])(.*?)(\\.[^.]+)$"            };            CleanDateTimes = new[]            {                @"(.+[^ _\,\.\(\)\[\]\-])[ _\.\(\)\[\]\-]+(19[0-9][0-9]|20[0-1][0-9])([ _\,\.\(\)\[\]\-][^0-9]|$)"            };            CleanStrings = new[]            {                @"[ _\,\.\(\)\[\]\-](ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|\[.*\])([ _\,\.\(\)\[\]\-]|$)",                @"[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|\[.*\])([ _\,\.\(\)\[\]\-]|$)",                @"(\[.*\])"            };            SubtitleFileExtensions = new[]            {                ".srt",                ".ssa",                ".ass",                ".sub"            };            SubtitleFlagDelimiters = new[]            {                '.'            };            SubtitleForcedFlags = new[]            {                "foreign",                "forced"            };            SubtitleDefaultFlags = new[]            {                "default"            };            AlbumStackingPrefixes = new[]            {                "disc",                "cd",                "disk",                "vol",                "volume"            };            AudioFileExtensions = new[]            {                ".nsv",                ".m4a",                ".flac",                ".aac",                ".strm",                ".pls",                ".rm",                ".mpa",                ".wav",                ".wma",                ".ogg",                ".opus",                ".mp3",                ".mp2",                ".mod",                ".amf",                ".669",                ".dmf",                ".dsm",                ".far",                ".gdm",                ".imf",                ".it",                ".m15",                ".med",                ".okt",                ".s3m",                ".stm",                ".sfx",                ".ult",                ".uni",                ".xm",                ".sid",                ".ac3",                ".dts",                ".cue",                ".aif",                ".aiff",                ".ape",                ".mac",                ".mpc",                ".mp+",                ".mpp",                ".shn",                ".wv",                ".nsf",                ".spc",                ".gym",                ".adplug",                ".adx",                ".dsp",                ".adp",                ".ymf",                ".ast",                ".afc",                ".hps",                ".xsp",                ".acc",                ".m4b",                ".oga",                ".dsf",                ".mka"            };            EpisodeExpressions = new[]            {                // *** Begin Kodi Standard Naming                // <!-- foo.s01.e01, foo.s01_e01, S01E02 foo, S01 - E02 -->                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?[][ ._-]*[Ee]([0-9]+))[^\\\/])*)?[Ss](?<seasonnumber>[0-9]+)[][ ._-]*[Ee](?<epnumber>[0-9]+)([^\\/]*)$")                {                    IsNamed = true                },                // <!-- foo.ep01, foo.EP_01 -->                new EpisodeExpression(@"[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$"),                new EpisodeExpression("([0-9]{4})[\\.-]([0-9]{2})[\\.-]([0-9]{2})", true)                {                    DateTimeFormats = new []                    {                        "yyyy.MM.dd",                        "yyyy-MM-dd",                        "yyyy_MM_dd"                    }                },                new EpisodeExpression("([0-9]{2})[\\.-]([0-9]{2})[\\.-]([0-9]{4})", true)                {                    DateTimeFormats = new []                    {                        "dd.MM.yyyy",                        "dd-MM-yyyy",                        "dd_MM_yyyy"                    }                },                new EpisodeExpression("[\\\\/\\._ \\[\\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\\.[1-9])(?![0-9]))?)([^\\\\/]*)$")                {                    SupportsAbsoluteEpisodeNumbers = true                },                new EpisodeExpression(@"[\\\\/\\._ -](?<seriesname>(?![0-9]+[0-9][0-9])([^\\\/])*)[\\\\/\\._ -](?<seasonnumber>[0-9]+)(?<epnumber>[0-9][0-9](?:(?:[a-i]|\\.[1-9])(?![0-9]))?)([\\._ -][^\\\\/]*)$")                {                    IsOptimistic = true,                    IsNamed = true,                    SupportsAbsoluteEpisodeNumbers = false                },                new EpisodeExpression("[\\/._ -]p(?:ar)?t[_. -]()([ivx]+|[0-9]+)([._ -][^\\/]*)$")                {                    SupportsAbsoluteEpisodeNumbers = true                },                // *** End Kodi Standard Naming                new EpisodeExpression(@".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})[^\\\/]*$")                {                    IsNamed = true                },                new EpisodeExpression(@".*(\\|\/)[sS](?<seasonnumber>\d{1,4})[x,X]?[eE](?<epnumber>\d{1,3})[^\\\/]*$")                {                    IsNamed = true                },                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))[^\\\/]*$")                {                    IsNamed = true                },                new EpisodeExpression(@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})[^\\\/]*$")                {                    IsNamed = true                },                // "01.avi"                new EpisodeExpression(@".*[\\\/](?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\.\w+$")                {                    IsOptimistic = true,                    IsNamed = true                },                // "1-12 episode title"                new EpisodeExpression(@"([0-9]+)-([0-9]+)")                {                },                // "01 - blah.avi", "01-blah.avi"                new EpisodeExpression(@".*(\\|\/)(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\s?-\s?[^\\\/]*$")                {                    IsOptimistic = true,                    IsNamed = true                },                // "01.blah.avi"                new EpisodeExpression(@".*(\\|\/)(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\.[^\\\/]+$")                {                    IsOptimistic = true,                    IsNamed = true                },                // "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi", "blah 2 - 01 - blah"                new EpisodeExpression(@".*[\\\/][^\\\/]* - (?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*[^\\\/]*$")                {                    IsOptimistic = true,                    IsNamed = true                },                // "01 episode title.avi"                new EpisodeExpression(@"[Ss]eason[\._ ](?<seasonnumber>[0-9]+)[\\\/](?<epnumber>\d{1,3})([^\\\/]*)$")                {                    IsOptimistic = true,                    IsNamed = true                },                // "Episode 16", "Episode 16 - Title"                new EpisodeExpression(@".*[\\\/][^\\\/]* (?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*[^\\\/]*$")                {                    IsOptimistic = true,                    IsNamed = true                }            };            EpisodeWithoutSeasonExpressions = new[]            {                @"[/\._ \-]()([0-9]+)(-[0-9]+)?"            };            EpisodeMultiPartExpressions = new[]            {                @"^[-_ex]+([0-9]+(?:(?:[a-i]|\\.[1-9])(?![0-9]))?)"            };            VideoExtraRules = new[]            {                new ExtraRule                {                    ExtraType = "trailer",                    RuleType = ExtraRuleType.Filename,                    Token = "trailer",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "trailer",                    RuleType = ExtraRuleType.Suffix,                    Token = "-trailer",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "trailer",                    RuleType = ExtraRuleType.Suffix,                    Token = ".trailer",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "trailer",                    RuleType = ExtraRuleType.Suffix,                    Token = "_trailer",                    MediaType = MediaType.Video                },                 new ExtraRule                {                    ExtraType = "trailer",                    RuleType = ExtraRuleType.Suffix,                    Token = " trailer",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "sample",                    RuleType = ExtraRuleType.Filename,                    Token = "sample",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "sample",                    RuleType = ExtraRuleType.Suffix,                    Token = "-sample",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "sample",                    RuleType = ExtraRuleType.Suffix,                    Token = ".sample",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "sample",                    RuleType = ExtraRuleType.Suffix,                    Token = "_sample",                    MediaType = MediaType.Video                },                 new ExtraRule                {                    ExtraType = "sample",                    RuleType = ExtraRuleType.Suffix,                    Token = " sample",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "themesong",                    RuleType = ExtraRuleType.Filename,                    Token = "theme",                    MediaType = MediaType.Audio                },                new ExtraRule                {                    ExtraType = "scene",                    RuleType = ExtraRuleType.Suffix,                    Token = "-scene",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "clip",                    RuleType = ExtraRuleType.Suffix,                    Token = "-clip",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "interview",                    RuleType = ExtraRuleType.Suffix,                    Token = "-interview",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "behindthescenes",                    RuleType = ExtraRuleType.Suffix,                    Token = "-behindthescenes",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "deletedscene",                    RuleType = ExtraRuleType.Suffix,                    Token = "-deleted",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "featurette",                    RuleType = ExtraRuleType.Suffix,                    Token = "-featurette",                    MediaType = MediaType.Video                },                new ExtraRule                {                    ExtraType = "short",                    RuleType = ExtraRuleType.Suffix,                    Token = "-short",                    MediaType = MediaType.Video                }            };            Format3DRules = new[]            {                // Kodi rules:                new Format3DRule                {                    PreceedingToken = "3d",                    Token = "hsbs"                },                new Format3DRule                {                    PreceedingToken = "3d",                    Token = "sbs"                },                new Format3DRule                {                    PreceedingToken = "3d",                    Token = "htab"                },                new Format3DRule                {                    PreceedingToken = "3d",                    Token = "tab"                },                                 // Media Browser rules:                new Format3DRule                {                    Token = "fsbs"                },                new Format3DRule                {                    Token = "hsbs"                },                new Format3DRule                {                    Token = "sbs"                },                new Format3DRule                {                    Token = "ftab"                },                new Format3DRule                {                    Token = "htab"                },                new Format3DRule                {                    Token = "tab"                },                new Format3DRule                {                    Token = "sbs3d"                },                new Format3DRule                {                    Token = "mvc"                }            };            AudioBookPartsExpressions = new[]            {                // Detect specified chapters, like CH 01                @"ch(?:apter)?[\s_-]?(?<chapter>\d+)",                // Detect specified parts, like Part 02                @"p(?:ar)?t[\s_-]?(?<part>\d+)",                // Chapter is often beginning of filename                @"^(?<chapter>\d+)",                // Part if often ending of filename                @"(?<part>\d+)$",                // Sometimes named as 0001_005 (chapter_part)                @"(?<chapter>\d+)_(?<part>\d+)",                // Some audiobooks are ripped from cd's, and will be named by disk number.                @"dis(?:c|k)[\s_-]?(?<chapter>\d+)"            };            var extensions = VideoFileExtensions.ToList();            extensions.AddRange(new[]            {                ".mkv",                ".m2t",                ".m2ts",                ".img",                ".iso",                ".mk3d",                ".ts",                ".rmvb",                ".mov",                ".avi",                ".mpg",                ".mpeg",                ".wmv",                ".mp4",                ".divx",                ".dvr-ms",                ".wtv",                ".ogm",                ".ogv",                ".asf",                ".m4v",                ".flv",                ".f4v",                ".3gp",                ".webm",                ".mts",                ".m2v",                ".rec",                ".mxf"            });            MultipleEpisodeExpressions = new string[]            {                @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[eExX](?<endingepnumber>\d{1,3}))+[^\\\/]*$",                @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",                @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",                @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})(-[xE]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",                @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",                @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",                @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",                @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$"            }.Select(i => new EpisodeExpression(i)            {                IsNamed = true            }).ToArray();            VideoFileExtensions = extensions                .Distinct(StringComparer.OrdinalIgnoreCase)                .ToArray();            Compile();        }        public Regex[] VideoFileStackingRegexes { get; private set; }        public Regex[] CleanDateTimeRegexes { get; private set; }        public Regex[] CleanStringRegexes { get; private set; }        public Regex[] EpisodeWithoutSeasonRegexes { get; private set; }        public Regex[] EpisodeMultiPartRegexes { get; private set; }        public void Compile()        {            VideoFileStackingRegexes = VideoFileStackingExpressions.Select(Compile).ToArray();            CleanDateTimeRegexes = CleanDateTimes.Select(Compile).ToArray();            CleanStringRegexes = CleanStrings.Select(Compile).ToArray();            EpisodeWithoutSeasonRegexes = EpisodeWithoutSeasonExpressions.Select(Compile).ToArray();            EpisodeMultiPartRegexes = EpisodeMultiPartExpressions.Select(Compile).ToArray();        }        private Regex Compile(string exp)        {            return new Regex(exp, RegexOptions.IgnoreCase | RegexOptions.Compiled);        }    }}
 |