< 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: 729
Uncovered lines: 0
Coverable lines: 729
Total lines: 912
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        {
 67024            VideoFileExtensions = new[]
 67025            {
 67026                ".001",
 67027                ".3g2",
 67028                ".3gp",
 67029                ".amv",
 67030                ".asf",
 67031                ".asx",
 67032                ".avi",
 67033                ".bin",
 67034                ".bivx",
 67035                ".divx",
 67036                ".dv",
 67037                ".dvr-ms",
 67038                ".f4v",
 67039                ".fli",
 67040                ".flv",
 67041                ".ifo",
 67042                ".img",
 67043                ".iso",
 67044                ".m2t",
 67045                ".m2ts",
 67046                ".m2v",
 67047                ".m4v",
 67048                ".mkv",
 67049                ".mk3d",
 67050                ".mov",
 67051                ".mp4",
 67052                ".mpe",
 67053                ".mpeg",
 67054                ".mpg",
 67055                ".mts",
 67056                ".mxf",
 67057                ".nrg",
 67058                ".nsv",
 67059                ".nuv",
 67060                ".ogg",
 67061                ".ogm",
 67062                ".ogv",
 67063                ".pva",
 67064                ".qt",
 67065                ".rec",
 67066                ".rm",
 67067                ".rmvb",
 67068                ".strm",
 67069                ".svq3",
 67070                ".tp",
 67071                ".ts",
 67072                ".ty",
 67073                ".viv",
 67074                ".vob",
 67075                ".vp3",
 67076                ".webm",
 67077                ".wmv",
 67078                ".wtv",
 67079                ".xvid"
 67080            };
 81
 67082            VideoFlagDelimiters = new[]
 67083            {
 67084                '(',
 67085                ')',
 67086                '-',
 67087                '.',
 67088                '_',
 67089                '[',
 67090                ']'
 67091            };
 92
 67093            StubFileExtensions = new[]
 67094            {
 67095                ".disc"
 67096            };
 97
 67098            StubTypes = new[]
 67099            {
 670100                new StubTypeRule(
 670101                    stubType: "dvd",
 670102                    token: "dvd"),
 670103
 670104                new StubTypeRule(
 670105                    stubType: "hddvd",
 670106                    token: "hddvd"),
 670107
 670108                new StubTypeRule(
 670109                    stubType: "bluray",
 670110                    token: "bluray"),
 670111
 670112                new StubTypeRule(
 670113                    stubType: "bluray",
 670114                    token: "brrip"),
 670115
 670116                new StubTypeRule(
 670117                    stubType: "bluray",
 670118                    token: "bd25"),
 670119
 670120                new StubTypeRule(
 670121                    stubType: "bluray",
 670122                    token: "bd50"),
 670123
 670124                new StubTypeRule(
 670125                    stubType: "vhs",
 670126                    token: "vhs"),
 670127
 670128                new StubTypeRule(
 670129                    stubType: "tv",
 670130                    token: "HDTV"),
 670131
 670132                new StubTypeRule(
 670133                    stubType: "tv",
 670134                    token: "PDTV"),
 670135
 670136                new StubTypeRule(
 670137                    stubType: "tv",
 670138                    token: "DSR")
 670139            };
 140
 670141            VideoFileStackingRules = new[]
 670142            {
 670143                new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])
 670144                new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])
 670145            };
 146
 670147            CleanDateTimes = new[]
 670148            {
 670149                @"(.+[^_\,\.\(\)\[\]\-])[_\.\(\)\[\]\-](19[0-9]{2}|20[0-9]{2})(?![0-9]+|\W[0-9]{2}\W[0-9]{2})([ _\,\.\(\
 670150                @"(.+[^_\,\.\(\)\[\]\-])[ _\.\(\)\[\]\-]+(19[0-9]{2}|20[0-9]{2})(?![0-9]+|\W[0-9]{2}\W[0-9]{2})([ _\,\.\
 670151            };
 152
 670153            CleanStrings = new[]
 670154            {
 670155                @"^\s*(?<cleaned>.+?)[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|d
 670156                @"^(?<cleaned>.+?)(\[.*\])",
 670157                @"^\s*(?<cleaned>.+?)\WE[0-9]+(-|~)E?[0-9]+(\W|$)",
 670158                @"^\s*\[[^\]]+\](?!\.\w+$)\s*(?<cleaned>.+)",
 670159                @"^\s*(?<cleaned>.+?)\s+-\s+[0-9]+\s*$",
 670160                @"^\s*(?<cleaned>.+?)(([-._ ](trailer|sample))|-(scene|clip|behindthescenes|deleted|deletedscene|feature
 670161            };
 162
 670163            SubtitleFileExtensions = new[]
 670164            {
 670165                ".ass",
 670166                ".mks",
 670167                ".sami",
 670168                ".smi",
 670169                ".srt",
 670170                ".ssa",
 670171                ".sub",
 670172                ".sup",
 670173                ".vtt",
 670174            };
 175
 670176            LyricFileExtensions = new[]
 670177            {
 670178                ".lrc",
 670179                ".elrc",
 670180                ".txt"
 670181            };
 182
 670183            AlbumStackingPrefixes = new[]
 670184            {
 670185                "cd",
 670186                "digital media",
 670187                "disc",
 670188                "disk",
 670189                "vol",
 670190                "volume",
 670191                "part",
 670192                "act"
 670193            };
 194
 670195            ArtistSubfolders = new[]
 670196            {
 670197                "albums",
 670198                "broadcasts",
 670199                "bootlegs",
 670200                "compilations",
 670201                "dj-mixes",
 670202                "eps",
 670203                "live",
 670204                "mixtapes",
 670205                "others",
 670206                "remixes",
 670207                "singles",
 670208                "soundtracks",
 670209                "spokenwords",
 670210                "streets"
 670211            };
 212
 670213            AudioFileExtensions = new[]
 670214            {
 670215                ".669",
 670216                ".3gp",
 670217                ".aa",
 670218                ".aac",
 670219                ".aax",
 670220                ".ac3",
 670221                ".act",
 670222                ".adp",
 670223                ".adplug",
 670224                ".adx",
 670225                ".afc",
 670226                ".amf",
 670227                ".aif",
 670228                ".aiff",
 670229                ".alac",
 670230                ".amr",
 670231                ".ape",
 670232                ".ast",
 670233                ".au",
 670234                ".awb",
 670235                ".cda",
 670236                ".cue",
 670237                ".dmf",
 670238                ".dsf",
 670239                ".dsm",
 670240                ".dsp",
 670241                ".dts",
 670242                ".dvf",
 670243                ".eac3",
 670244                ".far",
 670245                ".flac",
 670246                ".gdm",
 670247                ".gsm",
 670248                ".gym",
 670249                ".hps",
 670250                ".imf",
 670251                ".it",
 670252                ".m15",
 670253                ".m4a",
 670254                ".m4b",
 670255                ".mac",
 670256                ".med",
 670257                ".mka",
 670258                ".mmf",
 670259                ".mod",
 670260                ".mogg",
 670261                ".mp2",
 670262                ".mp3",
 670263                ".mpa",
 670264                ".mpc",
 670265                ".mpp",
 670266                ".mp+",
 670267                ".msv",
 670268                ".nmf",
 670269                ".nsf",
 670270                ".nsv",
 670271                ".oga",
 670272                ".ogg",
 670273                ".okt",
 670274                ".opus",
 670275                ".pls",
 670276                ".ra",
 670277                ".rf64",
 670278                ".rm",
 670279                ".s3m",
 670280                ".sfx",
 670281                ".shn",
 670282                ".sid",
 670283                ".stm",
 670284                ".strm",
 670285                ".ult",
 670286                ".uni",
 670287                ".vox",
 670288                ".wav",
 670289                ".wma",
 670290                ".wv",
 670291                ".xm",
 670292                ".xsp",
 670293                ".ymf"
 670294            };
 295
 670296            MediaFlagDelimiters = new[]
 670297            {
 670298                '.'
 670299            };
 300
 670301            MediaForcedFlags = new[]
 670302            {
 670303                "foreign",
 670304                "forced"
 670305            };
 306
 670307            MediaDefaultFlags = new[]
 670308            {
 670309                "default"
 670310            };
 311
 670312            MediaHearingImpairedFlags = new[]
 670313            {
 670314                "cc",
 670315                "hi",
 670316                "sdh"
 670317            };
 318
 670319            EpisodeExpressions = new[]
 670320            {
 670321                // *** Begin Kodi Standard Naming
 670322                // <!-- foo.s01.e01, foo.s01_e01, S01E02 foo, S01 - E02 -->
 670323                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![Ss]([0-9]+)[][ ._-]*[Ee]([0-9]+))[^\\\/])*)?[Ss](?<s
 670324                {
 670325                    IsNamed = true
 670326                },
 670327                // <!-- foo.ep01, foo.EP_01 -->
 670328                new EpisodeExpression(@"[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$"),
 670329                // <!-- foo.E01., foo.e01. -->
 670330                new EpisodeExpression(@"[^\\/]*?()\.?[Ee]([0-9]+)\.([^\\/]*)$"),
 670331                new EpisodeExpression("(?<year>[0-9]{4})[._ -](?<month>[0-9]{2})[._ -](?<day>[0-9]{2})", true)
 670332                {
 670333                    DateTimeFormats = new[]
 670334                    {
 670335                        "yyyy.MM.dd",
 670336                        "yyyy-MM-dd",
 670337                        "yyyy_MM_dd",
 670338                        "yyyy MM dd"
 670339                    }
 670340                },
 670341                new EpisodeExpression("(?<day>[0-9]{2})[._ -](?<month>[0-9]{2})[._ -](?<year>[0-9]{4})", true)
 670342                {
 670343                    DateTimeFormats = new[]
 670344                    {
 670345                        "dd.MM.yyyy",
 670346                        "dd-MM-yyyy",
 670347                        "dd_MM_yyyy",
 670348                        "dd MM yyyy"
 670349                    }
 670350                },
 670351
 670352                // This isn't a Kodi naming rule, but the expression below causes false episode numbers for
 670353                // Title Season X Episode X naming schemes.
 670354                // "Series Season X Episode X - Title.avi", "Series S03 E09.avi", "s3 e9 - Title.avi"
 670355                new EpisodeExpression(@".*[\\\/]((?<seriesname>[^\\/]+?)\s)?[Ss](?:eason)?\s*(?<seasonnumber>[0-9]+)\s+[
 670356                {
 670357                    IsNamed = true
 670358                },
 670359
 670360                // Not a Kodi rule as well, but the expression below also causes false positives,
 670361                // so we make sure this one gets tested first.
 670362                // "Foo Bar 889"
 670363                new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>[0-9]{1,4})(-(?<endin
 670364                {
 670365                    IsNamed = true
 670366                },
 670367
 670368                new EpisodeExpression(@"[\\\/\._ \[\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\.[1-9])(?![0-9]))?)([^\\\/]*)$")
 670369                {
 670370                    SupportsAbsoluteEpisodeNumbers = true
 670371                },
 670372
 670373                // Not a Kodi rule as well, but below rule also causes false positives for triple-digit episode names
 670374                // [bar] Foo - 1 [baz] special case of below expression to prevent false positives with digits in the se
 670375                new EpisodeExpression(@".*[\\\/]?.*?(\[.*?\])+.*?(?<seriesname>[-\w\s]+?)[\s_]*-[\s_]*(?<epnumber>[0-9]+
 670376                {
 670377                    IsNamed = true
 670378                },
 670379
 670380                // /server/anything_102.mp4
 670381                // /server/james.corden.2017.04.20.anne.hathaway.720p.hdtv.x264-crooks.mkv
 670382                // /server/anything_1996.11.14.mp4
 670383                new EpisodeExpression(@"[\\/._ -](?<seriesname>(?![0-9]+[0-9][0-9])([^\\\/_])*)[\\\/._ -](?<seasonnumber
 670384                {
 670385                    IsOptimistic = true,
 670386                    IsNamed = true,
 670387                    SupportsAbsoluteEpisodeNumbers = false
 670388                },
 670389                new EpisodeExpression(@"[\/._ -]p(?:ar)?t[_. -]()([ivx]+|[0-9]+)([._ -][^\/]*)$")
 670390                {
 670391                    SupportsAbsoluteEpisodeNumbers = true
 670392                },
 670393
 670394                // *** End Kodi Standard Naming
 670395
 670396                // "Episode 16", "Episode 16 - Title"
 670397                new EpisodeExpression(@"[Ee]pisode (?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))?[^\\\/]*$")
 670398                {
 670399                    IsNamed = true
 670400                },
 670401
 670402                new EpisodeExpression(@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]+)[xX](?<epnumber>[0-9]+)[^\\\/]*$")
 670403                {
 670404                    IsNamed = true
 670405                },
 670406
 670407                new EpisodeExpression(@".*(\\|\/)[sS](?<seasonnumber>[0-9]+)[x,X]?[eE](?<epnumber>[0-9]+)[^\\\/]*$")
 670408                {
 670409                    IsNamed = true
 670410                },
 670411
 670412                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<sea
 670413                {
 670414                    IsNamed = true
 670415                },
 670416
 670417                new EpisodeExpression(@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epn
 670418                {
 670419                    IsNamed = true
 670420                },
 670421
 670422                // "01.avi"
 670423                new EpisodeExpression(@".*[\\\/](?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))*\.\w+$")
 670424                {
 670425                    IsOptimistic = true,
 670426                    IsNamed = true
 670427                },
 670428
 670429                // "1-12 episode title"
 670430                new EpisodeExpression("([0-9]+)-([0-9]+)"),
 670431
 670432                // "01 - blah.avi", "01-blah.avi"
 670433                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\s?-\s?[^\\\/]*
 670434                {
 670435                    IsOptimistic = true,
 670436                    IsNamed = true
 670437                },
 670438
 670439                // "01.blah.avi"
 670440                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\.[^\\\/]+$")
 670441                {
 670442                    IsOptimistic = true,
 670443                    IsNamed = true
 670444                },
 670445
 670446                // "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi",
 670447                new EpisodeExpression(@".*[\\\/][^\\\/]* - (?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\
 670448                {
 670449                    IsOptimistic = true,
 670450                    IsNamed = true
 670451                },
 670452
 670453                // "01 episode title.avi"
 670454                new EpisodeExpression(@"[Ss]eason[\._ ](?<seasonnumber>[0-9]+)[\\\/](?<epnumber>[0-9]{1,3})([^\\\/]*)$")
 670455                {
 670456                    IsOptimistic = true,
 670457                    IsNamed = true
 670458                },
 670459
 670460                // Series and season only expression
 670461                // "the show/season 1", "the show/s01"
 670462                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)\/[Ss](eason)?[\. _\-]*(?<seasonnumber>[0-9]+)")
 670463                {
 670464                    IsNamed = true
 670465                },
 670466
 670467                // Series and season only expression
 670468                // "the show S01", "the show season 1"
 670469                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)[\. _\-]+[sS](eason)?[\. _\-]*(?<seasonnumber>[0-9]
 670470                {
 670471                    IsNamed = true
 670472                },
 670473
 670474                // Anime style expression
 670475                // "[Group][Series Name][21][1080p][FLAC][HASH]"
 670476                // "[Group] Series Name [04][BDRIP]"
 670477                new EpisodeExpression(@"(?:\[(?:[^\]]+)\]\s*)?(?<seriesname>\[[^\]]+\]|[^[\]]+)\s*\[(?<epnumber>[0-9]+)\
 670478                {
 670479                    IsNamed = true
 670480                },
 670481            };
 482
 670483            VideoExtraRules = new[]
 670484            {
 670485                new ExtraRule(
 670486                    ExtraType.Trailer,
 670487                    ExtraRuleType.DirectoryName,
 670488                    "trailers",
 670489                    MediaType.Video),
 670490
 670491                new ExtraRule(
 670492                    ExtraType.ThemeVideo,
 670493                    ExtraRuleType.DirectoryName,
 670494                    "backdrops",
 670495                    MediaType.Video),
 670496
 670497                new ExtraRule(
 670498                    ExtraType.ThemeSong,
 670499                    ExtraRuleType.DirectoryName,
 670500                    "theme-music",
 670501                    MediaType.Audio),
 670502
 670503                new ExtraRule(
 670504                    ExtraType.BehindTheScenes,
 670505                    ExtraRuleType.DirectoryName,
 670506                    "behind the scenes",
 670507                    MediaType.Video),
 670508
 670509                new ExtraRule(
 670510                    ExtraType.DeletedScene,
 670511                    ExtraRuleType.DirectoryName,
 670512                    "deleted scenes",
 670513                    MediaType.Video),
 670514
 670515                new ExtraRule(
 670516                    ExtraType.Interview,
 670517                    ExtraRuleType.DirectoryName,
 670518                    "interviews",
 670519                    MediaType.Video),
 670520
 670521                new ExtraRule(
 670522                    ExtraType.Scene,
 670523                    ExtraRuleType.DirectoryName,
 670524                    "scenes",
 670525                    MediaType.Video),
 670526
 670527                new ExtraRule(
 670528                    ExtraType.Sample,
 670529                    ExtraRuleType.DirectoryName,
 670530                    "samples",
 670531                    MediaType.Video),
 670532
 670533                new ExtraRule(
 670534                    ExtraType.Short,
 670535                    ExtraRuleType.DirectoryName,
 670536                    "shorts",
 670537                    MediaType.Video),
 670538
 670539                new ExtraRule(
 670540                    ExtraType.Featurette,
 670541                    ExtraRuleType.DirectoryName,
 670542                    "featurettes",
 670543                    MediaType.Video),
 670544
 670545                new ExtraRule(
 670546                    ExtraType.Unknown,
 670547                    ExtraRuleType.DirectoryName,
 670548                    "extras",
 670549                    MediaType.Video),
 670550
 670551                new ExtraRule(
 670552                    ExtraType.Unknown,
 670553                    ExtraRuleType.DirectoryName,
 670554                    "extra",
 670555                    MediaType.Video),
 670556
 670557                new ExtraRule(
 670558                    ExtraType.Unknown,
 670559                    ExtraRuleType.DirectoryName,
 670560                    "other",
 670561                    MediaType.Video),
 670562
 670563                new ExtraRule(
 670564                    ExtraType.Clip,
 670565                    ExtraRuleType.DirectoryName,
 670566                    "clips",
 670567                    MediaType.Video),
 670568
 670569                new ExtraRule(
 670570                    ExtraType.Trailer,
 670571                    ExtraRuleType.Filename,
 670572                    "trailer",
 670573                    MediaType.Video),
 670574
 670575                new ExtraRule(
 670576                    ExtraType.Sample,
 670577                    ExtraRuleType.Filename,
 670578                    "sample",
 670579                    MediaType.Video),
 670580
 670581                new ExtraRule(
 670582                    ExtraType.ThemeSong,
 670583                    ExtraRuleType.Filename,
 670584                    "theme",
 670585                    MediaType.Audio),
 670586
 670587                new ExtraRule(
 670588                    ExtraType.Trailer,
 670589                    ExtraRuleType.Suffix,
 670590                    "-trailer",
 670591                    MediaType.Video),
 670592
 670593                new ExtraRule(
 670594                    ExtraType.Trailer,
 670595                    ExtraRuleType.Suffix,
 670596                    ".trailer",
 670597                    MediaType.Video),
 670598
 670599                new ExtraRule(
 670600                    ExtraType.Trailer,
 670601                    ExtraRuleType.Suffix,
 670602                    "_trailer",
 670603                    MediaType.Video),
 670604
 670605                new ExtraRule(
 670606                    ExtraType.Trailer,
 670607                    ExtraRuleType.Suffix,
 670608                    "- trailer",
 670609                    MediaType.Video),
 670610
 670611                new ExtraRule(
 670612                    ExtraType.Sample,
 670613                    ExtraRuleType.Suffix,
 670614                    "-sample",
 670615                    MediaType.Video),
 670616
 670617                new ExtraRule(
 670618                    ExtraType.Sample,
 670619                    ExtraRuleType.Suffix,
 670620                    ".sample",
 670621                    MediaType.Video),
 670622
 670623                new ExtraRule(
 670624                    ExtraType.Sample,
 670625                    ExtraRuleType.Suffix,
 670626                    "_sample",
 670627                    MediaType.Video),
 670628
 670629                new ExtraRule(
 670630                    ExtraType.Sample,
 670631                    ExtraRuleType.Suffix,
 670632                    "- sample",
 670633                    MediaType.Video),
 670634
 670635                new ExtraRule(
 670636                    ExtraType.Scene,
 670637                    ExtraRuleType.Suffix,
 670638                    "-scene",
 670639                    MediaType.Video),
 670640
 670641                new ExtraRule(
 670642                    ExtraType.Clip,
 670643                    ExtraRuleType.Suffix,
 670644                    "-clip",
 670645                    MediaType.Video),
 670646
 670647                new ExtraRule(
 670648                    ExtraType.Interview,
 670649                    ExtraRuleType.Suffix,
 670650                    "-interview",
 670651                    MediaType.Video),
 670652
 670653                new ExtraRule(
 670654                    ExtraType.BehindTheScenes,
 670655                    ExtraRuleType.Suffix,
 670656                    "-behindthescenes",
 670657                    MediaType.Video),
 670658
 670659                new ExtraRule(
 670660                    ExtraType.DeletedScene,
 670661                    ExtraRuleType.Suffix,
 670662                    "-deleted",
 670663                    MediaType.Video),
 670664
 670665                new ExtraRule(
 670666                    ExtraType.DeletedScene,
 670667                    ExtraRuleType.Suffix,
 670668                    "-deletedscene",
 670669                    MediaType.Video),
 670670
 670671                new ExtraRule(
 670672                    ExtraType.Featurette,
 670673                    ExtraRuleType.Suffix,
 670674                    "-featurette",
 670675                    MediaType.Video),
 670676
 670677                new ExtraRule(
 670678                    ExtraType.Short,
 670679                    ExtraRuleType.Suffix,
 670680                    "-short",
 670681                    MediaType.Video),
 670682
 670683                new ExtraRule(
 670684                    ExtraType.Unknown,
 670685                    ExtraRuleType.Suffix,
 670686                    "-extra",
 670687                    MediaType.Video),
 670688
 670689                new ExtraRule(
 670690                    ExtraType.Unknown,
 670691                    ExtraRuleType.Suffix,
 670692                    "-other",
 670693                    MediaType.Video)
 670694            };
 695
 670696            AllExtrasTypesFolderNames = VideoExtraRules
 670697                .Where(i => i.RuleType == ExtraRuleType.DirectoryName)
 670698                .ToDictionary(i => i.Token, i => i.ExtraType, StringComparer.OrdinalIgnoreCase);
 699
 670700            Format3DRules = new[]
 670701            {
 670702                // Kodi rules:
 670703                new Format3DRule(
 670704                    precedingToken: "3d",
 670705                    token: "hsbs"),
 670706
 670707                new Format3DRule(
 670708                    precedingToken: "3d",
 670709                    token: "sbs"),
 670710
 670711                new Format3DRule(
 670712                    precedingToken: "3d",
 670713                    token: "htab"),
 670714
 670715                new Format3DRule(
 670716                    precedingToken: "3d",
 670717                    token: "tab"),
 670718
 670719                 // Media Browser rules:
 670720                new Format3DRule("fsbs"),
 670721                new Format3DRule("hsbs"),
 670722                new Format3DRule("sbs"),
 670723                new Format3DRule("ftab"),
 670724                new Format3DRule("htab"),
 670725                new Format3DRule("tab"),
 670726                new Format3DRule("sbs3d"),
 670727                new Format3DRule("mvc")
 670728            };
 729
 670730            AudioBookPartsExpressions = new[]
 670731            {
 670732                // Detect specified chapters, like CH 01
 670733                @"ch(?:apter)?[\s_-]?(?<chapter>[0-9]+)",
 670734                // Detect specified parts, like Part 02
 670735                @"p(?:ar)?t[\s_-]?(?<part>[0-9]+)",
 670736                // Chapter is often beginning of filename
 670737                "^(?<chapter>[0-9]+)",
 670738                // Part if often ending of filename
 670739                "(?<!ch(?:apter) )(?<part>[0-9]+)$",
 670740                // Sometimes named as 0001_005 (chapter_part)
 670741                "(?<chapter>[0-9]+)_(?<part>[0-9]+)",
 670742                // Some audiobooks are ripped from cd's, and will be named by disk number.
 670743                @"dis(?:c|k)[\s_-]?(?<chapter>[0-9]+)"
 670744            };
 745
 670746            AudioBookNamesExpressions = new[]
 670747            {
 670748                // Detect year usually in brackets after name Batman (2020)
 670749                @"^(?<name>.+?)\s*\(\s*(?<year>[0-9]{4})\s*\)\s*$",
 670750                @"^\s*(?<name>[^ ].*?)\s*$"
 670751            };
 752
 670753            MultipleEpisodeExpressions = new[]
 670754            {
 670755                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endinge
 670756                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[xX][eE](?<endin
 670757                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )?[xXeE](?<endingepnumber>[
 670758                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})(-[xE]?[eE]?(?<endingepnumber>[0-9
 670759                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 670760                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 670761                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 670762                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 670763                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})((-| 
 670764                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})(-[xX
 670765            }.Select(i => new EpisodeExpression(i)
 670766            {
 670767                IsNamed = true
 670768            }).ToArray();
 769
 670770            Compile();
 670771        }
 772
 773        /// <summary>
 774        /// Gets or sets the folder name to extra types mapping.
 775        /// </summary>
 776        public Dictionary<string, ExtraType> AllExtrasTypesFolderNames { get; set; }
 777
 778        /// <summary>
 779        /// Gets or sets list of audio file extensions.
 780        /// </summary>
 781        public string[] AudioFileExtensions { get; set; }
 782
 783        /// <summary>
 784        /// Gets or sets list of external media flag delimiters.
 785        /// </summary>
 786        public char[] MediaFlagDelimiters { get; set; }
 787
 788        /// <summary>
 789        /// Gets or sets list of external media forced flags.
 790        /// </summary>
 791        public string[] MediaForcedFlags { get; set; }
 792
 793        /// <summary>
 794        /// Gets or sets list of external media default flags.
 795        /// </summary>
 796        public string[] MediaDefaultFlags { get; set; }
 797
 798        /// <summary>
 799        /// Gets or sets list of external media hearing impaired flags.
 800        /// </summary>
 801        public string[] MediaHearingImpairedFlags { get; set; }
 802
 803        /// <summary>
 804        /// Gets or sets list of album stacking prefixes.
 805        /// </summary>
 806        public string[] AlbumStackingPrefixes { get; set; }
 807
 808        /// <summary>
 809        /// Gets or sets list of artist subfolders.
 810        /// </summary>
 811        public string[] ArtistSubfolders { get; set; }
 812
 813        /// <summary>
 814        /// Gets or sets list of subtitle file extensions.
 815        /// </summary>
 816        public string[] SubtitleFileExtensions { get; set; }
 817
 818        /// <summary>
 819        /// Gets the list of lyric file extensions.
 820        /// </summary>
 821        public string[] LyricFileExtensions { get; }
 822
 823        /// <summary>
 824        /// Gets or sets list of episode regular expressions.
 825        /// </summary>
 826        public EpisodeExpression[] EpisodeExpressions { get; set; }
 827
 828        /// <summary>
 829        /// Gets or sets list of video file extensions.
 830        /// </summary>
 831        public string[] VideoFileExtensions { get; set; }
 832
 833        /// <summary>
 834        /// Gets or sets list of video stub file extensions.
 835        /// </summary>
 836        public string[] StubFileExtensions { get; set; }
 837
 838        /// <summary>
 839        /// Gets or sets list of raw audiobook parts regular expressions strings.
 840        /// </summary>
 841        public string[] AudioBookPartsExpressions { get; set; }
 842
 843        /// <summary>
 844        /// Gets or sets list of raw audiobook names regular expressions strings.
 845        /// </summary>
 846        public string[] AudioBookNamesExpressions { get; set; }
 847
 848        /// <summary>
 849        /// Gets or sets list of stub type rules.
 850        /// </summary>
 851        public StubTypeRule[] StubTypes { get; set; }
 852
 853        /// <summary>
 854        /// Gets or sets list of video flag delimiters.
 855        /// </summary>
 856        public char[] VideoFlagDelimiters { get; set; }
 857
 858        /// <summary>
 859        /// Gets or sets list of 3D Format rules.
 860        /// </summary>
 861        public Format3DRule[] Format3DRules { get; set; }
 862
 863        /// <summary>
 864        /// Gets the file stacking rules.
 865        /// </summary>
 866        public FileStackRule[] VideoFileStackingRules { get; }
 867
 868        /// <summary>
 869        /// Gets or sets list of raw clean DateTimes regular expressions strings.
 870        /// </summary>
 871        public string[] CleanDateTimes { get; set; }
 872
 873        /// <summary>
 874        /// Gets or sets list of raw clean strings regular expressions strings.
 875        /// </summary>
 876        public string[] CleanStrings { get; set; }
 877
 878        /// <summary>
 879        /// Gets or sets list of multi-episode regular expressions.
 880        /// </summary>
 881        public EpisodeExpression[] MultipleEpisodeExpressions { get; set; }
 882
 883        /// <summary>
 884        /// Gets or sets list of extra rules for videos.
 885        /// </summary>
 886        public ExtraRule[] VideoExtraRules { get; set; }
 887
 888        /// <summary>
 889        /// Gets list of clean datetime regular expressions.
 890        /// </summary>
 891        public Regex[] CleanDateTimeRegexes { get; private set; } = Array.Empty<Regex>();
 892
 893        /// <summary>
 894        /// Gets list of clean string regular expressions.
 895        /// </summary>
 896        public Regex[] CleanStringRegexes { get; private set; } = Array.Empty<Regex>();
 897
 898        /// <summary>
 899        /// Compiles raw regex strings into regexes.
 900        /// </summary>
 901        public void Compile()
 902        {
 671903            CleanDateTimeRegexes = CleanDateTimes.Select(Compile).ToArray();
 671904            CleanStringRegexes = CleanStrings.Select(Compile).ToArray();
 671905        }
 906
 907        private Regex Compile(string exp)
 908        {
 5368909            return new Regex(exp, RegexOptions.IgnoreCase | RegexOptions.Compiled);
 910        }
 911    }
 912}