< 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        {
 66424            VideoFileExtensions = new[]
 66425            {
 66426                ".001",
 66427                ".3g2",
 66428                ".3gp",
 66429                ".amv",
 66430                ".asf",
 66431                ".asx",
 66432                ".avi",
 66433                ".bin",
 66434                ".bivx",
 66435                ".divx",
 66436                ".dv",
 66437                ".dvr-ms",
 66438                ".f4v",
 66439                ".fli",
 66440                ".flv",
 66441                ".ifo",
 66442                ".img",
 66443                ".iso",
 66444                ".m2t",
 66445                ".m2ts",
 66446                ".m2v",
 66447                ".m4v",
 66448                ".mkv",
 66449                ".mk3d",
 66450                ".mov",
 66451                ".mp4",
 66452                ".mpe",
 66453                ".mpeg",
 66454                ".mpg",
 66455                ".mts",
 66456                ".mxf",
 66457                ".nrg",
 66458                ".nsv",
 66459                ".nuv",
 66460                ".ogg",
 66461                ".ogm",
 66462                ".ogv",
 66463                ".pva",
 66464                ".qt",
 66465                ".rec",
 66466                ".rm",
 66467                ".rmvb",
 66468                ".strm",
 66469                ".svq3",
 66470                ".tp",
 66471                ".ts",
 66472                ".ty",
 66473                ".viv",
 66474                ".vob",
 66475                ".vp3",
 66476                ".webm",
 66477                ".wmv",
 66478                ".wtv",
 66479                ".xvid"
 66480            };
 81
 66482            VideoFlagDelimiters = new[]
 66483            {
 66484                '(',
 66485                ')',
 66486                '-',
 66487                '.',
 66488                '_',
 66489                '[',
 66490                ']'
 66491            };
 92
 66493            StubFileExtensions = new[]
 66494            {
 66495                ".disc"
 66496            };
 97
 66498            StubTypes = new[]
 66499            {
 664100                new StubTypeRule(
 664101                    stubType: "dvd",
 664102                    token: "dvd"),
 664103
 664104                new StubTypeRule(
 664105                    stubType: "hddvd",
 664106                    token: "hddvd"),
 664107
 664108                new StubTypeRule(
 664109                    stubType: "bluray",
 664110                    token: "bluray"),
 664111
 664112                new StubTypeRule(
 664113                    stubType: "bluray",
 664114                    token: "brrip"),
 664115
 664116                new StubTypeRule(
 664117                    stubType: "bluray",
 664118                    token: "bd25"),
 664119
 664120                new StubTypeRule(
 664121                    stubType: "bluray",
 664122                    token: "bd50"),
 664123
 664124                new StubTypeRule(
 664125                    stubType: "vhs",
 664126                    token: "vhs"),
 664127
 664128                new StubTypeRule(
 664129                    stubType: "tv",
 664130                    token: "HDTV"),
 664131
 664132                new StubTypeRule(
 664133                    stubType: "tv",
 664134                    token: "PDTV"),
 664135
 664136                new StubTypeRule(
 664137                    stubType: "tv",
 664138                    token: "DSR")
 664139            };
 140
 664141            VideoFileStackingRules = new[]
 664142            {
 664143                new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])
 664144                new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])
 664145            };
 146
 664147            CleanDateTimes = new[]
 664148            {
 664149                @"(.+[^_\,\.\(\)\[\]\-])[_\.\(\)\[\]\-](19[0-9]{2}|20[0-9]{2})(?![0-9]+|\W[0-9]{2}\W[0-9]{2})([ _\,\.\(\
 664150                @"(.+[^_\,\.\(\)\[\]\-])[ _\.\(\)\[\]\-]+(19[0-9]{2}|20[0-9]{2})(?![0-9]+|\W[0-9]{2}\W[0-9]{2})([ _\,\.\
 664151            };
 152
 664153            CleanStrings = new[]
 664154            {
 664155                @"^\s*(?<cleaned>.+?)[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|d
 664156                @"^(?<cleaned>.+?)(\[.*\])",
 664157                @"^\s*(?<cleaned>.+?)\WE[0-9]+(-|~)E?[0-9]+(\W|$)",
 664158                @"^\s*\[[^\]]+\](?!\.\w+$)\s*(?<cleaned>.+)",
 664159                @"^\s*(?<cleaned>.+?)\s+-\s+[0-9]+\s*$",
 664160                @"^\s*(?<cleaned>.+?)(([-._ ](trailer|sample))|-(scene|clip|behindthescenes|deleted|deletedscene|feature
 664161            };
 162
 664163            SubtitleFileExtensions = new[]
 664164            {
 664165                ".ass",
 664166                ".mks",
 664167                ".sami",
 664168                ".smi",
 664169                ".srt",
 664170                ".ssa",
 664171                ".sub",
 664172                ".sup",
 664173                ".vtt",
 664174            };
 175
 664176            LyricFileExtensions = new[]
 664177            {
 664178                ".lrc",
 664179                ".elrc",
 664180                ".txt"
 664181            };
 182
 664183            AlbumStackingPrefixes = new[]
 664184            {
 664185                "cd",
 664186                "digital media",
 664187                "disc",
 664188                "disk",
 664189                "vol",
 664190                "volume",
 664191                "part",
 664192                "act"
 664193            };
 194
 664195            ArtistSubfolders = new[]
 664196            {
 664197                "albums",
 664198                "broadcasts",
 664199                "bootlegs",
 664200                "compilations",
 664201                "dj-mixes",
 664202                "eps",
 664203                "live",
 664204                "mixtapes",
 664205                "others",
 664206                "remixes",
 664207                "singles",
 664208                "soundtracks",
 664209                "spokenwords",
 664210                "streets"
 664211            };
 212
 664213            AudioFileExtensions = new[]
 664214            {
 664215                ".669",
 664216                ".3gp",
 664217                ".aa",
 664218                ".aac",
 664219                ".aax",
 664220                ".ac3",
 664221                ".act",
 664222                ".adp",
 664223                ".adplug",
 664224                ".adx",
 664225                ".afc",
 664226                ".amf",
 664227                ".aif",
 664228                ".aiff",
 664229                ".alac",
 664230                ".amr",
 664231                ".ape",
 664232                ".ast",
 664233                ".au",
 664234                ".awb",
 664235                ".cda",
 664236                ".cue",
 664237                ".dmf",
 664238                ".dsf",
 664239                ".dsm",
 664240                ".dsp",
 664241                ".dts",
 664242                ".dvf",
 664243                ".eac3",
 664244                ".far",
 664245                ".flac",
 664246                ".gdm",
 664247                ".gsm",
 664248                ".gym",
 664249                ".hps",
 664250                ".imf",
 664251                ".it",
 664252                ".m15",
 664253                ".m4a",
 664254                ".m4b",
 664255                ".mac",
 664256                ".med",
 664257                ".mka",
 664258                ".mmf",
 664259                ".mod",
 664260                ".mogg",
 664261                ".mp2",
 664262                ".mp3",
 664263                ".mpa",
 664264                ".mpc",
 664265                ".mpp",
 664266                ".mp+",
 664267                ".msv",
 664268                ".nmf",
 664269                ".nsf",
 664270                ".nsv",
 664271                ".oga",
 664272                ".ogg",
 664273                ".okt",
 664274                ".opus",
 664275                ".pls",
 664276                ".ra",
 664277                ".rf64",
 664278                ".rm",
 664279                ".s3m",
 664280                ".sfx",
 664281                ".shn",
 664282                ".sid",
 664283                ".stm",
 664284                ".strm",
 664285                ".ult",
 664286                ".uni",
 664287                ".vox",
 664288                ".wav",
 664289                ".wma",
 664290                ".wv",
 664291                ".xm",
 664292                ".xsp",
 664293                ".ymf"
 664294            };
 295
 664296            MediaFlagDelimiters = new[]
 664297            {
 664298                '.'
 664299            };
 300
 664301            MediaForcedFlags = new[]
 664302            {
 664303                "foreign",
 664304                "forced"
 664305            };
 306
 664307            MediaDefaultFlags = new[]
 664308            {
 664309                "default"
 664310            };
 311
 664312            MediaHearingImpairedFlags = new[]
 664313            {
 664314                "cc",
 664315                "hi",
 664316                "sdh"
 664317            };
 318
 664319            EpisodeExpressions = new[]
 664320            {
 664321                // *** Begin Kodi Standard Naming
 664322                // <!-- foo.s01.e01, foo.s01_e01, S01E02 foo, S01 - E02 -->
 664323                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![Ss]([0-9]+)[][ ._-]*[Ee]([0-9]+))[^\\\/])*)?[Ss](?<s
 664324                {
 664325                    IsNamed = true
 664326                },
 664327                // <!-- foo.ep01, foo.EP_01 -->
 664328                new EpisodeExpression(@"[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$"),
 664329                // <!-- foo.E01., foo.e01. -->
 664330                new EpisodeExpression(@"[^\\/]*?()\.?[Ee]([0-9]+)\.([^\\/]*)$"),
 664331                new EpisodeExpression("(?<year>[0-9]{4})[._ -](?<month>[0-9]{2})[._ -](?<day>[0-9]{2})", true)
 664332                {
 664333                    DateTimeFormats = new[]
 664334                    {
 664335                        "yyyy.MM.dd",
 664336                        "yyyy-MM-dd",
 664337                        "yyyy_MM_dd",
 664338                        "yyyy MM dd"
 664339                    }
 664340                },
 664341                new EpisodeExpression("(?<day>[0-9]{2})[._ -](?<month>[0-9]{2})[._ -](?<year>[0-9]{4})", true)
 664342                {
 664343                    DateTimeFormats = new[]
 664344                    {
 664345                        "dd.MM.yyyy",
 664346                        "dd-MM-yyyy",
 664347                        "dd_MM_yyyy",
 664348                        "dd MM yyyy"
 664349                    }
 664350                },
 664351
 664352                // This isn't a Kodi naming rule, but the expression below causes false episode numbers for
 664353                // Title Season X Episode X naming schemes.
 664354                // "Series Season X Episode X - Title.avi", "Series S03 E09.avi", "s3 e9 - Title.avi"
 664355                new EpisodeExpression(@".*[\\\/]((?<seriesname>[^\\/]+?)\s)?[Ss](?:eason)?\s*(?<seasonnumber>[0-9]+)\s+[
 664356                {
 664357                    IsNamed = true
 664358                },
 664359
 664360                // Not a Kodi rule as well, but the expression below also causes false positives,
 664361                // so we make sure this one gets tested first.
 664362                // "Foo Bar 889"
 664363                new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>[0-9]{1,4})(-(?<endin
 664364                {
 664365                    IsNamed = true
 664366                },
 664367
 664368                new EpisodeExpression(@"[\\\/\._ \[\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\.[1-9])(?![0-9]))?)([^\\\/]*)$")
 664369                {
 664370                    SupportsAbsoluteEpisodeNumbers = true
 664371                },
 664372
 664373                // Not a Kodi rule as well, but below rule also causes false positives for triple-digit episode names
 664374                // [bar] Foo - 1 [baz] special case of below expression to prevent false positives with digits in the se
 664375                new EpisodeExpression(@".*[\\\/]?.*?(\[.*?\])+.*?(?<seriesname>[-\w\s]+?)[\s_]*-[\s_]*(?<epnumber>[0-9]+
 664376                {
 664377                    IsNamed = true
 664378                },
 664379
 664380                // /server/anything_102.mp4
 664381                // /server/james.corden.2017.04.20.anne.hathaway.720p.hdtv.x264-crooks.mkv
 664382                // /server/anything_1996.11.14.mp4
 664383                new EpisodeExpression(@"[\\/._ -](?<seriesname>(?![0-9]+[0-9][0-9])([^\\\/_])*)[\\\/._ -](?<seasonnumber
 664384                {
 664385                    IsOptimistic = true,
 664386                    IsNamed = true,
 664387                    SupportsAbsoluteEpisodeNumbers = false
 664388                },
 664389                new EpisodeExpression(@"[\/._ -]p(?:ar)?t[_. -]()([ivx]+|[0-9]+)([._ -][^\/]*)$")
 664390                {
 664391                    SupportsAbsoluteEpisodeNumbers = true
 664392                },
 664393
 664394                // *** End Kodi Standard Naming
 664395
 664396                // "Episode 16", "Episode 16 - Title"
 664397                new EpisodeExpression(@"[Ee]pisode (?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))?[^\\\/]*$")
 664398                {
 664399                    IsNamed = true
 664400                },
 664401
 664402                new EpisodeExpression(@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]+)[xX](?<epnumber>[0-9]+)[^\\\/]*$")
 664403                {
 664404                    IsNamed = true
 664405                },
 664406
 664407                new EpisodeExpression(@".*(\\|\/)[sS](?<seasonnumber>[0-9]+)[x,X]?[eE](?<epnumber>[0-9]+)[^\\\/]*$")
 664408                {
 664409                    IsNamed = true
 664410                },
 664411
 664412                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<sea
 664413                {
 664414                    IsNamed = true
 664415                },
 664416
 664417                new EpisodeExpression(@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epn
 664418                {
 664419                    IsNamed = true
 664420                },
 664421
 664422                // "01.avi"
 664423                new EpisodeExpression(@".*[\\\/](?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))*\.\w+$")
 664424                {
 664425                    IsOptimistic = true,
 664426                    IsNamed = true
 664427                },
 664428
 664429                // "1-12 episode title"
 664430                new EpisodeExpression("([0-9]+)-([0-9]+)"),
 664431
 664432                // "01 - blah.avi", "01-blah.avi"
 664433                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\s?-\s?[^\\\/]*
 664434                {
 664435                    IsOptimistic = true,
 664436                    IsNamed = true
 664437                },
 664438
 664439                // "01.blah.avi"
 664440                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\.[^\\\/]+$")
 664441                {
 664442                    IsOptimistic = true,
 664443                    IsNamed = true
 664444                },
 664445
 664446                // "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi",
 664447                new EpisodeExpression(@".*[\\\/][^\\\/]* - (?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\
 664448                {
 664449                    IsOptimistic = true,
 664450                    IsNamed = true
 664451                },
 664452
 664453                // "01 episode title.avi"
 664454                new EpisodeExpression(@"[Ss]eason[\._ ](?<seasonnumber>[0-9]+)[\\\/](?<epnumber>[0-9]{1,3})([^\\\/]*)$")
 664455                {
 664456                    IsOptimistic = true,
 664457                    IsNamed = true
 664458                },
 664459
 664460                // Series and season only expression
 664461                // "the show/season 1", "the show/s01"
 664462                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)\/[Ss](eason)?[\. _\-]*(?<seasonnumber>[0-9]+)")
 664463                {
 664464                    IsNamed = true
 664465                },
 664466
 664467                // Series and season only expression
 664468                // "the show S01", "the show season 1"
 664469                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)[\. _\-]+[sS](eason)?[\. _\-]*(?<seasonnumber>[0-9]
 664470                {
 664471                    IsNamed = true
 664472                },
 664473
 664474                // Anime style expression
 664475                // "[Group][Series Name][21][1080p][FLAC][HASH]"
 664476                // "[Group] Series Name [04][BDRIP]"
 664477                new EpisodeExpression(@"(?:\[(?:[^\]]+)\]\s*)?(?<seriesname>\[[^\]]+\]|[^[\]]+)\s*\[(?<epnumber>[0-9]+)\
 664478                {
 664479                    IsNamed = true
 664480                },
 664481            };
 482
 664483            VideoExtraRules = new[]
 664484            {
 664485                new ExtraRule(
 664486                    ExtraType.Trailer,
 664487                    ExtraRuleType.DirectoryName,
 664488                    "trailers",
 664489                    MediaType.Video),
 664490
 664491                new ExtraRule(
 664492                    ExtraType.ThemeVideo,
 664493                    ExtraRuleType.DirectoryName,
 664494                    "backdrops",
 664495                    MediaType.Video),
 664496
 664497                new ExtraRule(
 664498                    ExtraType.ThemeSong,
 664499                    ExtraRuleType.DirectoryName,
 664500                    "theme-music",
 664501                    MediaType.Audio),
 664502
 664503                new ExtraRule(
 664504                    ExtraType.BehindTheScenes,
 664505                    ExtraRuleType.DirectoryName,
 664506                    "behind the scenes",
 664507                    MediaType.Video),
 664508
 664509                new ExtraRule(
 664510                    ExtraType.DeletedScene,
 664511                    ExtraRuleType.DirectoryName,
 664512                    "deleted scenes",
 664513                    MediaType.Video),
 664514
 664515                new ExtraRule(
 664516                    ExtraType.Interview,
 664517                    ExtraRuleType.DirectoryName,
 664518                    "interviews",
 664519                    MediaType.Video),
 664520
 664521                new ExtraRule(
 664522                    ExtraType.Scene,
 664523                    ExtraRuleType.DirectoryName,
 664524                    "scenes",
 664525                    MediaType.Video),
 664526
 664527                new ExtraRule(
 664528                    ExtraType.Sample,
 664529                    ExtraRuleType.DirectoryName,
 664530                    "samples",
 664531                    MediaType.Video),
 664532
 664533                new ExtraRule(
 664534                    ExtraType.Short,
 664535                    ExtraRuleType.DirectoryName,
 664536                    "shorts",
 664537                    MediaType.Video),
 664538
 664539                new ExtraRule(
 664540                    ExtraType.Featurette,
 664541                    ExtraRuleType.DirectoryName,
 664542                    "featurettes",
 664543                    MediaType.Video),
 664544
 664545                new ExtraRule(
 664546                    ExtraType.Unknown,
 664547                    ExtraRuleType.DirectoryName,
 664548                    "extras",
 664549                    MediaType.Video),
 664550
 664551                new ExtraRule(
 664552                    ExtraType.Unknown,
 664553                    ExtraRuleType.DirectoryName,
 664554                    "extra",
 664555                    MediaType.Video),
 664556
 664557                new ExtraRule(
 664558                    ExtraType.Unknown,
 664559                    ExtraRuleType.DirectoryName,
 664560                    "other",
 664561                    MediaType.Video),
 664562
 664563                new ExtraRule(
 664564                    ExtraType.Clip,
 664565                    ExtraRuleType.DirectoryName,
 664566                    "clips",
 664567                    MediaType.Video),
 664568
 664569                new ExtraRule(
 664570                    ExtraType.Trailer,
 664571                    ExtraRuleType.Filename,
 664572                    "trailer",
 664573                    MediaType.Video),
 664574
 664575                new ExtraRule(
 664576                    ExtraType.Trailer,
 664577                    ExtraRuleType.Suffix,
 664578                    "-trailer",
 664579                    MediaType.Video),
 664580
 664581                new ExtraRule(
 664582                    ExtraType.Trailer,
 664583                    ExtraRuleType.Suffix,
 664584                    ".trailer",
 664585                    MediaType.Video),
 664586
 664587                new ExtraRule(
 664588                    ExtraType.Trailer,
 664589                    ExtraRuleType.Suffix,
 664590                    "_trailer",
 664591                    MediaType.Video),
 664592
 664593                new ExtraRule(
 664594                    ExtraType.Trailer,
 664595                    ExtraRuleType.Suffix,
 664596                    " trailer",
 664597                    MediaType.Video),
 664598
 664599                new ExtraRule(
 664600                    ExtraType.Sample,
 664601                    ExtraRuleType.Filename,
 664602                    "sample",
 664603                    MediaType.Video),
 664604
 664605                new ExtraRule(
 664606                    ExtraType.Sample,
 664607                    ExtraRuleType.Suffix,
 664608                    "-sample",
 664609                    MediaType.Video),
 664610
 664611                new ExtraRule(
 664612                    ExtraType.Sample,
 664613                    ExtraRuleType.Suffix,
 664614                    ".sample",
 664615                    MediaType.Video),
 664616
 664617                new ExtraRule(
 664618                    ExtraType.Sample,
 664619                    ExtraRuleType.Suffix,
 664620                    "_sample",
 664621                    MediaType.Video),
 664622
 664623                new ExtraRule(
 664624                    ExtraType.Sample,
 664625                    ExtraRuleType.Suffix,
 664626                    " sample",
 664627                    MediaType.Video),
 664628
 664629                new ExtraRule(
 664630                    ExtraType.ThemeSong,
 664631                    ExtraRuleType.Filename,
 664632                    "theme",
 664633                    MediaType.Audio),
 664634
 664635                new ExtraRule(
 664636                    ExtraType.Scene,
 664637                    ExtraRuleType.Suffix,
 664638                    "-scene",
 664639                    MediaType.Video),
 664640
 664641                new ExtraRule(
 664642                    ExtraType.Clip,
 664643                    ExtraRuleType.Suffix,
 664644                    "-clip",
 664645                    MediaType.Video),
 664646
 664647                new ExtraRule(
 664648                    ExtraType.Interview,
 664649                    ExtraRuleType.Suffix,
 664650                    "-interview",
 664651                    MediaType.Video),
 664652
 664653                new ExtraRule(
 664654                    ExtraType.BehindTheScenes,
 664655                    ExtraRuleType.Suffix,
 664656                    "-behindthescenes",
 664657                    MediaType.Video),
 664658
 664659                new ExtraRule(
 664660                    ExtraType.DeletedScene,
 664661                    ExtraRuleType.Suffix,
 664662                    "-deleted",
 664663                    MediaType.Video),
 664664
 664665                new ExtraRule(
 664666                    ExtraType.DeletedScene,
 664667                    ExtraRuleType.Suffix,
 664668                    "-deletedscene",
 664669                    MediaType.Video),
 664670
 664671                new ExtraRule(
 664672                    ExtraType.Featurette,
 664673                    ExtraRuleType.Suffix,
 664674                    "-featurette",
 664675                    MediaType.Video),
 664676
 664677                new ExtraRule(
 664678                    ExtraType.Short,
 664679                    ExtraRuleType.Suffix,
 664680                    "-short",
 664681                    MediaType.Video),
 664682
 664683                new ExtraRule(
 664684                    ExtraType.Unknown,
 664685                    ExtraRuleType.Suffix,
 664686                    "-extra",
 664687                    MediaType.Video),
 664688
 664689                new ExtraRule(
 664690                    ExtraType.Unknown,
 664691                    ExtraRuleType.Suffix,
 664692                    "-other",
 664693                    MediaType.Video)
 664694            };
 695
 664696            AllExtrasTypesFolderNames = VideoExtraRules
 664697                .Where(i => i.RuleType == ExtraRuleType.DirectoryName)
 664698                .ToDictionary(i => i.Token, i => i.ExtraType, StringComparer.OrdinalIgnoreCase);
 699
 664700            Format3DRules = new[]
 664701            {
 664702                // Kodi rules:
 664703                new Format3DRule(
 664704                    precedingToken: "3d",
 664705                    token: "hsbs"),
 664706
 664707                new Format3DRule(
 664708                    precedingToken: "3d",
 664709                    token: "sbs"),
 664710
 664711                new Format3DRule(
 664712                    precedingToken: "3d",
 664713                    token: "htab"),
 664714
 664715                new Format3DRule(
 664716                    precedingToken: "3d",
 664717                    token: "tab"),
 664718
 664719                 // Media Browser rules:
 664720                new Format3DRule("fsbs"),
 664721                new Format3DRule("hsbs"),
 664722                new Format3DRule("sbs"),
 664723                new Format3DRule("ftab"),
 664724                new Format3DRule("htab"),
 664725                new Format3DRule("tab"),
 664726                new Format3DRule("sbs3d"),
 664727                new Format3DRule("mvc")
 664728            };
 729
 664730            AudioBookPartsExpressions = new[]
 664731            {
 664732                // Detect specified chapters, like CH 01
 664733                @"ch(?:apter)?[\s_-]?(?<chapter>[0-9]+)",
 664734                // Detect specified parts, like Part 02
 664735                @"p(?:ar)?t[\s_-]?(?<part>[0-9]+)",
 664736                // Chapter is often beginning of filename
 664737                "^(?<chapter>[0-9]+)",
 664738                // Part if often ending of filename
 664739                "(?<!ch(?:apter) )(?<part>[0-9]+)$",
 664740                // Sometimes named as 0001_005 (chapter_part)
 664741                "(?<chapter>[0-9]+)_(?<part>[0-9]+)",
 664742                // Some audiobooks are ripped from cd's, and will be named by disk number.
 664743                @"dis(?:c|k)[\s_-]?(?<chapter>[0-9]+)"
 664744            };
 745
 664746            AudioBookNamesExpressions = new[]
 664747            {
 664748                // Detect year usually in brackets after name Batman (2020)
 664749                @"^(?<name>.+?)\s*\(\s*(?<year>[0-9]{4})\s*\)\s*$",
 664750                @"^\s*(?<name>[^ ].*?)\s*$"
 664751            };
 752
 664753            MultipleEpisodeExpressions = new[]
 664754            {
 664755                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endinge
 664756                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[xX][eE](?<endin
 664757                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )?[xXeE](?<endingepnumber>[
 664758                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})(-[xE]?[eE]?(?<endingepnumber>[0-9
 664759                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 664760                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 664761                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 664762                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 664763                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})((-| 
 664764                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})(-[xX
 664765            }.Select(i => new EpisodeExpression(i)
 664766            {
 664767                IsNamed = true
 664768            }).ToArray();
 769
 664770            Compile();
 664771        }
 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        {
 665903            CleanDateTimeRegexes = CleanDateTimes.Select(Compile).ToArray();
 665904            CleanStringRegexes = CleanStrings.Select(Compile).ToArray();
 665905        }
 906
 907        private Regex Compile(string exp)
 908        {
 5320909            return new Regex(exp, RegexOptions.IgnoreCase | RegexOptions.Compiled);
 910        }
 911    }
 912}