< 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: 728
Uncovered lines: 0
Coverable lines: 728
Total lines: 911
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

0255075100

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            };
 193
 664194            ArtistSubfolders = new[]
 664195            {
 664196                "albums",
 664197                "broadcasts",
 664198                "bootlegs",
 664199                "compilations",
 664200                "dj-mixes",
 664201                "eps",
 664202                "live",
 664203                "mixtapes",
 664204                "others",
 664205                "remixes",
 664206                "singles",
 664207                "soundtracks",
 664208                "spokenwords",
 664209                "streets"
 664210            };
 211
 664212            AudioFileExtensions = new[]
 664213            {
 664214                ".669",
 664215                ".3gp",
 664216                ".aa",
 664217                ".aac",
 664218                ".aax",
 664219                ".ac3",
 664220                ".act",
 664221                ".adp",
 664222                ".adplug",
 664223                ".adx",
 664224                ".afc",
 664225                ".amf",
 664226                ".aif",
 664227                ".aiff",
 664228                ".alac",
 664229                ".amr",
 664230                ".ape",
 664231                ".ast",
 664232                ".au",
 664233                ".awb",
 664234                ".cda",
 664235                ".cue",
 664236                ".dmf",
 664237                ".dsf",
 664238                ".dsm",
 664239                ".dsp",
 664240                ".dts",
 664241                ".dvf",
 664242                ".eac3",
 664243                ".far",
 664244                ".flac",
 664245                ".gdm",
 664246                ".gsm",
 664247                ".gym",
 664248                ".hps",
 664249                ".imf",
 664250                ".it",
 664251                ".m15",
 664252                ".m4a",
 664253                ".m4b",
 664254                ".mac",
 664255                ".med",
 664256                ".mka",
 664257                ".mmf",
 664258                ".mod",
 664259                ".mogg",
 664260                ".mp2",
 664261                ".mp3",
 664262                ".mpa",
 664263                ".mpc",
 664264                ".mpp",
 664265                ".mp+",
 664266                ".msv",
 664267                ".nmf",
 664268                ".nsf",
 664269                ".nsv",
 664270                ".oga",
 664271                ".ogg",
 664272                ".okt",
 664273                ".opus",
 664274                ".pls",
 664275                ".ra",
 664276                ".rf64",
 664277                ".rm",
 664278                ".s3m",
 664279                ".sfx",
 664280                ".shn",
 664281                ".sid",
 664282                ".stm",
 664283                ".strm",
 664284                ".ult",
 664285                ".uni",
 664286                ".vox",
 664287                ".wav",
 664288                ".wma",
 664289                ".wv",
 664290                ".xm",
 664291                ".xsp",
 664292                ".ymf"
 664293            };
 294
 664295            MediaFlagDelimiters = new[]
 664296            {
 664297                '.'
 664298            };
 299
 664300            MediaForcedFlags = new[]
 664301            {
 664302                "foreign",
 664303                "forced"
 664304            };
 305
 664306            MediaDefaultFlags = new[]
 664307            {
 664308                "default"
 664309            };
 310
 664311            MediaHearingImpairedFlags = new[]
 664312            {
 664313                "cc",
 664314                "hi",
 664315                "sdh"
 664316            };
 317
 664318            EpisodeExpressions = new[]
 664319            {
 664320                // *** Begin Kodi Standard Naming
 664321                // <!-- foo.s01.e01, foo.s01_e01, S01E02 foo, S01 - E02 -->
 664322                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![Ss]([0-9]+)[][ ._-]*[Ee]([0-9]+))[^\\\/])*)?[Ss](?<s
 664323                {
 664324                    IsNamed = true
 664325                },
 664326                // <!-- foo.ep01, foo.EP_01 -->
 664327                new EpisodeExpression(@"[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$"),
 664328                // <!-- foo.E01., foo.e01. -->
 664329                new EpisodeExpression(@"[^\\/]*?()\.?[Ee]([0-9]+)\.([^\\/]*)$"),
 664330                new EpisodeExpression("(?<year>[0-9]{4})[._ -](?<month>[0-9]{2})[._ -](?<day>[0-9]{2})", true)
 664331                {
 664332                    DateTimeFormats = new[]
 664333                    {
 664334                        "yyyy.MM.dd",
 664335                        "yyyy-MM-dd",
 664336                        "yyyy_MM_dd",
 664337                        "yyyy MM dd"
 664338                    }
 664339                },
 664340                new EpisodeExpression("(?<day>[0-9]{2})[._ -](?<month>[0-9]{2})[._ -](?<year>[0-9]{4})", true)
 664341                {
 664342                    DateTimeFormats = new[]
 664343                    {
 664344                        "dd.MM.yyyy",
 664345                        "dd-MM-yyyy",
 664346                        "dd_MM_yyyy",
 664347                        "dd MM yyyy"
 664348                    }
 664349                },
 664350
 664351                // This isn't a Kodi naming rule, but the expression below causes false episode numbers for
 664352                // Title Season X Episode X naming schemes.
 664353                // "Series Season X Episode X - Title.avi", "Series S03 E09.avi", "s3 e9 - Title.avi"
 664354                new EpisodeExpression(@".*[\\\/]((?<seriesname>[^\\/]+?)\s)?[Ss](?:eason)?\s*(?<seasonnumber>[0-9]+)\s+[
 664355                {
 664356                    IsNamed = true
 664357                },
 664358
 664359                // Not a Kodi rule as well, but the expression below also causes false positives,
 664360                // so we make sure this one gets tested first.
 664361                // "Foo Bar 889"
 664362                new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>[0-9]{1,4})(-(?<endin
 664363                {
 664364                    IsNamed = true
 664365                },
 664366
 664367                new EpisodeExpression(@"[\\\/\._ \[\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\.[1-9])(?![0-9]))?)([^\\\/]*)$")
 664368                {
 664369                    SupportsAbsoluteEpisodeNumbers = true
 664370                },
 664371
 664372                // Not a Kodi rule as well, but below rule also causes false positives for triple-digit episode names
 664373                // [bar] Foo - 1 [baz] special case of below expression to prevent false positives with digits in the se
 664374                new EpisodeExpression(@".*[\\\/]?.*?(\[.*?\])+.*?(?<seriesname>[-\w\s]+?)[\s_]*-[\s_]*(?<epnumber>[0-9]+
 664375                {
 664376                    IsNamed = true
 664377                },
 664378
 664379                // /server/anything_102.mp4
 664380                // /server/james.corden.2017.04.20.anne.hathaway.720p.hdtv.x264-crooks.mkv
 664381                // /server/anything_1996.11.14.mp4
 664382                new EpisodeExpression(@"[\\/._ -](?<seriesname>(?![0-9]+[0-9][0-9])([^\\\/_])*)[\\\/._ -](?<seasonnumber
 664383                {
 664384                    IsOptimistic = true,
 664385                    IsNamed = true,
 664386                    SupportsAbsoluteEpisodeNumbers = false
 664387                },
 664388                new EpisodeExpression(@"[\/._ -]p(?:ar)?t[_. -]()([ivx]+|[0-9]+)([._ -][^\/]*)$")
 664389                {
 664390                    SupportsAbsoluteEpisodeNumbers = true
 664391                },
 664392
 664393                // *** End Kodi Standard Naming
 664394
 664395                // "Episode 16", "Episode 16 - Title"
 664396                new EpisodeExpression(@"[Ee]pisode (?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))?[^\\\/]*$")
 664397                {
 664398                    IsNamed = true
 664399                },
 664400
 664401                new EpisodeExpression(@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]+)[xX](?<epnumber>[0-9]+)[^\\\/]*$")
 664402                {
 664403                    IsNamed = true
 664404                },
 664405
 664406                new EpisodeExpression(@".*(\\|\/)[sS](?<seasonnumber>[0-9]+)[x,X]?[eE](?<epnumber>[0-9]+)[^\\\/]*$")
 664407                {
 664408                    IsNamed = true
 664409                },
 664410
 664411                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<sea
 664412                {
 664413                    IsNamed = true
 664414                },
 664415
 664416                new EpisodeExpression(@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epn
 664417                {
 664418                    IsNamed = true
 664419                },
 664420
 664421                // "01.avi"
 664422                new EpisodeExpression(@".*[\\\/](?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))*\.\w+$")
 664423                {
 664424                    IsOptimistic = true,
 664425                    IsNamed = true
 664426                },
 664427
 664428                // "1-12 episode title"
 664429                new EpisodeExpression("([0-9]+)-([0-9]+)"),
 664430
 664431                // "01 - blah.avi", "01-blah.avi"
 664432                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\s?-\s?[^\\\/]*
 664433                {
 664434                    IsOptimistic = true,
 664435                    IsNamed = true
 664436                },
 664437
 664438                // "01.blah.avi"
 664439                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\.[^\\\/]+$")
 664440                {
 664441                    IsOptimistic = true,
 664442                    IsNamed = true
 664443                },
 664444
 664445                // "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi",
 664446                new EpisodeExpression(@".*[\\\/][^\\\/]* - (?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\
 664447                {
 664448                    IsOptimistic = true,
 664449                    IsNamed = true
 664450                },
 664451
 664452                // "01 episode title.avi"
 664453                new EpisodeExpression(@"[Ss]eason[\._ ](?<seasonnumber>[0-9]+)[\\\/](?<epnumber>[0-9]{1,3})([^\\\/]*)$")
 664454                {
 664455                    IsOptimistic = true,
 664456                    IsNamed = true
 664457                },
 664458
 664459                // Series and season only expression
 664460                // "the show/season 1", "the show/s01"
 664461                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)\/[Ss](eason)?[\. _\-]*(?<seasonnumber>[0-9]+)")
 664462                {
 664463                    IsNamed = true
 664464                },
 664465
 664466                // Series and season only expression
 664467                // "the show S01", "the show season 1"
 664468                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)[\. _\-]+[sS](eason)?[\. _\-]*(?<seasonnumber>[0-9]
 664469                {
 664470                    IsNamed = true
 664471                },
 664472
 664473                // Anime style expression
 664474                // "[Group][Series Name][21][1080p][FLAC][HASH]"
 664475                // "[Group] Series Name [04][BDRIP]"
 664476                new EpisodeExpression(@"(?:\[(?:[^\]]+)\]\s*)?(?<seriesname>\[[^\]]+\]|[^[\]]+)\s*\[(?<epnumber>[0-9]+)\
 664477                {
 664478                    IsNamed = true
 664479                },
 664480            };
 481
 664482            VideoExtraRules = new[]
 664483            {
 664484                new ExtraRule(
 664485                    ExtraType.Trailer,
 664486                    ExtraRuleType.DirectoryName,
 664487                    "trailers",
 664488                    MediaType.Video),
 664489
 664490                new ExtraRule(
 664491                    ExtraType.ThemeVideo,
 664492                    ExtraRuleType.DirectoryName,
 664493                    "backdrops",
 664494                    MediaType.Video),
 664495
 664496                new ExtraRule(
 664497                    ExtraType.ThemeSong,
 664498                    ExtraRuleType.DirectoryName,
 664499                    "theme-music",
 664500                    MediaType.Audio),
 664501
 664502                new ExtraRule(
 664503                    ExtraType.BehindTheScenes,
 664504                    ExtraRuleType.DirectoryName,
 664505                    "behind the scenes",
 664506                    MediaType.Video),
 664507
 664508                new ExtraRule(
 664509                    ExtraType.DeletedScene,
 664510                    ExtraRuleType.DirectoryName,
 664511                    "deleted scenes",
 664512                    MediaType.Video),
 664513
 664514                new ExtraRule(
 664515                    ExtraType.Interview,
 664516                    ExtraRuleType.DirectoryName,
 664517                    "interviews",
 664518                    MediaType.Video),
 664519
 664520                new ExtraRule(
 664521                    ExtraType.Scene,
 664522                    ExtraRuleType.DirectoryName,
 664523                    "scenes",
 664524                    MediaType.Video),
 664525
 664526                new ExtraRule(
 664527                    ExtraType.Sample,
 664528                    ExtraRuleType.DirectoryName,
 664529                    "samples",
 664530                    MediaType.Video),
 664531
 664532                new ExtraRule(
 664533                    ExtraType.Short,
 664534                    ExtraRuleType.DirectoryName,
 664535                    "shorts",
 664536                    MediaType.Video),
 664537
 664538                new ExtraRule(
 664539                    ExtraType.Featurette,
 664540                    ExtraRuleType.DirectoryName,
 664541                    "featurettes",
 664542                    MediaType.Video),
 664543
 664544                new ExtraRule(
 664545                    ExtraType.Unknown,
 664546                    ExtraRuleType.DirectoryName,
 664547                    "extras",
 664548                    MediaType.Video),
 664549
 664550                new ExtraRule(
 664551                    ExtraType.Unknown,
 664552                    ExtraRuleType.DirectoryName,
 664553                    "extra",
 664554                    MediaType.Video),
 664555
 664556                new ExtraRule(
 664557                    ExtraType.Unknown,
 664558                    ExtraRuleType.DirectoryName,
 664559                    "other",
 664560                    MediaType.Video),
 664561
 664562                new ExtraRule(
 664563                    ExtraType.Clip,
 664564                    ExtraRuleType.DirectoryName,
 664565                    "clips",
 664566                    MediaType.Video),
 664567
 664568                new ExtraRule(
 664569                    ExtraType.Trailer,
 664570                    ExtraRuleType.Filename,
 664571                    "trailer",
 664572                    MediaType.Video),
 664573
 664574                new ExtraRule(
 664575                    ExtraType.Trailer,
 664576                    ExtraRuleType.Suffix,
 664577                    "-trailer",
 664578                    MediaType.Video),
 664579
 664580                new ExtraRule(
 664581                    ExtraType.Trailer,
 664582                    ExtraRuleType.Suffix,
 664583                    ".trailer",
 664584                    MediaType.Video),
 664585
 664586                new ExtraRule(
 664587                    ExtraType.Trailer,
 664588                    ExtraRuleType.Suffix,
 664589                    "_trailer",
 664590                    MediaType.Video),
 664591
 664592                new ExtraRule(
 664593                    ExtraType.Trailer,
 664594                    ExtraRuleType.Suffix,
 664595                    " trailer",
 664596                    MediaType.Video),
 664597
 664598                new ExtraRule(
 664599                    ExtraType.Sample,
 664600                    ExtraRuleType.Filename,
 664601                    "sample",
 664602                    MediaType.Video),
 664603
 664604                new ExtraRule(
 664605                    ExtraType.Sample,
 664606                    ExtraRuleType.Suffix,
 664607                    "-sample",
 664608                    MediaType.Video),
 664609
 664610                new ExtraRule(
 664611                    ExtraType.Sample,
 664612                    ExtraRuleType.Suffix,
 664613                    ".sample",
 664614                    MediaType.Video),
 664615
 664616                new ExtraRule(
 664617                    ExtraType.Sample,
 664618                    ExtraRuleType.Suffix,
 664619                    "_sample",
 664620                    MediaType.Video),
 664621
 664622                new ExtraRule(
 664623                    ExtraType.Sample,
 664624                    ExtraRuleType.Suffix,
 664625                    " sample",
 664626                    MediaType.Video),
 664627
 664628                new ExtraRule(
 664629                    ExtraType.ThemeSong,
 664630                    ExtraRuleType.Filename,
 664631                    "theme",
 664632                    MediaType.Audio),
 664633
 664634                new ExtraRule(
 664635                    ExtraType.Scene,
 664636                    ExtraRuleType.Suffix,
 664637                    "-scene",
 664638                    MediaType.Video),
 664639
 664640                new ExtraRule(
 664641                    ExtraType.Clip,
 664642                    ExtraRuleType.Suffix,
 664643                    "-clip",
 664644                    MediaType.Video),
 664645
 664646                new ExtraRule(
 664647                    ExtraType.Interview,
 664648                    ExtraRuleType.Suffix,
 664649                    "-interview",
 664650                    MediaType.Video),
 664651
 664652                new ExtraRule(
 664653                    ExtraType.BehindTheScenes,
 664654                    ExtraRuleType.Suffix,
 664655                    "-behindthescenes",
 664656                    MediaType.Video),
 664657
 664658                new ExtraRule(
 664659                    ExtraType.DeletedScene,
 664660                    ExtraRuleType.Suffix,
 664661                    "-deleted",
 664662                    MediaType.Video),
 664663
 664664                new ExtraRule(
 664665                    ExtraType.DeletedScene,
 664666                    ExtraRuleType.Suffix,
 664667                    "-deletedscene",
 664668                    MediaType.Video),
 664669
 664670                new ExtraRule(
 664671                    ExtraType.Featurette,
 664672                    ExtraRuleType.Suffix,
 664673                    "-featurette",
 664674                    MediaType.Video),
 664675
 664676                new ExtraRule(
 664677                    ExtraType.Short,
 664678                    ExtraRuleType.Suffix,
 664679                    "-short",
 664680                    MediaType.Video),
 664681
 664682                new ExtraRule(
 664683                    ExtraType.Unknown,
 664684                    ExtraRuleType.Suffix,
 664685                    "-extra",
 664686                    MediaType.Video),
 664687
 664688                new ExtraRule(
 664689                    ExtraType.Unknown,
 664690                    ExtraRuleType.Suffix,
 664691                    "-other",
 664692                    MediaType.Video)
 664693            };
 694
 664695            AllExtrasTypesFolderNames = VideoExtraRules
 664696                .Where(i => i.RuleType == ExtraRuleType.DirectoryName)
 664697                .ToDictionary(i => i.Token, i => i.ExtraType, StringComparer.OrdinalIgnoreCase);
 698
 664699            Format3DRules = new[]
 664700            {
 664701                // Kodi rules:
 664702                new Format3DRule(
 664703                    precedingToken: "3d",
 664704                    token: "hsbs"),
 664705
 664706                new Format3DRule(
 664707                    precedingToken: "3d",
 664708                    token: "sbs"),
 664709
 664710                new Format3DRule(
 664711                    precedingToken: "3d",
 664712                    token: "htab"),
 664713
 664714                new Format3DRule(
 664715                    precedingToken: "3d",
 664716                    token: "tab"),
 664717
 664718                 // Media Browser rules:
 664719                new Format3DRule("fsbs"),
 664720                new Format3DRule("hsbs"),
 664721                new Format3DRule("sbs"),
 664722                new Format3DRule("ftab"),
 664723                new Format3DRule("htab"),
 664724                new Format3DRule("tab"),
 664725                new Format3DRule("sbs3d"),
 664726                new Format3DRule("mvc")
 664727            };
 728
 664729            AudioBookPartsExpressions = new[]
 664730            {
 664731                // Detect specified chapters, like CH 01
 664732                @"ch(?:apter)?[\s_-]?(?<chapter>[0-9]+)",
 664733                // Detect specified parts, like Part 02
 664734                @"p(?:ar)?t[\s_-]?(?<part>[0-9]+)",
 664735                // Chapter is often beginning of filename
 664736                "^(?<chapter>[0-9]+)",
 664737                // Part if often ending of filename
 664738                "(?<!ch(?:apter) )(?<part>[0-9]+)$",
 664739                // Sometimes named as 0001_005 (chapter_part)
 664740                "(?<chapter>[0-9]+)_(?<part>[0-9]+)",
 664741                // Some audiobooks are ripped from cd's, and will be named by disk number.
 664742                @"dis(?:c|k)[\s_-]?(?<chapter>[0-9]+)"
 664743            };
 744
 664745            AudioBookNamesExpressions = new[]
 664746            {
 664747                // Detect year usually in brackets after name Batman (2020)
 664748                @"^(?<name>.+?)\s*\(\s*(?<year>[0-9]{4})\s*\)\s*$",
 664749                @"^\s*(?<name>[^ ].*?)\s*$"
 664750            };
 751
 664752            MultipleEpisodeExpressions = new[]
 664753            {
 664754                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endinge
 664755                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[xX][eE](?<endin
 664756                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )?[xXeE](?<endingepnumber>[
 664757                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})(-[xE]?[eE]?(?<endingepnumber>[0-9
 664758                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 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](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})((-| 
 664763                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})(-[xX
 664764            }.Select(i => new EpisodeExpression(i)
 664765            {
 664766                IsNamed = true
 664767            }).ToArray();
 768
 664769            Compile();
 664770        }
 771
 772        /// <summary>
 773        /// Gets or sets the folder name to extra types mapping.
 774        /// </summary>
 775        public Dictionary<string, ExtraType> AllExtrasTypesFolderNames { get; set; }
 776
 777        /// <summary>
 778        /// Gets or sets list of audio file extensions.
 779        /// </summary>
 780        public string[] AudioFileExtensions { get; set; }
 781
 782        /// <summary>
 783        /// Gets or sets list of external media flag delimiters.
 784        /// </summary>
 785        public char[] MediaFlagDelimiters { get; set; }
 786
 787        /// <summary>
 788        /// Gets or sets list of external media forced flags.
 789        /// </summary>
 790        public string[] MediaForcedFlags { get; set; }
 791
 792        /// <summary>
 793        /// Gets or sets list of external media default flags.
 794        /// </summary>
 795        public string[] MediaDefaultFlags { get; set; }
 796
 797        /// <summary>
 798        /// Gets or sets list of external media hearing impaired flags.
 799        /// </summary>
 800        public string[] MediaHearingImpairedFlags { get; set; }
 801
 802        /// <summary>
 803        /// Gets or sets list of album stacking prefixes.
 804        /// </summary>
 805        public string[] AlbumStackingPrefixes { get; set; }
 806
 807        /// <summary>
 808        /// Gets or sets list of artist subfolders.
 809        /// </summary>
 810        public string[] ArtistSubfolders { get; set; }
 811
 812        /// <summary>
 813        /// Gets or sets list of subtitle file extensions.
 814        /// </summary>
 815        public string[] SubtitleFileExtensions { get; set; }
 816
 817        /// <summary>
 818        /// Gets the list of lyric file extensions.
 819        /// </summary>
 820        public string[] LyricFileExtensions { get; }
 821
 822        /// <summary>
 823        /// Gets or sets list of episode regular expressions.
 824        /// </summary>
 825        public EpisodeExpression[] EpisodeExpressions { get; set; }
 826
 827        /// <summary>
 828        /// Gets or sets list of video file extensions.
 829        /// </summary>
 830        public string[] VideoFileExtensions { get; set; }
 831
 832        /// <summary>
 833        /// Gets or sets list of video stub file extensions.
 834        /// </summary>
 835        public string[] StubFileExtensions { get; set; }
 836
 837        /// <summary>
 838        /// Gets or sets list of raw audiobook parts regular expressions strings.
 839        /// </summary>
 840        public string[] AudioBookPartsExpressions { get; set; }
 841
 842        /// <summary>
 843        /// Gets or sets list of raw audiobook names regular expressions strings.
 844        /// </summary>
 845        public string[] AudioBookNamesExpressions { get; set; }
 846
 847        /// <summary>
 848        /// Gets or sets list of stub type rules.
 849        /// </summary>
 850        public StubTypeRule[] StubTypes { get; set; }
 851
 852        /// <summary>
 853        /// Gets or sets list of video flag delimiters.
 854        /// </summary>
 855        public char[] VideoFlagDelimiters { get; set; }
 856
 857        /// <summary>
 858        /// Gets or sets list of 3D Format rules.
 859        /// </summary>
 860        public Format3DRule[] Format3DRules { get; set; }
 861
 862        /// <summary>
 863        /// Gets the file stacking rules.
 864        /// </summary>
 865        public FileStackRule[] VideoFileStackingRules { get; }
 866
 867        /// <summary>
 868        /// Gets or sets list of raw clean DateTimes regular expressions strings.
 869        /// </summary>
 870        public string[] CleanDateTimes { get; set; }
 871
 872        /// <summary>
 873        /// Gets or sets list of raw clean strings regular expressions strings.
 874        /// </summary>
 875        public string[] CleanStrings { get; set; }
 876
 877        /// <summary>
 878        /// Gets or sets list of multi-episode regular expressions.
 879        /// </summary>
 880        public EpisodeExpression[] MultipleEpisodeExpressions { get; set; }
 881
 882        /// <summary>
 883        /// Gets or sets list of extra rules for videos.
 884        /// </summary>
 885        public ExtraRule[] VideoExtraRules { get; set; }
 886
 887        /// <summary>
 888        /// Gets list of clean datetime regular expressions.
 889        /// </summary>
 890        public Regex[] CleanDateTimeRegexes { get; private set; } = Array.Empty<Regex>();
 891
 892        /// <summary>
 893        /// Gets list of clean string regular expressions.
 894        /// </summary>
 895        public Regex[] CleanStringRegexes { get; private set; } = Array.Empty<Regex>();
 896
 897        /// <summary>
 898        /// Compiles raw regex strings into regexes.
 899        /// </summary>
 900        public void Compile()
 901        {
 665902            CleanDateTimeRegexes = CleanDateTimes.Select(Compile).ToArray();
 665903            CleanStringRegexes = CleanStrings.Select(Compile).ToArray();
 665904        }
 905
 906        private Regex Compile(string exp)
 907        {
 5320908            return new Regex(exp, RegexOptions.IgnoreCase | RegexOptions.Compiled);
 909        }
 910    }
 911}