< 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: 741
Uncovered lines: 0
Coverable lines: 741
Total lines: 924
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 4/15/2026 - 12:14:34 AM Line coverage: 100% (731/731) Total lines: 9145/5/2026 - 12:15:44 AM Line coverage: 100% (739/739) Total lines: 9227/26/2026 - 12:17:51 AM Line coverage: 100% (741/741) Total lines: 924

Coverage delta

Coverage delta 1 -1

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        {
 74124            VideoFileExtensions =
 74125            [
 74126                ".001",
 74127                ".3g2",
 74128                ".3gp",
 74129                ".amv",
 74130                ".asf",
 74131                ".asx",
 74132                ".avi",
 74133                ".bin",
 74134                ".bivx",
 74135                ".divx",
 74136                ".dv",
 74137                ".dvr-ms",
 74138                ".f4v",
 74139                ".fli",
 74140                ".flv",
 74141                ".ifo",
 74142                ".img",
 74143                ".iso",
 74144                ".m2t",
 74145                ".m2ts",
 74146                ".m2v",
 74147                ".m4v",
 74148                ".mkv",
 74149                ".mk3d",
 74150                ".mov",
 74151                ".mp4",
 74152                ".mpe",
 74153                ".mpeg",
 74154                ".mpg",
 74155                ".mts",
 74156                ".mxf",
 74157                ".nrg",
 74158                ".nsv",
 74159                ".nuv",
 74160                ".ogm",
 74161                ".ogv",
 74162                ".pva",
 74163                ".qt",
 74164                ".rec",
 74165                ".rm",
 74166                ".rmvb",
 74167                ".strm",
 74168                ".svq3",
 74169                ".tp",
 74170                ".ts",
 74171                ".ty",
 74172                ".viv",
 74173                ".vob",
 74174                ".vp3",
 74175                ".webm",
 74176                ".wmv",
 74177                ".wtv",
 74178                ".xvid"
 74179            ];
 80
 74181            VideoFlagDelimiters =
 74182            [
 74183                '(',
 74184                ')',
 74185                '-',
 74186                '.',
 74187                '_',
 74188                '[',
 74189                ']'
 74190            ];
 91
 74192            StubFileExtensions =
 74193            [
 74194                ".disc"
 74195            ];
 96
 74197            StubTypes =
 74198            [
 74199                new StubTypeRule(
 741100                    stubType: "dvd",
 741101                    token: "dvd"),
 741102
 741103                new StubTypeRule(
 741104                    stubType: "hddvd",
 741105                    token: "hddvd"),
 741106
 741107                new StubTypeRule(
 741108                    stubType: "bluray",
 741109                    token: "bluray"),
 741110
 741111                new StubTypeRule(
 741112                    stubType: "bluray",
 741113                    token: "brrip"),
 741114
 741115                new StubTypeRule(
 741116                    stubType: "bluray",
 741117                    token: "bd25"),
 741118
 741119                new StubTypeRule(
 741120                    stubType: "bluray",
 741121                    token: "bd50"),
 741122
 741123                new StubTypeRule(
 741124                    stubType: "vhs",
 741125                    token: "vhs"),
 741126
 741127                new StubTypeRule(
 741128                    stubType: "tv",
 741129                    token: "HDTV"),
 741130
 741131                new StubTypeRule(
 741132                    stubType: "tv",
 741133                    token: "PDTV"),
 741134
 741135                new StubTypeRule(
 741136                    stubType: "tv",
 741137                    token: "DSR")
 741138            ];
 139
 741140            VideoFileStackingRules =
 741141            [
 741142                new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])
 741143                new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])
 741144            ];
 145
 741146            CleanDateTimes =
 741147            [
 741148                @"(.+[^_\,\.\(\)\[\]\-])[_\.\(\)\[\]\-](19[0-9]{2}|20[0-9]{2})(?![0-9]+|\W[0-9]{2}\W[0-9]{2})([ _\,\.\(\
 741149                @"(.+[^_\,\.\(\)\[\]\-])[ _\.\(\)\[\]\-]+(19[0-9]{2}|20[0-9]{2})(?![0-9]+|\W[0-9]{2}\W[0-9]{2})([ _\,\.\
 741150            ];
 151
 741152            CleanStrings =
 741153            [
 741154                @"^\s*(?<cleaned>.+?)[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|d
 741155                @"^\s*(?<cleaned>.+?)((\s*\[[^\]]+\]\s*)+)(\.[^\s]+)?$",
 741156                @"^\s*(?<cleaned>.+?)\WE[0-9]+(-|~)E?[0-9]+(\W|$)",
 741157                @"^\s*\[[^\]]+\](?!\.\w+$)\s*(?<cleaned>.+)",
 741158                @"^\s*(?<cleaned>.+?)\s+-\s+[0-9]+\s*$",
 741159                @"^\s*(?<cleaned>.+?)(([-._ ](trailer|sample))|-(scene|clip|behindthescenes|deleted|deletedscene|feature
 741160            ];
 161
 741162            SubtitleFileExtensions =
 741163            [
 741164                ".ass",
 741165                ".mks",
 741166                ".sami",
 741167                ".smi",
 741168                ".srt",
 741169                ".ssa",
 741170                ".sub",
 741171                ".sup",
 741172                ".vtt",
 741173            ];
 174
 741175            LyricFileExtensions =
 741176            [
 741177                ".lrc",
 741178                ".elrc",
 741179                ".txt"
 741180            ];
 181
 741182            AlbumStackingPrefixes =
 741183            [
 741184                "cd",
 741185                "digital media",
 741186                "disc",
 741187                "disk",
 741188                "vol",
 741189                "volume",
 741190                "part",
 741191                "act"
 741192            ];
 193
 741194            ArtistSubfolders =
 741195            [
 741196                "albums",
 741197                "broadcasts",
 741198                "bootlegs",
 741199                "compilations",
 741200                "dj-mixes",
 741201                "eps",
 741202                "live",
 741203                "mixtapes",
 741204                "others",
 741205                "remixes",
 741206                "singles",
 741207                "soundtracks",
 741208                "spokenwords",
 741209                "streets"
 741210            ];
 211
 741212            AudioFileExtensions =
 741213            [
 741214                ".669",
 741215                ".3gp",
 741216                ".aa",
 741217                ".aac",
 741218                ".aax",
 741219                ".ac3",
 741220                ".act",
 741221                ".adp",
 741222                ".adplug",
 741223                ".adx",
 741224                ".afc",
 741225                ".amf",
 741226                ".aif",
 741227                ".aifc",
 741228                ".aiff",
 741229                ".alac",
 741230                ".amr",
 741231                ".ape",
 741232                ".ast",
 741233                ".au",
 741234                ".awb",
 741235                ".cda",
 741236                ".cue",
 741237                ".dmf",
 741238                ".dsf",
 741239                ".dsm",
 741240                ".dsp",
 741241                ".dts",
 741242                ".dvf",
 741243                ".eac3",
 741244                ".ec3",
 741245                ".far",
 741246                ".flac",
 741247                ".gdm",
 741248                ".gsm",
 741249                ".gym",
 741250                ".hps",
 741251                ".imf",
 741252                ".it",
 741253                ".m15",
 741254                ".m4a",
 741255                ".m4b",
 741256                ".mac",
 741257                ".med",
 741258                ".mka",
 741259                ".mmf",
 741260                ".mod",
 741261                ".mogg",
 741262                ".mp2",
 741263                ".mp3",
 741264                ".mpa",
 741265                ".mpc",
 741266                ".mpp",
 741267                ".mp+",
 741268                ".msv",
 741269                ".nmf",
 741270                ".nsf",
 741271                ".nsv",
 741272                ".oga",
 741273                ".ogg",
 741274                ".okt",
 741275                ".opus",
 741276                ".pls",
 741277                ".ra",
 741278                ".rf64",
 741279                ".rm",
 741280                ".s3m",
 741281                ".sfx",
 741282                ".shn",
 741283                ".sid",
 741284                ".stm",
 741285                ".strm",
 741286                ".ult",
 741287                ".uni",
 741288                ".vox",
 741289                ".wav",
 741290                ".wma",
 741291                ".wv",
 741292                ".xm",
 741293                ".xsp",
 741294                ".ymf"
 741295            ];
 296
 741297            MediaFlagDelimiters =
 741298            [
 741299                '.'
 741300            ];
 301
 741302            MediaForcedFlags =
 741303            [
 741304                "foreign",
 741305                "forced"
 741306            ];
 307
 741308            MediaDefaultFlags =
 741309            [
 741310                "default"
 741311            ];
 312
 741313            MediaHearingImpairedFlags =
 741314            [
 741315                "cc",
 741316                "hi",
 741317                "sdh"
 741318            ];
 319
 741320            EpisodeExpressions =
 741321            [
 741322                // *** Begin Kodi Standard Naming
 741323                // <!-- foo.s01.e01, foo.s01_e01, S01E02 foo, S01 - E02 -->
 741324                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![Ss]([0-9]+)[][ ._-]*[Ee]([0-9]+))[^\\\/])*)?[Ss](?<s
 741325                {
 741326                    IsNamed = true
 741327                },
 741328                // <!-- foo.ep01, foo.EP_01 -->
 741329                new EpisodeExpression(@"[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$"),
 741330                // <!-- foo.E01., foo.e01. -->
 741331                new EpisodeExpression(@"[^\\/]*?()\.?[Ee]([0-9]+)\.([^\\/]*)$"),
 741332                new EpisodeExpression("(?<year>[0-9]{4})[._ -](?<month>[0-9]{2})[._ -](?<day>[0-9]{2})", true)
 741333                {
 741334                    DateTimeFormats =
 741335                    [
 741336                        "yyyy.MM.dd",
 741337                        "yyyy-MM-dd",
 741338                        "yyyy_MM_dd",
 741339                        "yyyy MM dd"
 741340                    ]
 741341                },
 741342                new EpisodeExpression("(?<day>[0-9]{2})[._ -](?<month>[0-9]{2})[._ -](?<year>[0-9]{4})", true)
 741343                {
 741344                    DateTimeFormats =
 741345                    [
 741346                        "dd.MM.yyyy",
 741347                        "dd-MM-yyyy",
 741348                        "dd_MM_yyyy",
 741349                        "dd MM yyyy"
 741350                    ]
 741351                },
 741352
 741353                // This isn't a Kodi naming rule, but the expression below causes false episode numbers for
 741354                // Title Season X Episode X naming schemes.
 741355                // "Series Season X Episode X - Title.avi", "Series S03 E09.avi", "s3 e9 - Title.avi"
 741356                new EpisodeExpression(@".*[\\\/]((?<seriesname>[^\\/]+?)\s)?[Ss](?:eason)?\s*(?<seasonnumber>[0-9]+)\s+[
 741357                {
 741358                    IsNamed = true
 741359                },
 741360
 741361                // Not a Kodi rule as well, but the expression below also causes false positives,
 741362                // so we make sure this one gets tested first.
 741363                // "Foo Bar 889"
 741364                // Names carrying an SxxEyy marker are excluded because the Kodi expression above already covers them.
 741365                // Without that guard this expression reads digits out of the title instead, turning
 741366                // "S01E01 1-23-45 [Bluray-1080p]" into episodes 1 through 45.
 741367                new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?![^\\\/]*[Ss][0-9]+[][ ._-]*[Ee][0-9]+)(?<seriesname>[\w
 741368                {
 741369                    IsNamed = true
 741370                },
 741371
 741372                new EpisodeExpression(@"[\\\/\._ \[\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\.[1-9])(?![0-9]))?)([^\\\/]*)$")
 741373                {
 741374                    SupportsAbsoluteEpisodeNumbers = true
 741375                },
 741376
 741377                // Not a Kodi rule as well, but below rule also causes false positives for triple-digit episode names
 741378                // [bar] Foo - 1 [baz] special case of below expression to prevent false positives with digits in the se
 741379                new EpisodeExpression(@".*[\\\/]?.*?(\[.*?\])+.*?(?<seriesname>[-\w\s]+?)[\s_]*-[\s_]*(?<epnumber>[0-9]+
 741380                {
 741381                    IsNamed = true
 741382                },
 741383
 741384                // "Name - 101.mkv", "Name - 101 [720p].mkv", "Name - 101 (2020).mkv"
 741385                // Handles absolute episode numbers with hyphen delimiter (common in anime)
 741386                // Without brackets (bracketed version handled above)
 741387                new EpisodeExpression(@".*[\\\/](?<seriesname>[^\\\/]+?)[\s_]+-[\s_]+(?<epnumber>[0-9]+)[\s_]*(?:\[.*?\]
 741388                {
 741389                    IsNamed = true
 741390                },
 741391
 741392                // /server/anything_102.mp4
 741393                // /server/james.corden.2017.04.20.anne.hathaway.720p.hdtv.x264-crooks.mkv
 741394                // /server/anything_1996.11.14.mp4
 741395                new EpisodeExpression(@"[\\/._ -](?<seriesname>(?![0-9]+[0-9][0-9])([^\\\/_])*)[\\\/._ -](?<seasonnumber
 741396                {
 741397                    IsOptimistic = true,
 741398                    IsNamed = true,
 741399                    SupportsAbsoluteEpisodeNumbers = false
 741400                },
 741401                new EpisodeExpression(@"[\/._ -]p(?:ar)?t[_. -]()([ivx]+|[0-9]+)([._ -][^\/]*)$")
 741402                {
 741403                    SupportsAbsoluteEpisodeNumbers = true
 741404                },
 741405
 741406                // *** End Kodi Standard Naming
 741407
 741408                // "Episode 16", "Episode 16 - Title"
 741409                new EpisodeExpression(@"[Ee]pisode (?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))?[^\\\/]*$")
 741410                {
 741411                    IsNamed = true
 741412                },
 741413
 741414                new EpisodeExpression(@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]+)[xX](?<epnumber>[0-9]+)[^\\\/]*$")
 741415                {
 741416                    IsNamed = true
 741417                },
 741418
 741419                new EpisodeExpression(@".*(\\|\/)[sS](?<seasonnumber>[0-9]+)[x,X]?[eE](?<epnumber>[0-9]+)[^\\\/]*$")
 741420                {
 741421                    IsNamed = true
 741422                },
 741423
 741424                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<sea
 741425                {
 741426                    IsNamed = true
 741427                },
 741428
 741429                new EpisodeExpression(@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epn
 741430                {
 741431                    IsNamed = true
 741432                },
 741433
 741434                // "01.avi"
 741435                new EpisodeExpression(@".*[\\\/](?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))*\.\w+$")
 741436                {
 741437                    IsOptimistic = true,
 741438                    IsNamed = true
 741439                },
 741440
 741441                // "1-12 episode title"
 741442                new EpisodeExpression("([0-9]+)-([0-9]+)"),
 741443
 741444                // "01 - blah.avi", "01-blah.avi"
 741445                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\s?-\s?[^\\\/]*
 741446                {
 741447                    IsOptimistic = true,
 741448                    IsNamed = true
 741449                },
 741450
 741451                // "01.blah.avi"
 741452                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\.[^\\\/]+$")
 741453                {
 741454                    IsOptimistic = true,
 741455                    IsNamed = true
 741456                },
 741457
 741458                // "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi",
 741459                new EpisodeExpression(@".*[\\\/][^\\\/]* - (?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\
 741460                {
 741461                    IsOptimistic = true,
 741462                    IsNamed = true
 741463                },
 741464
 741465                // "01 episode title.avi"
 741466                new EpisodeExpression(@"[Ss]eason[\._ ](?<seasonnumber>[0-9]+)[\\\/](?<epnumber>[0-9]{1,3})([^\\\/]*)$")
 741467                {
 741468                    IsOptimistic = true,
 741469                    IsNamed = true
 741470                },
 741471
 741472                // Series and season only expression
 741473                // "the show/season 1", "the show/s01"
 741474                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)\/[Ss](eason)?[\. _\-]*(?<seasonnumber>[0-9]+)")
 741475                {
 741476                    IsNamed = true
 741477                },
 741478
 741479                // Series and season only expression
 741480                // "the show S01", "the show season 1"
 741481                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)[\. _\-]+[sS](eason)?[\. _\-]*(?<seasonnumber>[0-9]
 741482                {
 741483                    IsNamed = true
 741484                },
 741485
 741486                // Anime style expression
 741487                // "[Group][Series Name][21][1080p][FLAC][HASH]"
 741488                // "[Group] Series Name [04][BDRIP]"
 741489                new EpisodeExpression(@"(?:\[(?:[^\]]+)\]\s*)?(?<seriesname>\[[^\]]+\]|[^[\]]+)\s*\[(?<epnumber>[0-9]+)\
 741490                {
 741491                    IsNamed = true
 741492                },
 741493            ];
 494
 741495            VideoExtraRules =
 741496            [
 741497                new ExtraRule(
 741498                    ExtraType.Trailer,
 741499                    ExtraRuleType.DirectoryName,
 741500                    "trailers",
 741501                    MediaType.Video),
 741502
 741503                new ExtraRule(
 741504                    ExtraType.ThemeVideo,
 741505                    ExtraRuleType.DirectoryName,
 741506                    "backdrops",
 741507                    MediaType.Video),
 741508
 741509                new ExtraRule(
 741510                    ExtraType.ThemeSong,
 741511                    ExtraRuleType.DirectoryName,
 741512                    "theme-music",
 741513                    MediaType.Audio),
 741514
 741515                new ExtraRule(
 741516                    ExtraType.BehindTheScenes,
 741517                    ExtraRuleType.DirectoryName,
 741518                    "behind the scenes",
 741519                    MediaType.Video),
 741520
 741521                new ExtraRule(
 741522                    ExtraType.DeletedScene,
 741523                    ExtraRuleType.DirectoryName,
 741524                    "deleted scenes",
 741525                    MediaType.Video),
 741526
 741527                new ExtraRule(
 741528                    ExtraType.Interview,
 741529                    ExtraRuleType.DirectoryName,
 741530                    "interviews",
 741531                    MediaType.Video),
 741532
 741533                new ExtraRule(
 741534                    ExtraType.Scene,
 741535                    ExtraRuleType.DirectoryName,
 741536                    "scenes",
 741537                    MediaType.Video),
 741538
 741539                new ExtraRule(
 741540                    ExtraType.Sample,
 741541                    ExtraRuleType.DirectoryName,
 741542                    "samples",
 741543                    MediaType.Video),
 741544
 741545                new ExtraRule(
 741546                    ExtraType.Short,
 741547                    ExtraRuleType.DirectoryName,
 741548                    "shorts",
 741549                    MediaType.Video),
 741550
 741551                new ExtraRule(
 741552                    ExtraType.Featurette,
 741553                    ExtraRuleType.DirectoryName,
 741554                    "featurettes",
 741555                    MediaType.Video),
 741556
 741557                new ExtraRule(
 741558                    ExtraType.Unknown,
 741559                    ExtraRuleType.DirectoryName,
 741560                    "extras",
 741561                    MediaType.Video),
 741562
 741563                new ExtraRule(
 741564                    ExtraType.Unknown,
 741565                    ExtraRuleType.DirectoryName,
 741566                    "extra",
 741567                    MediaType.Video),
 741568
 741569                new ExtraRule(
 741570                    ExtraType.Unknown,
 741571                    ExtraRuleType.DirectoryName,
 741572                    "other",
 741573                    MediaType.Video),
 741574
 741575                new ExtraRule(
 741576                    ExtraType.Clip,
 741577                    ExtraRuleType.DirectoryName,
 741578                    "clips",
 741579                    MediaType.Video),
 741580
 741581                new ExtraRule(
 741582                    ExtraType.Trailer,
 741583                    ExtraRuleType.Filename,
 741584                    "trailer",
 741585                    MediaType.Video),
 741586
 741587                new ExtraRule(
 741588                    ExtraType.Sample,
 741589                    ExtraRuleType.Filename,
 741590                    "sample",
 741591                    MediaType.Video),
 741592
 741593                new ExtraRule(
 741594                    ExtraType.ThemeSong,
 741595                    ExtraRuleType.Filename,
 741596                    "theme",
 741597                    MediaType.Audio),
 741598
 741599                new ExtraRule(
 741600                    ExtraType.Trailer,
 741601                    ExtraRuleType.Suffix,
 741602                    "-trailer",
 741603                    MediaType.Video),
 741604
 741605                new ExtraRule(
 741606                    ExtraType.Trailer,
 741607                    ExtraRuleType.Suffix,
 741608                    ".trailer",
 741609                    MediaType.Video),
 741610
 741611                new ExtraRule(
 741612                    ExtraType.Trailer,
 741613                    ExtraRuleType.Suffix,
 741614                    "_trailer",
 741615                    MediaType.Video),
 741616
 741617                new ExtraRule(
 741618                    ExtraType.Trailer,
 741619                    ExtraRuleType.Suffix,
 741620                    "- trailer",
 741621                    MediaType.Video),
 741622
 741623                new ExtraRule(
 741624                    ExtraType.Sample,
 741625                    ExtraRuleType.Suffix,
 741626                    "-sample",
 741627                    MediaType.Video),
 741628
 741629                new ExtraRule(
 741630                    ExtraType.Sample,
 741631                    ExtraRuleType.Suffix,
 741632                    ".sample",
 741633                    MediaType.Video),
 741634
 741635                new ExtraRule(
 741636                    ExtraType.Sample,
 741637                    ExtraRuleType.Suffix,
 741638                    "_sample",
 741639                    MediaType.Video),
 741640
 741641                new ExtraRule(
 741642                    ExtraType.Sample,
 741643                    ExtraRuleType.Suffix,
 741644                    "- sample",
 741645                    MediaType.Video),
 741646
 741647                new ExtraRule(
 741648                    ExtraType.Scene,
 741649                    ExtraRuleType.Suffix,
 741650                    "-scene",
 741651                    MediaType.Video),
 741652
 741653                new ExtraRule(
 741654                    ExtraType.Clip,
 741655                    ExtraRuleType.Suffix,
 741656                    "-clip",
 741657                    MediaType.Video),
 741658
 741659                new ExtraRule(
 741660                    ExtraType.Interview,
 741661                    ExtraRuleType.Suffix,
 741662                    "-interview",
 741663                    MediaType.Video),
 741664
 741665                new ExtraRule(
 741666                    ExtraType.BehindTheScenes,
 741667                    ExtraRuleType.Suffix,
 741668                    "-behindthescenes",
 741669                    MediaType.Video),
 741670
 741671                new ExtraRule(
 741672                    ExtraType.DeletedScene,
 741673                    ExtraRuleType.Suffix,
 741674                    "-deleted",
 741675                    MediaType.Video),
 741676
 741677                new ExtraRule(
 741678                    ExtraType.DeletedScene,
 741679                    ExtraRuleType.Suffix,
 741680                    "-deletedscene",
 741681                    MediaType.Video),
 741682
 741683                new ExtraRule(
 741684                    ExtraType.Featurette,
 741685                    ExtraRuleType.Suffix,
 741686                    "-featurette",
 741687                    MediaType.Video),
 741688
 741689                new ExtraRule(
 741690                    ExtraType.Short,
 741691                    ExtraRuleType.Suffix,
 741692                    "-short",
 741693                    MediaType.Video),
 741694
 741695                new ExtraRule(
 741696                    ExtraType.Unknown,
 741697                    ExtraRuleType.Suffix,
 741698                    "-extra",
 741699                    MediaType.Video),
 741700
 741701                new ExtraRule(
 741702                    ExtraType.Unknown,
 741703                    ExtraRuleType.Suffix,
 741704                    "-other",
 741705                    MediaType.Video)
 741706            ];
 707
 741708            AllExtrasTypesFolderNames = VideoExtraRules
 741709                .Where(i => i.RuleType == ExtraRuleType.DirectoryName)
 741710                .ToDictionary(i => i.Token, i => i.ExtraType, StringComparer.OrdinalIgnoreCase);
 711
 741712            Format3DRules =
 741713            [
 741714                // Kodi rules:
 741715                new Format3DRule(
 741716                    precedingToken: "3d",
 741717                    token: "hsbs"),
 741718
 741719                new Format3DRule(
 741720                    precedingToken: "3d",
 741721                    token: "sbs"),
 741722
 741723                new Format3DRule(
 741724                    precedingToken: "3d",
 741725                    token: "htab"),
 741726
 741727                new Format3DRule(
 741728                    precedingToken: "3d",
 741729                    token: "tab"),
 741730
 741731                 // Media Browser rules:
 741732                new Format3DRule("fsbs"),
 741733                new Format3DRule("hsbs"),
 741734                new Format3DRule("sbs"),
 741735                new Format3DRule("ftab"),
 741736                new Format3DRule("htab"),
 741737                new Format3DRule("tab"),
 741738                new Format3DRule("sbs3d"),
 741739                new Format3DRule("mvc")
 741740            ];
 741
 741742            AudioBookPartsExpressions =
 741743            [
 741744                // Detect specified chapters, like CH 01
 741745                @"ch(?:apter)?[\s_-]?(?<chapter>[0-9]+)",
 741746                // Detect specified parts, like Part 02
 741747                @"p(?:ar)?t[\s_-]?(?<part>[0-9]+)",
 741748                // Chapter is often beginning of filename
 741749                "^(?<chapter>[0-9]+)",
 741750                // Part if often ending of filename
 741751                "(?<!ch(?:apter) )(?<part>[0-9]+)$",
 741752                // Sometimes named as 0001_005 (chapter_part)
 741753                "(?<chapter>[0-9]+)_(?<part>[0-9]+)",
 741754                // Some audiobooks are ripped from cd's, and will be named by disk number.
 741755                @"dis(?:c|k)[\s_-]?(?<chapter>[0-9]+)"
 741756            ];
 757
 741758            AudioBookNamesExpressions =
 741759            [
 741760                // Detect year usually in brackets after name Batman (2020)
 741761                @"^(?<name>.+?)\s*\(\s*(?<year>[0-9]{4})\s*\)\s*$",
 741762                @"^\s*(?<name>[^ ].*?)\s*$"
 741763            ];
 764
 741765            MultipleEpisodeExpressions = new[]
 741766            {
 741767                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endinge
 741768                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[xX][eE](?<endin
 741769                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )?[xXeE](?<endingepnumber>[
 741770                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})(-[xE]?[eE]?(?<endingepnumber>[0-9
 741771                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 741772                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 741773                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 741774                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 741775                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})((-| 
 741776                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})(-[xX
 741777            }.Select(i => new EpisodeExpression(i)
 741778            {
 741779                IsNamed = true
 741780            }).ToArray();
 781
 741782            Compile();
 741783        }
 784
 785        /// <summary>
 786        /// Gets or sets the folder name to extra types mapping.
 787        /// </summary>
 788        public Dictionary<string, ExtraType> AllExtrasTypesFolderNames { get; set; }
 789
 790        /// <summary>
 791        /// Gets or sets list of audio file extensions.
 792        /// </summary>
 793        public string[] AudioFileExtensions { get; set; }
 794
 795        /// <summary>
 796        /// Gets or sets list of external media flag delimiters.
 797        /// </summary>
 798        public char[] MediaFlagDelimiters { get; set; }
 799
 800        /// <summary>
 801        /// Gets or sets list of external media forced flags.
 802        /// </summary>
 803        public string[] MediaForcedFlags { get; set; }
 804
 805        /// <summary>
 806        /// Gets or sets list of external media default flags.
 807        /// </summary>
 808        public string[] MediaDefaultFlags { get; set; }
 809
 810        /// <summary>
 811        /// Gets or sets list of external media hearing impaired flags.
 812        /// </summary>
 813        public string[] MediaHearingImpairedFlags { get; set; }
 814
 815        /// <summary>
 816        /// Gets or sets list of album stacking prefixes.
 817        /// </summary>
 818        public string[] AlbumStackingPrefixes { get; set; }
 819
 820        /// <summary>
 821        /// Gets or sets list of artist subfolders.
 822        /// </summary>
 823        public string[] ArtistSubfolders { get; set; }
 824
 825        /// <summary>
 826        /// Gets or sets list of subtitle file extensions.
 827        /// </summary>
 828        public string[] SubtitleFileExtensions { get; set; }
 829
 830        /// <summary>
 831        /// Gets the list of lyric file extensions.
 832        /// </summary>
 833        public string[] LyricFileExtensions { get; }
 834
 835        /// <summary>
 836        /// Gets or sets list of episode regular expressions.
 837        /// </summary>
 838        public EpisodeExpression[] EpisodeExpressions { get; set; }
 839
 840        /// <summary>
 841        /// Gets or sets list of video file extensions.
 842        /// </summary>
 843        public string[] VideoFileExtensions { get; set; }
 844
 845        /// <summary>
 846        /// Gets or sets list of video stub file extensions.
 847        /// </summary>
 848        public string[] StubFileExtensions { get; set; }
 849
 850        /// <summary>
 851        /// Gets or sets list of raw audiobook parts regular expressions strings.
 852        /// </summary>
 853        public string[] AudioBookPartsExpressions { get; set; }
 854
 855        /// <summary>
 856        /// Gets or sets list of raw audiobook names regular expressions strings.
 857        /// </summary>
 858        public string[] AudioBookNamesExpressions { get; set; }
 859
 860        /// <summary>
 861        /// Gets or sets list of stub type rules.
 862        /// </summary>
 863        public StubTypeRule[] StubTypes { get; set; }
 864
 865        /// <summary>
 866        /// Gets or sets list of video flag delimiters.
 867        /// </summary>
 868        public char[] VideoFlagDelimiters { get; set; }
 869
 870        /// <summary>
 871        /// Gets or sets list of 3D Format rules.
 872        /// </summary>
 873        public Format3DRule[] Format3DRules { get; set; }
 874
 875        /// <summary>
 876        /// Gets the file stacking rules.
 877        /// </summary>
 878        public FileStackRule[] VideoFileStackingRules { get; }
 879
 880        /// <summary>
 881        /// Gets or sets list of raw clean DateTimes regular expressions strings.
 882        /// </summary>
 883        public string[] CleanDateTimes { get; set; }
 884
 885        /// <summary>
 886        /// Gets or sets list of raw clean strings regular expressions strings.
 887        /// </summary>
 888        public string[] CleanStrings { get; set; }
 889
 890        /// <summary>
 891        /// Gets or sets list of multi-episode regular expressions.
 892        /// </summary>
 893        public EpisodeExpression[] MultipleEpisodeExpressions { get; set; }
 894
 895        /// <summary>
 896        /// Gets or sets list of extra rules for videos.
 897        /// </summary>
 898        public ExtraRule[] VideoExtraRules { get; set; }
 899
 900        /// <summary>
 901        /// Gets list of clean datetime regular expressions.
 902        /// </summary>
 903        public Regex[] CleanDateTimeRegexes { get; private set; } = [];
 904
 905        /// <summary>
 906        /// Gets list of clean string regular expressions.
 907        /// </summary>
 908        public Regex[] CleanStringRegexes { get; private set; } = [];
 909
 910        /// <summary>
 911        /// Compiles raw regex strings into regexes.
 912        /// </summary>
 913        public void Compile()
 914        {
 742915            CleanDateTimeRegexes = CleanDateTimes.Select(Compile).ToArray();
 742916            CleanStringRegexes = CleanStrings.Select(Compile).ToArray();
 742917        }
 918
 919        private Regex Compile(string exp)
 920        {
 5936921            return new Regex(exp, RegexOptions.IgnoreCase | RegexOptions.Compiled);
 922        }
 923    }
 924}