< 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: 730
Uncovered lines: 0
Coverable lines: 730
Total lines: 913
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 =
 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 =
 67083            [
 67084                '(',
 67085                ')',
 67086                '-',
 67087                '.',
 67088                '_',
 67089                '[',
 67090                ']'
 67091            ];
 92
 67093            StubFileExtensions =
 67094            [
 67095                ".disc"
 67096            ];
 97
 67098            StubTypes =
 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 =
 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 =
 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 =
 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 =
 670164            [
 670165                ".ass",
 670166                ".mks",
 670167                ".sami",
 670168                ".smi",
 670169                ".srt",
 670170                ".ssa",
 670171                ".sub",
 670172                ".sup",
 670173                ".vtt",
 670174            ];
 175
 670176            LyricFileExtensions =
 670177            [
 670178                ".lrc",
 670179                ".elrc",
 670180                ".txt"
 670181            ];
 182
 670183            AlbumStackingPrefixes =
 670184            [
 670185                "cd",
 670186                "digital media",
 670187                "disc",
 670188                "disk",
 670189                "vol",
 670190                "volume",
 670191                "part",
 670192                "act"
 670193            ];
 194
 670195            ArtistSubfolders =
 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 =
 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                ".ec3",
 670245                ".far",
 670246                ".flac",
 670247                ".gdm",
 670248                ".gsm",
 670249                ".gym",
 670250                ".hps",
 670251                ".imf",
 670252                ".it",
 670253                ".m15",
 670254                ".m4a",
 670255                ".m4b",
 670256                ".mac",
 670257                ".med",
 670258                ".mka",
 670259                ".mmf",
 670260                ".mod",
 670261                ".mogg",
 670262                ".mp2",
 670263                ".mp3",
 670264                ".mpa",
 670265                ".mpc",
 670266                ".mpp",
 670267                ".mp+",
 670268                ".msv",
 670269                ".nmf",
 670270                ".nsf",
 670271                ".nsv",
 670272                ".oga",
 670273                ".ogg",
 670274                ".okt",
 670275                ".opus",
 670276                ".pls",
 670277                ".ra",
 670278                ".rf64",
 670279                ".rm",
 670280                ".s3m",
 670281                ".sfx",
 670282                ".shn",
 670283                ".sid",
 670284                ".stm",
 670285                ".strm",
 670286                ".ult",
 670287                ".uni",
 670288                ".vox",
 670289                ".wav",
 670290                ".wma",
 670291                ".wv",
 670292                ".xm",
 670293                ".xsp",
 670294                ".ymf"
 670295            ];
 296
 670297            MediaFlagDelimiters =
 670298            [
 670299                '.'
 670300            ];
 301
 670302            MediaForcedFlags =
 670303            [
 670304                "foreign",
 670305                "forced"
 670306            ];
 307
 670308            MediaDefaultFlags =
 670309            [
 670310                "default"
 670311            ];
 312
 670313            MediaHearingImpairedFlags =
 670314            [
 670315                "cc",
 670316                "hi",
 670317                "sdh"
 670318            ];
 319
 670320            EpisodeExpressions =
 670321            [
 670322                // *** Begin Kodi Standard Naming
 670323                // <!-- foo.s01.e01, foo.s01_e01, S01E02 foo, S01 - E02 -->
 670324                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![Ss]([0-9]+)[][ ._-]*[Ee]([0-9]+))[^\\\/])*)?[Ss](?<s
 670325                {
 670326                    IsNamed = true
 670327                },
 670328                // <!-- foo.ep01, foo.EP_01 -->
 670329                new EpisodeExpression(@"[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$"),
 670330                // <!-- foo.E01., foo.e01. -->
 670331                new EpisodeExpression(@"[^\\/]*?()\.?[Ee]([0-9]+)\.([^\\/]*)$"),
 670332                new EpisodeExpression("(?<year>[0-9]{4})[._ -](?<month>[0-9]{2})[._ -](?<day>[0-9]{2})", true)
 670333                {
 670334                    DateTimeFormats =
 670335                    [
 670336                        "yyyy.MM.dd",
 670337                        "yyyy-MM-dd",
 670338                        "yyyy_MM_dd",
 670339                        "yyyy MM dd"
 670340                    ]
 670341                },
 670342                new EpisodeExpression("(?<day>[0-9]{2})[._ -](?<month>[0-9]{2})[._ -](?<year>[0-9]{4})", true)
 670343                {
 670344                    DateTimeFormats =
 670345                    [
 670346                        "dd.MM.yyyy",
 670347                        "dd-MM-yyyy",
 670348                        "dd_MM_yyyy",
 670349                        "dd MM yyyy"
 670350                    ]
 670351                },
 670352
 670353                // This isn't a Kodi naming rule, but the expression below causes false episode numbers for
 670354                // Title Season X Episode X naming schemes.
 670355                // "Series Season X Episode X - Title.avi", "Series S03 E09.avi", "s3 e9 - Title.avi"
 670356                new EpisodeExpression(@".*[\\\/]((?<seriesname>[^\\/]+?)\s)?[Ss](?:eason)?\s*(?<seasonnumber>[0-9]+)\s+[
 670357                {
 670358                    IsNamed = true
 670359                },
 670360
 670361                // Not a Kodi rule as well, but the expression below also causes false positives,
 670362                // so we make sure this one gets tested first.
 670363                // "Foo Bar 889"
 670364                new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>[0-9]{1,4})(-(?<endin
 670365                {
 670366                    IsNamed = true
 670367                },
 670368
 670369                new EpisodeExpression(@"[\\\/\._ \[\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\.[1-9])(?![0-9]))?)([^\\\/]*)$")
 670370                {
 670371                    SupportsAbsoluteEpisodeNumbers = true
 670372                },
 670373
 670374                // Not a Kodi rule as well, but below rule also causes false positives for triple-digit episode names
 670375                // [bar] Foo - 1 [baz] special case of below expression to prevent false positives with digits in the se
 670376                new EpisodeExpression(@".*[\\\/]?.*?(\[.*?\])+.*?(?<seriesname>[-\w\s]+?)[\s_]*-[\s_]*(?<epnumber>[0-9]+
 670377                {
 670378                    IsNamed = true
 670379                },
 670380
 670381                // /server/anything_102.mp4
 670382                // /server/james.corden.2017.04.20.anne.hathaway.720p.hdtv.x264-crooks.mkv
 670383                // /server/anything_1996.11.14.mp4
 670384                new EpisodeExpression(@"[\\/._ -](?<seriesname>(?![0-9]+[0-9][0-9])([^\\\/_])*)[\\\/._ -](?<seasonnumber
 670385                {
 670386                    IsOptimistic = true,
 670387                    IsNamed = true,
 670388                    SupportsAbsoluteEpisodeNumbers = false
 670389                },
 670390                new EpisodeExpression(@"[\/._ -]p(?:ar)?t[_. -]()([ivx]+|[0-9]+)([._ -][^\/]*)$")
 670391                {
 670392                    SupportsAbsoluteEpisodeNumbers = true
 670393                },
 670394
 670395                // *** End Kodi Standard Naming
 670396
 670397                // "Episode 16", "Episode 16 - Title"
 670398                new EpisodeExpression(@"[Ee]pisode (?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))?[^\\\/]*$")
 670399                {
 670400                    IsNamed = true
 670401                },
 670402
 670403                new EpisodeExpression(@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]+)[xX](?<epnumber>[0-9]+)[^\\\/]*$")
 670404                {
 670405                    IsNamed = true
 670406                },
 670407
 670408                new EpisodeExpression(@".*(\\|\/)[sS](?<seasonnumber>[0-9]+)[x,X]?[eE](?<epnumber>[0-9]+)[^\\\/]*$")
 670409                {
 670410                    IsNamed = true
 670411                },
 670412
 670413                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<sea
 670414                {
 670415                    IsNamed = true
 670416                },
 670417
 670418                new EpisodeExpression(@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epn
 670419                {
 670420                    IsNamed = true
 670421                },
 670422
 670423                // "01.avi"
 670424                new EpisodeExpression(@".*[\\\/](?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))*\.\w+$")
 670425                {
 670426                    IsOptimistic = true,
 670427                    IsNamed = true
 670428                },
 670429
 670430                // "1-12 episode title"
 670431                new EpisodeExpression("([0-9]+)-([0-9]+)"),
 670432
 670433                // "01 - blah.avi", "01-blah.avi"
 670434                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\s?-\s?[^\\\/]*
 670435                {
 670436                    IsOptimistic = true,
 670437                    IsNamed = true
 670438                },
 670439
 670440                // "01.blah.avi"
 670441                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\.[^\\\/]+$")
 670442                {
 670443                    IsOptimistic = true,
 670444                    IsNamed = true
 670445                },
 670446
 670447                // "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi",
 670448                new EpisodeExpression(@".*[\\\/][^\\\/]* - (?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\
 670449                {
 670450                    IsOptimistic = true,
 670451                    IsNamed = true
 670452                },
 670453
 670454                // "01 episode title.avi"
 670455                new EpisodeExpression(@"[Ss]eason[\._ ](?<seasonnumber>[0-9]+)[\\\/](?<epnumber>[0-9]{1,3})([^\\\/]*)$")
 670456                {
 670457                    IsOptimistic = true,
 670458                    IsNamed = true
 670459                },
 670460
 670461                // Series and season only expression
 670462                // "the show/season 1", "the show/s01"
 670463                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)\/[Ss](eason)?[\. _\-]*(?<seasonnumber>[0-9]+)")
 670464                {
 670465                    IsNamed = true
 670466                },
 670467
 670468                // Series and season only expression
 670469                // "the show S01", "the show season 1"
 670470                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)[\. _\-]+[sS](eason)?[\. _\-]*(?<seasonnumber>[0-9]
 670471                {
 670472                    IsNamed = true
 670473                },
 670474
 670475                // Anime style expression
 670476                // "[Group][Series Name][21][1080p][FLAC][HASH]"
 670477                // "[Group] Series Name [04][BDRIP]"
 670478                new EpisodeExpression(@"(?:\[(?:[^\]]+)\]\s*)?(?<seriesname>\[[^\]]+\]|[^[\]]+)\s*\[(?<epnumber>[0-9]+)\
 670479                {
 670480                    IsNamed = true
 670481                },
 670482            ];
 483
 670484            VideoExtraRules =
 670485            [
 670486                new ExtraRule(
 670487                    ExtraType.Trailer,
 670488                    ExtraRuleType.DirectoryName,
 670489                    "trailers",
 670490                    MediaType.Video),
 670491
 670492                new ExtraRule(
 670493                    ExtraType.ThemeVideo,
 670494                    ExtraRuleType.DirectoryName,
 670495                    "backdrops",
 670496                    MediaType.Video),
 670497
 670498                new ExtraRule(
 670499                    ExtraType.ThemeSong,
 670500                    ExtraRuleType.DirectoryName,
 670501                    "theme-music",
 670502                    MediaType.Audio),
 670503
 670504                new ExtraRule(
 670505                    ExtraType.BehindTheScenes,
 670506                    ExtraRuleType.DirectoryName,
 670507                    "behind the scenes",
 670508                    MediaType.Video),
 670509
 670510                new ExtraRule(
 670511                    ExtraType.DeletedScene,
 670512                    ExtraRuleType.DirectoryName,
 670513                    "deleted scenes",
 670514                    MediaType.Video),
 670515
 670516                new ExtraRule(
 670517                    ExtraType.Interview,
 670518                    ExtraRuleType.DirectoryName,
 670519                    "interviews",
 670520                    MediaType.Video),
 670521
 670522                new ExtraRule(
 670523                    ExtraType.Scene,
 670524                    ExtraRuleType.DirectoryName,
 670525                    "scenes",
 670526                    MediaType.Video),
 670527
 670528                new ExtraRule(
 670529                    ExtraType.Sample,
 670530                    ExtraRuleType.DirectoryName,
 670531                    "samples",
 670532                    MediaType.Video),
 670533
 670534                new ExtraRule(
 670535                    ExtraType.Short,
 670536                    ExtraRuleType.DirectoryName,
 670537                    "shorts",
 670538                    MediaType.Video),
 670539
 670540                new ExtraRule(
 670541                    ExtraType.Featurette,
 670542                    ExtraRuleType.DirectoryName,
 670543                    "featurettes",
 670544                    MediaType.Video),
 670545
 670546                new ExtraRule(
 670547                    ExtraType.Unknown,
 670548                    ExtraRuleType.DirectoryName,
 670549                    "extras",
 670550                    MediaType.Video),
 670551
 670552                new ExtraRule(
 670553                    ExtraType.Unknown,
 670554                    ExtraRuleType.DirectoryName,
 670555                    "extra",
 670556                    MediaType.Video),
 670557
 670558                new ExtraRule(
 670559                    ExtraType.Unknown,
 670560                    ExtraRuleType.DirectoryName,
 670561                    "other",
 670562                    MediaType.Video),
 670563
 670564                new ExtraRule(
 670565                    ExtraType.Clip,
 670566                    ExtraRuleType.DirectoryName,
 670567                    "clips",
 670568                    MediaType.Video),
 670569
 670570                new ExtraRule(
 670571                    ExtraType.Trailer,
 670572                    ExtraRuleType.Filename,
 670573                    "trailer",
 670574                    MediaType.Video),
 670575
 670576                new ExtraRule(
 670577                    ExtraType.Sample,
 670578                    ExtraRuleType.Filename,
 670579                    "sample",
 670580                    MediaType.Video),
 670581
 670582                new ExtraRule(
 670583                    ExtraType.ThemeSong,
 670584                    ExtraRuleType.Filename,
 670585                    "theme",
 670586                    MediaType.Audio),
 670587
 670588                new ExtraRule(
 670589                    ExtraType.Trailer,
 670590                    ExtraRuleType.Suffix,
 670591                    "-trailer",
 670592                    MediaType.Video),
 670593
 670594                new ExtraRule(
 670595                    ExtraType.Trailer,
 670596                    ExtraRuleType.Suffix,
 670597                    ".trailer",
 670598                    MediaType.Video),
 670599
 670600                new ExtraRule(
 670601                    ExtraType.Trailer,
 670602                    ExtraRuleType.Suffix,
 670603                    "_trailer",
 670604                    MediaType.Video),
 670605
 670606                new ExtraRule(
 670607                    ExtraType.Trailer,
 670608                    ExtraRuleType.Suffix,
 670609                    "- trailer",
 670610                    MediaType.Video),
 670611
 670612                new ExtraRule(
 670613                    ExtraType.Sample,
 670614                    ExtraRuleType.Suffix,
 670615                    "-sample",
 670616                    MediaType.Video),
 670617
 670618                new ExtraRule(
 670619                    ExtraType.Sample,
 670620                    ExtraRuleType.Suffix,
 670621                    ".sample",
 670622                    MediaType.Video),
 670623
 670624                new ExtraRule(
 670625                    ExtraType.Sample,
 670626                    ExtraRuleType.Suffix,
 670627                    "_sample",
 670628                    MediaType.Video),
 670629
 670630                new ExtraRule(
 670631                    ExtraType.Sample,
 670632                    ExtraRuleType.Suffix,
 670633                    "- sample",
 670634                    MediaType.Video),
 670635
 670636                new ExtraRule(
 670637                    ExtraType.Scene,
 670638                    ExtraRuleType.Suffix,
 670639                    "-scene",
 670640                    MediaType.Video),
 670641
 670642                new ExtraRule(
 670643                    ExtraType.Clip,
 670644                    ExtraRuleType.Suffix,
 670645                    "-clip",
 670646                    MediaType.Video),
 670647
 670648                new ExtraRule(
 670649                    ExtraType.Interview,
 670650                    ExtraRuleType.Suffix,
 670651                    "-interview",
 670652                    MediaType.Video),
 670653
 670654                new ExtraRule(
 670655                    ExtraType.BehindTheScenes,
 670656                    ExtraRuleType.Suffix,
 670657                    "-behindthescenes",
 670658                    MediaType.Video),
 670659
 670660                new ExtraRule(
 670661                    ExtraType.DeletedScene,
 670662                    ExtraRuleType.Suffix,
 670663                    "-deleted",
 670664                    MediaType.Video),
 670665
 670666                new ExtraRule(
 670667                    ExtraType.DeletedScene,
 670668                    ExtraRuleType.Suffix,
 670669                    "-deletedscene",
 670670                    MediaType.Video),
 670671
 670672                new ExtraRule(
 670673                    ExtraType.Featurette,
 670674                    ExtraRuleType.Suffix,
 670675                    "-featurette",
 670676                    MediaType.Video),
 670677
 670678                new ExtraRule(
 670679                    ExtraType.Short,
 670680                    ExtraRuleType.Suffix,
 670681                    "-short",
 670682                    MediaType.Video),
 670683
 670684                new ExtraRule(
 670685                    ExtraType.Unknown,
 670686                    ExtraRuleType.Suffix,
 670687                    "-extra",
 670688                    MediaType.Video),
 670689
 670690                new ExtraRule(
 670691                    ExtraType.Unknown,
 670692                    ExtraRuleType.Suffix,
 670693                    "-other",
 670694                    MediaType.Video)
 670695            ];
 696
 670697            AllExtrasTypesFolderNames = VideoExtraRules
 670698                .Where(i => i.RuleType == ExtraRuleType.DirectoryName)
 670699                .ToDictionary(i => i.Token, i => i.ExtraType, StringComparer.OrdinalIgnoreCase);
 700
 670701            Format3DRules =
 670702            [
 670703                // Kodi rules:
 670704                new Format3DRule(
 670705                    precedingToken: "3d",
 670706                    token: "hsbs"),
 670707
 670708                new Format3DRule(
 670709                    precedingToken: "3d",
 670710                    token: "sbs"),
 670711
 670712                new Format3DRule(
 670713                    precedingToken: "3d",
 670714                    token: "htab"),
 670715
 670716                new Format3DRule(
 670717                    precedingToken: "3d",
 670718                    token: "tab"),
 670719
 670720                 // Media Browser rules:
 670721                new Format3DRule("fsbs"),
 670722                new Format3DRule("hsbs"),
 670723                new Format3DRule("sbs"),
 670724                new Format3DRule("ftab"),
 670725                new Format3DRule("htab"),
 670726                new Format3DRule("tab"),
 670727                new Format3DRule("sbs3d"),
 670728                new Format3DRule("mvc")
 670729            ];
 730
 670731            AudioBookPartsExpressions =
 670732            [
 670733                // Detect specified chapters, like CH 01
 670734                @"ch(?:apter)?[\s_-]?(?<chapter>[0-9]+)",
 670735                // Detect specified parts, like Part 02
 670736                @"p(?:ar)?t[\s_-]?(?<part>[0-9]+)",
 670737                // Chapter is often beginning of filename
 670738                "^(?<chapter>[0-9]+)",
 670739                // Part if often ending of filename
 670740                "(?<!ch(?:apter) )(?<part>[0-9]+)$",
 670741                // Sometimes named as 0001_005 (chapter_part)
 670742                "(?<chapter>[0-9]+)_(?<part>[0-9]+)",
 670743                // Some audiobooks are ripped from cd's, and will be named by disk number.
 670744                @"dis(?:c|k)[\s_-]?(?<chapter>[0-9]+)"
 670745            ];
 746
 670747            AudioBookNamesExpressions =
 670748            [
 670749                // Detect year usually in brackets after name Batman (2020)
 670750                @"^(?<name>.+?)\s*\(\s*(?<year>[0-9]{4})\s*\)\s*$",
 670751                @"^\s*(?<name>[^ ].*?)\s*$"
 670752            ];
 753
 670754            MultipleEpisodeExpressions = new[]
 670755            {
 670756                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endinge
 670757                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[xX][eE](?<endin
 670758                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )?[xXeE](?<endingepnumber>[
 670759                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})(-[xE]?[eE]?(?<endingepnumber>[0-9
 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]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 670764                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})((-| 
 670765                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})(-[xX
 670766            }.Select(i => new EpisodeExpression(i)
 670767            {
 670768                IsNamed = true
 670769            }).ToArray();
 770
 670771            Compile();
 670772        }
 773
 774        /// <summary>
 775        /// Gets or sets the folder name to extra types mapping.
 776        /// </summary>
 777        public Dictionary<string, ExtraType> AllExtrasTypesFolderNames { get; set; }
 778
 779        /// <summary>
 780        /// Gets or sets list of audio file extensions.
 781        /// </summary>
 782        public string[] AudioFileExtensions { get; set; }
 783
 784        /// <summary>
 785        /// Gets or sets list of external media flag delimiters.
 786        /// </summary>
 787        public char[] MediaFlagDelimiters { get; set; }
 788
 789        /// <summary>
 790        /// Gets or sets list of external media forced flags.
 791        /// </summary>
 792        public string[] MediaForcedFlags { get; set; }
 793
 794        /// <summary>
 795        /// Gets or sets list of external media default flags.
 796        /// </summary>
 797        public string[] MediaDefaultFlags { get; set; }
 798
 799        /// <summary>
 800        /// Gets or sets list of external media hearing impaired flags.
 801        /// </summary>
 802        public string[] MediaHearingImpairedFlags { get; set; }
 803
 804        /// <summary>
 805        /// Gets or sets list of album stacking prefixes.
 806        /// </summary>
 807        public string[] AlbumStackingPrefixes { get; set; }
 808
 809        /// <summary>
 810        /// Gets or sets list of artist subfolders.
 811        /// </summary>
 812        public string[] ArtistSubfolders { get; set; }
 813
 814        /// <summary>
 815        /// Gets or sets list of subtitle file extensions.
 816        /// </summary>
 817        public string[] SubtitleFileExtensions { get; set; }
 818
 819        /// <summary>
 820        /// Gets the list of lyric file extensions.
 821        /// </summary>
 822        public string[] LyricFileExtensions { get; }
 823
 824        /// <summary>
 825        /// Gets or sets list of episode regular expressions.
 826        /// </summary>
 827        public EpisodeExpression[] EpisodeExpressions { get; set; }
 828
 829        /// <summary>
 830        /// Gets or sets list of video file extensions.
 831        /// </summary>
 832        public string[] VideoFileExtensions { get; set; }
 833
 834        /// <summary>
 835        /// Gets or sets list of video stub file extensions.
 836        /// </summary>
 837        public string[] StubFileExtensions { get; set; }
 838
 839        /// <summary>
 840        /// Gets or sets list of raw audiobook parts regular expressions strings.
 841        /// </summary>
 842        public string[] AudioBookPartsExpressions { get; set; }
 843
 844        /// <summary>
 845        /// Gets or sets list of raw audiobook names regular expressions strings.
 846        /// </summary>
 847        public string[] AudioBookNamesExpressions { get; set; }
 848
 849        /// <summary>
 850        /// Gets or sets list of stub type rules.
 851        /// </summary>
 852        public StubTypeRule[] StubTypes { get; set; }
 853
 854        /// <summary>
 855        /// Gets or sets list of video flag delimiters.
 856        /// </summary>
 857        public char[] VideoFlagDelimiters { get; set; }
 858
 859        /// <summary>
 860        /// Gets or sets list of 3D Format rules.
 861        /// </summary>
 862        public Format3DRule[] Format3DRules { get; set; }
 863
 864        /// <summary>
 865        /// Gets the file stacking rules.
 866        /// </summary>
 867        public FileStackRule[] VideoFileStackingRules { get; }
 868
 869        /// <summary>
 870        /// Gets or sets list of raw clean DateTimes regular expressions strings.
 871        /// </summary>
 872        public string[] CleanDateTimes { get; set; }
 873
 874        /// <summary>
 875        /// Gets or sets list of raw clean strings regular expressions strings.
 876        /// </summary>
 877        public string[] CleanStrings { get; set; }
 878
 879        /// <summary>
 880        /// Gets or sets list of multi-episode regular expressions.
 881        /// </summary>
 882        public EpisodeExpression[] MultipleEpisodeExpressions { get; set; }
 883
 884        /// <summary>
 885        /// Gets or sets list of extra rules for videos.
 886        /// </summary>
 887        public ExtraRule[] VideoExtraRules { get; set; }
 888
 889        /// <summary>
 890        /// Gets list of clean datetime regular expressions.
 891        /// </summary>
 892        public Regex[] CleanDateTimeRegexes { get; private set; } = [];
 893
 894        /// <summary>
 895        /// Gets list of clean string regular expressions.
 896        /// </summary>
 897        public Regex[] CleanStringRegexes { get; private set; } = [];
 898
 899        /// <summary>
 900        /// Compiles raw regex strings into regexes.
 901        /// </summary>
 902        public void Compile()
 903        {
 671904            CleanDateTimeRegexes = CleanDateTimes.Select(Compile).ToArray();
 671905            CleanStringRegexes = CleanStrings.Select(Compile).ToArray();
 671906        }
 907
 908        private Regex Compile(string exp)
 909        {
 5368910            return new Regex(exp, RegexOptions.IgnoreCase | RegexOptions.Compiled);
 911        }
 912    }
 913}