< Summary - Jellyfin

Information
Class: Emby.Naming.Common.NamingOptions
Assembly: Emby.Naming
File(s): /srv/git/jellyfin/Emby.Naming/Common/NamingOptions.cs
Line coverage
100%
Covered lines: 718
Uncovered lines: 0
Coverable lines: 718
Total lines: 901
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
Compile()100%11100%
Compile(...)100%11100%

File(s)

/srv/git/jellyfin/Emby.Naming/Common/NamingOptions.cs

#LineLine coverage
 1#pragma warning disable CA1819
 2
 3using System;
 4using System.Collections.Generic;
 5using System.Linq;
 6using System.Text.RegularExpressions;
 7using Emby.Naming.Video;
 8using MediaBrowser.Model.Entities;
 9
 10// ReSharper disable StringLiteralTypo
 11
 12namespace Emby.Naming.Common
 13{
 14    /// <summary>
 15    /// Big ugly class containing lot of different naming options that should be split and injected instead of passes ev
 16    /// </summary>
 17    public class NamingOptions
 18    {
 19        /// <summary>
 20        /// Initializes a new instance of the <see cref="NamingOptions"/> class.
 21        /// </summary>
 22        public NamingOptions()
 23        {
 64524            VideoFileExtensions = new[]
 64525            {
 64526                ".001",
 64527                ".3g2",
 64528                ".3gp",
 64529                ".amv",
 64530                ".asf",
 64531                ".asx",
 64532                ".avi",
 64533                ".bin",
 64534                ".bivx",
 64535                ".divx",
 64536                ".dv",
 64537                ".dvr-ms",
 64538                ".f4v",
 64539                ".fli",
 64540                ".flv",
 64541                ".ifo",
 64542                ".img",
 64543                ".iso",
 64544                ".m2t",
 64545                ".m2ts",
 64546                ".m2v",
 64547                ".m4v",
 64548                ".mkv",
 64549                ".mk3d",
 64550                ".mov",
 64551                ".mp4",
 64552                ".mpe",
 64553                ".mpeg",
 64554                ".mpg",
 64555                ".mts",
 64556                ".mxf",
 64557                ".nrg",
 64558                ".nsv",
 64559                ".nuv",
 64560                ".ogg",
 64561                ".ogm",
 64562                ".ogv",
 64563                ".pva",
 64564                ".qt",
 64565                ".rec",
 64566                ".rm",
 64567                ".rmvb",
 64568                ".strm",
 64569                ".svq3",
 64570                ".tp",
 64571                ".ts",
 64572                ".ty",
 64573                ".viv",
 64574                ".vob",
 64575                ".vp3",
 64576                ".webm",
 64577                ".wmv",
 64578                ".wtv",
 64579                ".xvid"
 64580            };
 81
 64582            VideoFlagDelimiters = new[]
 64583            {
 64584                '(',
 64585                ')',
 64586                '-',
 64587                '.',
 64588                '_',
 64589                '[',
 64590                ']'
 64591            };
 92
 64593            StubFileExtensions = new[]
 64594            {
 64595                ".disc"
 64596            };
 97
 64598            StubTypes = new[]
 64599            {
 645100                new StubTypeRule(
 645101                    stubType: "dvd",
 645102                    token: "dvd"),
 645103
 645104                new StubTypeRule(
 645105                    stubType: "hddvd",
 645106                    token: "hddvd"),
 645107
 645108                new StubTypeRule(
 645109                    stubType: "bluray",
 645110                    token: "bluray"),
 645111
 645112                new StubTypeRule(
 645113                    stubType: "bluray",
 645114                    token: "brrip"),
 645115
 645116                new StubTypeRule(
 645117                    stubType: "bluray",
 645118                    token: "bd25"),
 645119
 645120                new StubTypeRule(
 645121                    stubType: "bluray",
 645122                    token: "bd50"),
 645123
 645124                new StubTypeRule(
 645125                    stubType: "vhs",
 645126                    token: "vhs"),
 645127
 645128                new StubTypeRule(
 645129                    stubType: "tv",
 645130                    token: "HDTV"),
 645131
 645132                new StubTypeRule(
 645133                    stubType: "tv",
 645134                    token: "PDTV"),
 645135
 645136                new StubTypeRule(
 645137                    stubType: "tv",
 645138                    token: "DSR")
 645139            };
 140
 645141            VideoFileStackingRules = new[]
 645142            {
 645143                new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])
 645144                new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])
 645145            };
 146
 645147            CleanDateTimes = new[]
 645148            {
 645149                @"(.+[^_\,\.\(\)\[\]\-])[_\.\(\)\[\]\-](19[0-9]{2}|20[0-9]{2})(?![0-9]+|\W[0-9]{2}\W[0-9]{2})([ _\,\.\(\
 645150                @"(.+[^_\,\.\(\)\[\]\-])[ _\.\(\)\[\]\-]+(19[0-9]{2}|20[0-9]{2})(?![0-9]+|\W[0-9]{2}\W[0-9]{2})([ _\,\.\
 645151            };
 152
 645153            CleanStrings = new[]
 645154            {
 645155                @"^\s*(?<cleaned>.+?)[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|d
 645156                @"^(?<cleaned>.+?)(\[.*\])",
 645157                @"^\s*(?<cleaned>.+?)\WE[0-9]+(-|~)E?[0-9]+(\W|$)",
 645158                @"^\s*\[[^\]]+\](?!\.\w+$)\s*(?<cleaned>.+)",
 645159                @"^\s*(?<cleaned>.+?)\s+-\s+[0-9]+\s*$",
 645160                @"^\s*(?<cleaned>.+?)(([-._ ](trailer|sample))|-(scene|clip|behindthescenes|deleted|deletedscene|feature
 645161            };
 162
 645163            SubtitleFileExtensions = new[]
 645164            {
 645165                ".ass",
 645166                ".mks",
 645167                ".sami",
 645168                ".smi",
 645169                ".srt",
 645170                ".ssa",
 645171                ".sub",
 645172                ".sup",
 645173                ".vtt",
 645174            };
 175
 645176            LyricFileExtensions = new[]
 645177            {
 645178                ".lrc",
 645179                ".elrc",
 645180                ".txt"
 645181            };
 182
 645183            AlbumStackingPrefixes = new[]
 645184            {
 645185                "cd",
 645186                "digital media",
 645187                "disc",
 645188                "disk",
 645189                "vol",
 645190                "volume"
 645191            };
 192
 645193            ArtistSubfolders = new[]
 645194            {
 645195                "albums",
 645196                "broadcasts",
 645197                "bootlegs",
 645198                "compilations",
 645199                "dj-mixes",
 645200                "eps",
 645201                "live",
 645202                "mixtapes",
 645203                "others",
 645204                "remixes",
 645205                "singles",
 645206                "soundtracks",
 645207                "spokenwords",
 645208                "streets"
 645209            };
 210
 645211            AudioFileExtensions = new[]
 645212            {
 645213                ".669",
 645214                ".3gp",
 645215                ".aa",
 645216                ".aac",
 645217                ".aax",
 645218                ".ac3",
 645219                ".act",
 645220                ".adp",
 645221                ".adplug",
 645222                ".adx",
 645223                ".afc",
 645224                ".amf",
 645225                ".aif",
 645226                ".aiff",
 645227                ".alac",
 645228                ".amr",
 645229                ".ape",
 645230                ".ast",
 645231                ".au",
 645232                ".awb",
 645233                ".cda",
 645234                ".cue",
 645235                ".dmf",
 645236                ".dsf",
 645237                ".dsm",
 645238                ".dsp",
 645239                ".dts",
 645240                ".dvf",
 645241                ".far",
 645242                ".flac",
 645243                ".gdm",
 645244                ".gsm",
 645245                ".gym",
 645246                ".hps",
 645247                ".imf",
 645248                ".it",
 645249                ".m15",
 645250                ".m4a",
 645251                ".m4b",
 645252                ".mac",
 645253                ".med",
 645254                ".mka",
 645255                ".mmf",
 645256                ".mod",
 645257                ".mogg",
 645258                ".mp2",
 645259                ".mp3",
 645260                ".mpa",
 645261                ".mpc",
 645262                ".mpp",
 645263                ".mp+",
 645264                ".msv",
 645265                ".nmf",
 645266                ".nsf",
 645267                ".nsv",
 645268                ".oga",
 645269                ".ogg",
 645270                ".okt",
 645271                ".opus",
 645272                ".pls",
 645273                ".ra",
 645274                ".rf64",
 645275                ".rm",
 645276                ".s3m",
 645277                ".sfx",
 645278                ".shn",
 645279                ".sid",
 645280                ".stm",
 645281                ".strm",
 645282                ".ult",
 645283                ".uni",
 645284                ".vox",
 645285                ".wav",
 645286                ".wma",
 645287                ".wv",
 645288                ".xm",
 645289                ".xsp",
 645290                ".ymf"
 645291            };
 292
 645293            MediaFlagDelimiters = new[]
 645294            {
 645295                '.'
 645296            };
 297
 645298            MediaForcedFlags = new[]
 645299            {
 645300                "foreign",
 645301                "forced"
 645302            };
 303
 645304            MediaDefaultFlags = new[]
 645305            {
 645306                "default"
 645307            };
 308
 645309            MediaHearingImpairedFlags = new[]
 645310            {
 645311                "cc",
 645312                "hi",
 645313                "sdh"
 645314            };
 315
 645316            EpisodeExpressions = new[]
 645317            {
 645318                // *** Begin Kodi Standard Naming
 645319                // <!-- foo.s01.e01, foo.s01_e01, S01E02 foo, S01 - E02 -->
 645320                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![Ss]([0-9]+)[][ ._-]*[Ee]([0-9]+))[^\\\/])*)?[Ss](?<s
 645321                {
 645322                    IsNamed = true
 645323                },
 645324                // <!-- foo.ep01, foo.EP_01 -->
 645325                new EpisodeExpression(@"[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$"),
 645326                // <!-- foo.E01., foo.e01. -->
 645327                new EpisodeExpression(@"[^\\/]*?()\.?[Ee]([0-9]+)\.([^\\/]*)$"),
 645328                new EpisodeExpression("(?<year>[0-9]{4})[._ -](?<month>[0-9]{2})[._ -](?<day>[0-9]{2})", true)
 645329                {
 645330                    DateTimeFormats = new[]
 645331                    {
 645332                        "yyyy.MM.dd",
 645333                        "yyyy-MM-dd",
 645334                        "yyyy_MM_dd",
 645335                        "yyyy MM dd"
 645336                    }
 645337                },
 645338                new EpisodeExpression("(?<day>[0-9]{2})[._ -](?<month>[0-9]{2})[._ -](?<year>[0-9]{4})", true)
 645339                {
 645340                    DateTimeFormats = new[]
 645341                    {
 645342                        "dd.MM.yyyy",
 645343                        "dd-MM-yyyy",
 645344                        "dd_MM_yyyy",
 645345                        "dd MM yyyy"
 645346                    }
 645347                },
 645348
 645349                // This isn't a Kodi naming rule, but the expression below causes false episode numbers for
 645350                // Title Season X Episode X naming schemes.
 645351                // "Series Season X Episode X - Title.avi", "Series S03 E09.avi", "s3 e9 - Title.avi"
 645352                new EpisodeExpression(@".*[\\\/]((?<seriesname>[^\\/]+?)\s)?[Ss](?:eason)?\s*(?<seasonnumber>[0-9]+)\s+[
 645353                {
 645354                    IsNamed = true
 645355                },
 645356
 645357                // Not a Kodi rule as well, but the expression below also causes false positives,
 645358                // so we make sure this one gets tested first.
 645359                // "Foo Bar 889"
 645360                new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>[0-9]{1,4})(-(?<endin
 645361                {
 645362                    IsNamed = true
 645363                },
 645364
 645365                new EpisodeExpression(@"[\\\/\._ \[\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\.[1-9])(?![0-9]))?)([^\\\/]*)$")
 645366                {
 645367                    SupportsAbsoluteEpisodeNumbers = true
 645368                },
 645369
 645370                // Not a Kodi rule as well, but below rule also causes false positives for triple-digit episode names
 645371                // [bar] Foo - 1 [baz] special case of below expression to prevent false positives with digits in the se
 645372                new EpisodeExpression(@".*[\\\/]?.*?(\[.*?\])+.*?(?<seriesname>[-\w\s]+?)[\s_]*-[\s_]*(?<epnumber>[0-9]+
 645373                {
 645374                    IsNamed = true
 645375                },
 645376
 645377                // /server/anything_102.mp4
 645378                // /server/james.corden.2017.04.20.anne.hathaway.720p.hdtv.x264-crooks.mkv
 645379                // /server/anything_1996.11.14.mp4
 645380                new EpisodeExpression(@"[\\/._ -](?<seriesname>(?![0-9]+[0-9][0-9])([^\\\/_])*)[\\\/._ -](?<seasonnumber
 645381                {
 645382                    IsOptimistic = true,
 645383                    IsNamed = true,
 645384                    SupportsAbsoluteEpisodeNumbers = false
 645385                },
 645386                new EpisodeExpression(@"[\/._ -]p(?:ar)?t[_. -]()([ivx]+|[0-9]+)([._ -][^\/]*)$")
 645387                {
 645388                    SupportsAbsoluteEpisodeNumbers = true
 645389                },
 645390
 645391                // *** End Kodi Standard Naming
 645392
 645393                // "Episode 16", "Episode 16 - Title"
 645394                new EpisodeExpression(@"[Ee]pisode (?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))?[^\\\/]*$")
 645395                {
 645396                    IsNamed = true
 645397                },
 645398
 645399                new EpisodeExpression(@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]+)[xX](?<epnumber>[0-9]+)[^\\\/]*$")
 645400                {
 645401                    IsNamed = true
 645402                },
 645403
 645404                new EpisodeExpression(@".*(\\|\/)[sS](?<seasonnumber>[0-9]+)[x,X]?[eE](?<epnumber>[0-9]+)[^\\\/]*$")
 645405                {
 645406                    IsNamed = true
 645407                },
 645408
 645409                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<sea
 645410                {
 645411                    IsNamed = true
 645412                },
 645413
 645414                new EpisodeExpression(@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epn
 645415                {
 645416                    IsNamed = true
 645417                },
 645418
 645419                // "01.avi"
 645420                new EpisodeExpression(@".*[\\\/](?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))*\.\w+$")
 645421                {
 645422                    IsOptimistic = true,
 645423                    IsNamed = true
 645424                },
 645425
 645426                // "1-12 episode title"
 645427                new EpisodeExpression("([0-9]+)-([0-9]+)"),
 645428
 645429                // "01 - blah.avi", "01-blah.avi"
 645430                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\s?-\s?[^\\\/]*
 645431                {
 645432                    IsOptimistic = true,
 645433                    IsNamed = true
 645434                },
 645435
 645436                // "01.blah.avi"
 645437                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\.[^\\\/]+$")
 645438                {
 645439                    IsOptimistic = true,
 645440                    IsNamed = true
 645441                },
 645442
 645443                // "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi",
 645444                new EpisodeExpression(@".*[\\\/][^\\\/]* - (?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\
 645445                {
 645446                    IsOptimistic = true,
 645447                    IsNamed = true
 645448                },
 645449
 645450                // "01 episode title.avi"
 645451                new EpisodeExpression(@"[Ss]eason[\._ ](?<seasonnumber>[0-9]+)[\\\/](?<epnumber>[0-9]{1,3})([^\\\/]*)$")
 645452                {
 645453                    IsOptimistic = true,
 645454                    IsNamed = true
 645455                },
 645456
 645457                // Series and season only expression
 645458                // "the show/season 1", "the show/s01"
 645459                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)\/[Ss](eason)?[\. _\-]*(?<seasonnumber>[0-9]+)")
 645460                {
 645461                    IsNamed = true
 645462                },
 645463
 645464                // Series and season only expression
 645465                // "the show S01", "the show season 1"
 645466                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)[\. _\-]+[sS](eason)?[\. _\-]*(?<seasonnumber>[0-9]
 645467                {
 645468                    IsNamed = true
 645469                },
 645470            };
 471
 645472            VideoExtraRules = new[]
 645473            {
 645474                new ExtraRule(
 645475                    ExtraType.Trailer,
 645476                    ExtraRuleType.DirectoryName,
 645477                    "trailers",
 645478                    MediaType.Video),
 645479
 645480                new ExtraRule(
 645481                    ExtraType.ThemeVideo,
 645482                    ExtraRuleType.DirectoryName,
 645483                    "backdrops",
 645484                    MediaType.Video),
 645485
 645486                new ExtraRule(
 645487                    ExtraType.ThemeSong,
 645488                    ExtraRuleType.DirectoryName,
 645489                    "theme-music",
 645490                    MediaType.Audio),
 645491
 645492                new ExtraRule(
 645493                    ExtraType.BehindTheScenes,
 645494                    ExtraRuleType.DirectoryName,
 645495                    "behind the scenes",
 645496                    MediaType.Video),
 645497
 645498                new ExtraRule(
 645499                    ExtraType.DeletedScene,
 645500                    ExtraRuleType.DirectoryName,
 645501                    "deleted scenes",
 645502                    MediaType.Video),
 645503
 645504                new ExtraRule(
 645505                    ExtraType.Interview,
 645506                    ExtraRuleType.DirectoryName,
 645507                    "interviews",
 645508                    MediaType.Video),
 645509
 645510                new ExtraRule(
 645511                    ExtraType.Scene,
 645512                    ExtraRuleType.DirectoryName,
 645513                    "scenes",
 645514                    MediaType.Video),
 645515
 645516                new ExtraRule(
 645517                    ExtraType.Sample,
 645518                    ExtraRuleType.DirectoryName,
 645519                    "samples",
 645520                    MediaType.Video),
 645521
 645522                new ExtraRule(
 645523                    ExtraType.Short,
 645524                    ExtraRuleType.DirectoryName,
 645525                    "shorts",
 645526                    MediaType.Video),
 645527
 645528                new ExtraRule(
 645529                    ExtraType.Featurette,
 645530                    ExtraRuleType.DirectoryName,
 645531                    "featurettes",
 645532                    MediaType.Video),
 645533
 645534                new ExtraRule(
 645535                    ExtraType.Unknown,
 645536                    ExtraRuleType.DirectoryName,
 645537                    "extras",
 645538                    MediaType.Video),
 645539
 645540                new ExtraRule(
 645541                    ExtraType.Unknown,
 645542                    ExtraRuleType.DirectoryName,
 645543                    "extra",
 645544                    MediaType.Video),
 645545
 645546                new ExtraRule(
 645547                    ExtraType.Unknown,
 645548                    ExtraRuleType.DirectoryName,
 645549                    "other",
 645550                    MediaType.Video),
 645551
 645552                new ExtraRule(
 645553                    ExtraType.Clip,
 645554                    ExtraRuleType.DirectoryName,
 645555                    "clips",
 645556                    MediaType.Video),
 645557
 645558                new ExtraRule(
 645559                    ExtraType.Trailer,
 645560                    ExtraRuleType.Filename,
 645561                    "trailer",
 645562                    MediaType.Video),
 645563
 645564                new ExtraRule(
 645565                    ExtraType.Trailer,
 645566                    ExtraRuleType.Suffix,
 645567                    "-trailer",
 645568                    MediaType.Video),
 645569
 645570                new ExtraRule(
 645571                    ExtraType.Trailer,
 645572                    ExtraRuleType.Suffix,
 645573                    ".trailer",
 645574                    MediaType.Video),
 645575
 645576                new ExtraRule(
 645577                    ExtraType.Trailer,
 645578                    ExtraRuleType.Suffix,
 645579                    "_trailer",
 645580                    MediaType.Video),
 645581
 645582                new ExtraRule(
 645583                    ExtraType.Trailer,
 645584                    ExtraRuleType.Suffix,
 645585                    " trailer",
 645586                    MediaType.Video),
 645587
 645588                new ExtraRule(
 645589                    ExtraType.Sample,
 645590                    ExtraRuleType.Filename,
 645591                    "sample",
 645592                    MediaType.Video),
 645593
 645594                new ExtraRule(
 645595                    ExtraType.Sample,
 645596                    ExtraRuleType.Suffix,
 645597                    "-sample",
 645598                    MediaType.Video),
 645599
 645600                new ExtraRule(
 645601                    ExtraType.Sample,
 645602                    ExtraRuleType.Suffix,
 645603                    ".sample",
 645604                    MediaType.Video),
 645605
 645606                new ExtraRule(
 645607                    ExtraType.Sample,
 645608                    ExtraRuleType.Suffix,
 645609                    "_sample",
 645610                    MediaType.Video),
 645611
 645612                new ExtraRule(
 645613                    ExtraType.Sample,
 645614                    ExtraRuleType.Suffix,
 645615                    " sample",
 645616                    MediaType.Video),
 645617
 645618                new ExtraRule(
 645619                    ExtraType.ThemeSong,
 645620                    ExtraRuleType.Filename,
 645621                    "theme",
 645622                    MediaType.Audio),
 645623
 645624                new ExtraRule(
 645625                    ExtraType.Scene,
 645626                    ExtraRuleType.Suffix,
 645627                    "-scene",
 645628                    MediaType.Video),
 645629
 645630                new ExtraRule(
 645631                    ExtraType.Clip,
 645632                    ExtraRuleType.Suffix,
 645633                    "-clip",
 645634                    MediaType.Video),
 645635
 645636                new ExtraRule(
 645637                    ExtraType.Interview,
 645638                    ExtraRuleType.Suffix,
 645639                    "-interview",
 645640                    MediaType.Video),
 645641
 645642                new ExtraRule(
 645643                    ExtraType.BehindTheScenes,
 645644                    ExtraRuleType.Suffix,
 645645                    "-behindthescenes",
 645646                    MediaType.Video),
 645647
 645648                new ExtraRule(
 645649                    ExtraType.DeletedScene,
 645650                    ExtraRuleType.Suffix,
 645651                    "-deleted",
 645652                    MediaType.Video),
 645653
 645654                new ExtraRule(
 645655                    ExtraType.DeletedScene,
 645656                    ExtraRuleType.Suffix,
 645657                    "-deletedscene",
 645658                    MediaType.Video),
 645659
 645660                new ExtraRule(
 645661                    ExtraType.Featurette,
 645662                    ExtraRuleType.Suffix,
 645663                    "-featurette",
 645664                    MediaType.Video),
 645665
 645666                new ExtraRule(
 645667                    ExtraType.Short,
 645668                    ExtraRuleType.Suffix,
 645669                    "-short",
 645670                    MediaType.Video),
 645671
 645672                new ExtraRule(
 645673                    ExtraType.Unknown,
 645674                    ExtraRuleType.Suffix,
 645675                    "-extra",
 645676                    MediaType.Video),
 645677
 645678                new ExtraRule(
 645679                    ExtraType.Unknown,
 645680                    ExtraRuleType.Suffix,
 645681                    "-other",
 645682                    MediaType.Video)
 645683            };
 684
 645685            AllExtrasTypesFolderNames = VideoExtraRules
 645686                .Where(i => i.RuleType == ExtraRuleType.DirectoryName)
 645687                .ToDictionary(i => i.Token, i => i.ExtraType, StringComparer.OrdinalIgnoreCase);
 688
 645689            Format3DRules = new[]
 645690            {
 645691                // Kodi rules:
 645692                new Format3DRule(
 645693                    precedingToken: "3d",
 645694                    token: "hsbs"),
 645695
 645696                new Format3DRule(
 645697                    precedingToken: "3d",
 645698                    token: "sbs"),
 645699
 645700                new Format3DRule(
 645701                    precedingToken: "3d",
 645702                    token: "htab"),
 645703
 645704                new Format3DRule(
 645705                    precedingToken: "3d",
 645706                    token: "tab"),
 645707
 645708                 // Media Browser rules:
 645709                new Format3DRule("fsbs"),
 645710                new Format3DRule("hsbs"),
 645711                new Format3DRule("sbs"),
 645712                new Format3DRule("ftab"),
 645713                new Format3DRule("htab"),
 645714                new Format3DRule("tab"),
 645715                new Format3DRule("sbs3d"),
 645716                new Format3DRule("mvc")
 645717            };
 718
 645719            AudioBookPartsExpressions = new[]
 645720            {
 645721                // Detect specified chapters, like CH 01
 645722                @"ch(?:apter)?[\s_-]?(?<chapter>[0-9]+)",
 645723                // Detect specified parts, like Part 02
 645724                @"p(?:ar)?t[\s_-]?(?<part>[0-9]+)",
 645725                // Chapter is often beginning of filename
 645726                "^(?<chapter>[0-9]+)",
 645727                // Part if often ending of filename
 645728                "(?<!ch(?:apter) )(?<part>[0-9]+)$",
 645729                // Sometimes named as 0001_005 (chapter_part)
 645730                "(?<chapter>[0-9]+)_(?<part>[0-9]+)",
 645731                // Some audiobooks are ripped from cd's, and will be named by disk number.
 645732                @"dis(?:c|k)[\s_-]?(?<chapter>[0-9]+)"
 645733            };
 734
 645735            AudioBookNamesExpressions = new[]
 645736            {
 645737                // Detect year usually in brackets after name Batman (2020)
 645738                @"^(?<name>.+?)\s*\(\s*(?<year>[0-9]{4})\s*\)\s*$",
 645739                @"^\s*(?<name>[^ ].*?)\s*$"
 645740            };
 741
 645742            MultipleEpisodeExpressions = new[]
 645743            {
 645744                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endinge
 645745                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[xX][eE](?<endin
 645746                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )?[xXeE](?<endingepnumber>[
 645747                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})(-[xE]?[eE]?(?<endingepnumber>[0-9
 645748                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 645749                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 645750                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 645751                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 645752                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})((-| 
 645753                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})(-[xX
 645754            }.Select(i => new EpisodeExpression(i)
 645755            {
 645756                IsNamed = true
 645757            }).ToArray();
 758
 645759            Compile();
 645760        }
 761
 762        /// <summary>
 763        /// Gets or sets the folder name to extra types mapping.
 764        /// </summary>
 765        public Dictionary<string, ExtraType> AllExtrasTypesFolderNames { get; set; }
 766
 767        /// <summary>
 768        /// Gets or sets list of audio file extensions.
 769        /// </summary>
 770        public string[] AudioFileExtensions { get; set; }
 771
 772        /// <summary>
 773        /// Gets or sets list of external media flag delimiters.
 774        /// </summary>
 775        public char[] MediaFlagDelimiters { get; set; }
 776
 777        /// <summary>
 778        /// Gets or sets list of external media forced flags.
 779        /// </summary>
 780        public string[] MediaForcedFlags { get; set; }
 781
 782        /// <summary>
 783        /// Gets or sets list of external media default flags.
 784        /// </summary>
 785        public string[] MediaDefaultFlags { get; set; }
 786
 787        /// <summary>
 788        /// Gets or sets list of external media hearing impaired flags.
 789        /// </summary>
 790        public string[] MediaHearingImpairedFlags { get; set; }
 791
 792        /// <summary>
 793        /// Gets or sets list of album stacking prefixes.
 794        /// </summary>
 795        public string[] AlbumStackingPrefixes { get; set; }
 796
 797        /// <summary>
 798        /// Gets or sets list of artist subfolders.
 799        /// </summary>
 800        public string[] ArtistSubfolders { get; set; }
 801
 802        /// <summary>
 803        /// Gets or sets list of subtitle file extensions.
 804        /// </summary>
 805        public string[] SubtitleFileExtensions { get; set; }
 806
 807        /// <summary>
 808        /// Gets the list of lyric file extensions.
 809        /// </summary>
 810        public string[] LyricFileExtensions { get; }
 811
 812        /// <summary>
 813        /// Gets or sets list of episode regular expressions.
 814        /// </summary>
 815        public EpisodeExpression[] EpisodeExpressions { get; set; }
 816
 817        /// <summary>
 818        /// Gets or sets list of video file extensions.
 819        /// </summary>
 820        public string[] VideoFileExtensions { get; set; }
 821
 822        /// <summary>
 823        /// Gets or sets list of video stub file extensions.
 824        /// </summary>
 825        public string[] StubFileExtensions { get; set; }
 826
 827        /// <summary>
 828        /// Gets or sets list of raw audiobook parts regular expressions strings.
 829        /// </summary>
 830        public string[] AudioBookPartsExpressions { get; set; }
 831
 832        /// <summary>
 833        /// Gets or sets list of raw audiobook names regular expressions strings.
 834        /// </summary>
 835        public string[] AudioBookNamesExpressions { get; set; }
 836
 837        /// <summary>
 838        /// Gets or sets list of stub type rules.
 839        /// </summary>
 840        public StubTypeRule[] StubTypes { get; set; }
 841
 842        /// <summary>
 843        /// Gets or sets list of video flag delimiters.
 844        /// </summary>
 845        public char[] VideoFlagDelimiters { get; set; }
 846
 847        /// <summary>
 848        /// Gets or sets list of 3D Format rules.
 849        /// </summary>
 850        public Format3DRule[] Format3DRules { get; set; }
 851
 852        /// <summary>
 853        /// Gets the file stacking rules.
 854        /// </summary>
 855        public FileStackRule[] VideoFileStackingRules { get; }
 856
 857        /// <summary>
 858        /// Gets or sets list of raw clean DateTimes regular expressions strings.
 859        /// </summary>
 860        public string[] CleanDateTimes { get; set; }
 861
 862        /// <summary>
 863        /// Gets or sets list of raw clean strings regular expressions strings.
 864        /// </summary>
 865        public string[] CleanStrings { get; set; }
 866
 867        /// <summary>
 868        /// Gets or sets list of multi-episode regular expressions.
 869        /// </summary>
 870        public EpisodeExpression[] MultipleEpisodeExpressions { get; set; }
 871
 872        /// <summary>
 873        /// Gets or sets list of extra rules for videos.
 874        /// </summary>
 875        public ExtraRule[] VideoExtraRules { get; set; }
 876
 877        /// <summary>
 878        /// Gets list of clean datetime regular expressions.
 879        /// </summary>
 880        public Regex[] CleanDateTimeRegexes { get; private set; } = Array.Empty<Regex>();
 881
 882        /// <summary>
 883        /// Gets list of clean string regular expressions.
 884        /// </summary>
 885        public Regex[] CleanStringRegexes { get; private set; } = Array.Empty<Regex>();
 886
 887        /// <summary>
 888        /// Compiles raw regex strings into regexes.
 889        /// </summary>
 890        public void Compile()
 891        {
 646892            CleanDateTimeRegexes = CleanDateTimes.Select(Compile).ToArray();
 646893            CleanStringRegexes = CleanStrings.Select(Compile).ToArray();
 646894        }
 895
 896        private Regex Compile(string exp)
 897        {
 5168898            return new Regex(exp, RegexOptions.IgnoreCase | RegexOptions.Compiled);
 899        }
 900    }
 901}