< 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 5/6/2026 - 12:15:23 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        {
 75624            VideoFileExtensions =
 75625            [
 75626                ".001",
 75627                ".3g2",
 75628                ".3gp",
 75629                ".amv",
 75630                ".asf",
 75631                ".asx",
 75632                ".avi",
 75633                ".bin",
 75634                ".bivx",
 75635                ".divx",
 75636                ".dv",
 75637                ".dvr-ms",
 75638                ".f4v",
 75639                ".fli",
 75640                ".flv",
 75641                ".ifo",
 75642                ".img",
 75643                ".iso",
 75644                ".m2t",
 75645                ".m2ts",
 75646                ".m2v",
 75647                ".m4v",
 75648                ".mkv",
 75649                ".mk3d",
 75650                ".mov",
 75651                ".mp4",
 75652                ".mpe",
 75653                ".mpeg",
 75654                ".mpg",
 75655                ".mts",
 75656                ".mxf",
 75657                ".nrg",
 75658                ".nsv",
 75659                ".nuv",
 75660                ".ogm",
 75661                ".ogv",
 75662                ".pva",
 75663                ".qt",
 75664                ".rec",
 75665                ".rm",
 75666                ".rmvb",
 75667                ".strm",
 75668                ".svq3",
 75669                ".tp",
 75670                ".ts",
 75671                ".ty",
 75672                ".viv",
 75673                ".vob",
 75674                ".vp3",
 75675                ".webm",
 75676                ".wmv",
 75677                ".wtv",
 75678                ".xvid"
 75679            ];
 80
 75681            VideoFlagDelimiters =
 75682            [
 75683                '(',
 75684                ')',
 75685                '-',
 75686                '.',
 75687                '_',
 75688                '[',
 75689                ']'
 75690            ];
 91
 75692            StubFileExtensions =
 75693            [
 75694                ".disc"
 75695            ];
 96
 75697            StubTypes =
 75698            [
 75699                new StubTypeRule(
 756100                    stubType: "dvd",
 756101                    token: "dvd"),
 756102
 756103                new StubTypeRule(
 756104                    stubType: "hddvd",
 756105                    token: "hddvd"),
 756106
 756107                new StubTypeRule(
 756108                    stubType: "bluray",
 756109                    token: "bluray"),
 756110
 756111                new StubTypeRule(
 756112                    stubType: "bluray",
 756113                    token: "brrip"),
 756114
 756115                new StubTypeRule(
 756116                    stubType: "bluray",
 756117                    token: "bd25"),
 756118
 756119                new StubTypeRule(
 756120                    stubType: "bluray",
 756121                    token: "bd50"),
 756122
 756123                new StubTypeRule(
 756124                    stubType: "vhs",
 756125                    token: "vhs"),
 756126
 756127                new StubTypeRule(
 756128                    stubType: "tv",
 756129                    token: "HDTV"),
 756130
 756131                new StubTypeRule(
 756132                    stubType: "tv",
 756133                    token: "PDTV"),
 756134
 756135                new StubTypeRule(
 756136                    stubType: "tv",
 756137                    token: "DSR")
 756138            ];
 139
 756140            VideoFileStackingRules =
 756141            [
 756142                new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])
 756143                new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])
 756144            ];
 145
 756146            CleanDateTimes =
 756147            [
 756148                @"(.+[^_\,\.\(\)\[\]\-])[_\.\(\)\[\]\-](19[0-9]{2}|20[0-9]{2})(?![0-9]+|\W[0-9]{2}\W[0-9]{2})([ _\,\.\(\
 756149                @"(.+[^_\,\.\(\)\[\]\-])[ _\.\(\)\[\]\-]+(19[0-9]{2}|20[0-9]{2})(?![0-9]+|\W[0-9]{2}\W[0-9]{2})([ _\,\.\
 756150            ];
 151
 756152            CleanStrings =
 756153            [
 756154                @"^\s*(?<cleaned>.+?)[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|d
 756155                @"^\s*(?<cleaned>.+?)((\s*\[[^\]]+\]\s*)+)(\.[^\s]+)?$",
 756156                @"^\s*(?<cleaned>.+?)\WE[0-9]+(-|~)E?[0-9]+(\W|$)",
 756157                @"^\s*\[[^\]]+\](?!\.\w+$)\s*(?<cleaned>.+)",
 756158                @"^\s*(?<cleaned>.+?)\s+-\s+[0-9]+\s*$",
 756159                @"^\s*(?<cleaned>.+?)(([-._ ](trailer|sample))|-(scene|clip|behindthescenes|deleted|deletedscene|feature
 756160            ];
 161
 756162            SubtitleFileExtensions =
 756163            [
 756164                ".ass",
 756165                ".mks",
 756166                ".sami",
 756167                ".smi",
 756168                ".srt",
 756169                ".ssa",
 756170                ".sub",
 756171                ".sup",
 756172                ".vtt",
 756173            ];
 174
 756175            LyricFileExtensions =
 756176            [
 756177                ".lrc",
 756178                ".elrc",
 756179                ".txt"
 756180            ];
 181
 756182            AlbumStackingPrefixes =
 756183            [
 756184                "cd",
 756185                "digital media",
 756186                "disc",
 756187                "disk",
 756188                "vol",
 756189                "volume",
 756190                "part",
 756191                "act"
 756192            ];
 193
 756194            ArtistSubfolders =
 756195            [
 756196                "albums",
 756197                "broadcasts",
 756198                "bootlegs",
 756199                "compilations",
 756200                "dj-mixes",
 756201                "eps",
 756202                "live",
 756203                "mixtapes",
 756204                "others",
 756205                "remixes",
 756206                "singles",
 756207                "soundtracks",
 756208                "spokenwords",
 756209                "streets"
 756210            ];
 211
 756212            AudioFileExtensions =
 756213            [
 756214                ".669",
 756215                ".3gp",
 756216                ".aa",
 756217                ".aac",
 756218                ".aax",
 756219                ".ac3",
 756220                ".act",
 756221                ".adp",
 756222                ".adplug",
 756223                ".adx",
 756224                ".afc",
 756225                ".amf",
 756226                ".aif",
 756227                ".aifc",
 756228                ".aiff",
 756229                ".alac",
 756230                ".amr",
 756231                ".ape",
 756232                ".ast",
 756233                ".au",
 756234                ".awb",
 756235                ".cda",
 756236                ".cue",
 756237                ".dmf",
 756238                ".dsf",
 756239                ".dsm",
 756240                ".dsp",
 756241                ".dts",
 756242                ".dvf",
 756243                ".eac3",
 756244                ".ec3",
 756245                ".far",
 756246                ".flac",
 756247                ".gdm",
 756248                ".gsm",
 756249                ".gym",
 756250                ".hps",
 756251                ".imf",
 756252                ".it",
 756253                ".m15",
 756254                ".m4a",
 756255                ".m4b",
 756256                ".mac",
 756257                ".med",
 756258                ".mka",
 756259                ".mmf",
 756260                ".mod",
 756261                ".mogg",
 756262                ".mp2",
 756263                ".mp3",
 756264                ".mpa",
 756265                ".mpc",
 756266                ".mpp",
 756267                ".mp+",
 756268                ".msv",
 756269                ".nmf",
 756270                ".nsf",
 756271                ".nsv",
 756272                ".oga",
 756273                ".ogg",
 756274                ".okt",
 756275                ".opus",
 756276                ".pls",
 756277                ".ra",
 756278                ".rf64",
 756279                ".rm",
 756280                ".s3m",
 756281                ".sfx",
 756282                ".shn",
 756283                ".sid",
 756284                ".stm",
 756285                ".strm",
 756286                ".ult",
 756287                ".uni",
 756288                ".vox",
 756289                ".wav",
 756290                ".wma",
 756291                ".wv",
 756292                ".xm",
 756293                ".xsp",
 756294                ".ymf"
 756295            ];
 296
 756297            MediaFlagDelimiters =
 756298            [
 756299                '.'
 756300            ];
 301
 756302            MediaForcedFlags =
 756303            [
 756304                "foreign",
 756305                "forced"
 756306            ];
 307
 756308            MediaDefaultFlags =
 756309            [
 756310                "default"
 756311            ];
 312
 756313            MediaHearingImpairedFlags =
 756314            [
 756315                "cc",
 756316                "hi",
 756317                "sdh"
 756318            ];
 319
 756320            EpisodeExpressions =
 756321            [
 756322                // *** Begin Kodi Standard Naming
 756323                // <!-- foo.s01.e01, foo.s01_e01, S01E02 foo, S01 - E02 -->
 756324                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![Ss]([0-9]+)[][ ._-]*[Ee]([0-9]+))[^\\\/])*)?[Ss](?<s
 756325                {
 756326                    IsNamed = true
 756327                },
 756328                // <!-- foo.ep01, foo.EP_01 -->
 756329                new EpisodeExpression(@"[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$"),
 756330                // <!-- foo.E01., foo.e01. -->
 756331                new EpisodeExpression(@"[^\\/]*?()\.?[Ee]([0-9]+)\.([^\\/]*)$"),
 756332                new EpisodeExpression("(?<year>[0-9]{4})[._ -](?<month>[0-9]{2})[._ -](?<day>[0-9]{2})", true)
 756333                {
 756334                    DateTimeFormats =
 756335                    [
 756336                        "yyyy.MM.dd",
 756337                        "yyyy-MM-dd",
 756338                        "yyyy_MM_dd",
 756339                        "yyyy MM dd"
 756340                    ]
 756341                },
 756342                new EpisodeExpression("(?<day>[0-9]{2})[._ -](?<month>[0-9]{2})[._ -](?<year>[0-9]{4})", true)
 756343                {
 756344                    DateTimeFormats =
 756345                    [
 756346                        "dd.MM.yyyy",
 756347                        "dd-MM-yyyy",
 756348                        "dd_MM_yyyy",
 756349                        "dd MM yyyy"
 756350                    ]
 756351                },
 756352
 756353                // This isn't a Kodi naming rule, but the expression below causes false episode numbers for
 756354                // Title Season X Episode X naming schemes.
 756355                // "Series Season X Episode X - Title.avi", "Series S03 E09.avi", "s3 e9 - Title.avi"
 756356                new EpisodeExpression(@".*[\\\/]((?<seriesname>[^\\/]+?)\s)?[Ss](?:eason)?\s*(?<seasonnumber>[0-9]+)\s+[
 756357                {
 756358                    IsNamed = true
 756359                },
 756360
 756361                // Not a Kodi rule as well, but the expression below also causes false positives,
 756362                // so we make sure this one gets tested first.
 756363                // "Foo Bar 889"
 756364                // Names carrying an SxxEyy marker are excluded because the Kodi expression above already covers them.
 756365                // Without that guard this expression reads digits out of the title instead, turning
 756366                // "S01E01 1-23-45 [Bluray-1080p]" into episodes 1 through 45.
 756367                new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?![^\\\/]*[Ss][0-9]+[][ ._-]*[Ee][0-9]+)(?<seriesname>[\w
 756368                {
 756369                    IsNamed = true
 756370                },
 756371
 756372                new EpisodeExpression(@"[\\\/\._ \[\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\.[1-9])(?![0-9]))?)([^\\\/]*)$")
 756373                {
 756374                    SupportsAbsoluteEpisodeNumbers = true
 756375                },
 756376
 756377                // Not a Kodi rule as well, but below rule also causes false positives for triple-digit episode names
 756378                // [bar] Foo - 1 [baz] special case of below expression to prevent false positives with digits in the se
 756379                new EpisodeExpression(@".*[\\\/]?.*?(\[.*?\])+.*?(?<seriesname>[-\w\s]+?)[\s_]*-[\s_]*(?<epnumber>[0-9]+
 756380                {
 756381                    IsNamed = true
 756382                },
 756383
 756384                // "Name - 101.mkv", "Name - 101 [720p].mkv", "Name - 101 (2020).mkv"
 756385                // Handles absolute episode numbers with hyphen delimiter (common in anime)
 756386                // Without brackets (bracketed version handled above)
 756387                new EpisodeExpression(@".*[\\\/](?<seriesname>[^\\\/]+?)[\s_]+-[\s_]+(?<epnumber>[0-9]+)[\s_]*(?:\[.*?\]
 756388                {
 756389                    IsNamed = true
 756390                },
 756391
 756392                // /server/anything_102.mp4
 756393                // /server/james.corden.2017.04.20.anne.hathaway.720p.hdtv.x264-crooks.mkv
 756394                // /server/anything_1996.11.14.mp4
 756395                new EpisodeExpression(@"[\\/._ -](?<seriesname>(?![0-9]+[0-9][0-9])([^\\\/_])*)[\\\/._ -](?<seasonnumber
 756396                {
 756397                    IsOptimistic = true,
 756398                    IsNamed = true,
 756399                    SupportsAbsoluteEpisodeNumbers = false
 756400                },
 756401                new EpisodeExpression(@"[\/._ -]p(?:ar)?t[_. -]()([ivx]+|[0-9]+)([._ -][^\/]*)$")
 756402                {
 756403                    SupportsAbsoluteEpisodeNumbers = true
 756404                },
 756405
 756406                // *** End Kodi Standard Naming
 756407
 756408                // "Episode 16", "Episode 16 - Title"
 756409                new EpisodeExpression(@"[Ee]pisode (?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))?[^\\\/]*$")
 756410                {
 756411                    IsNamed = true
 756412                },
 756413
 756414                new EpisodeExpression(@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]+)[xX](?<epnumber>[0-9]+)[^\\\/]*$")
 756415                {
 756416                    IsNamed = true
 756417                },
 756418
 756419                new EpisodeExpression(@".*(\\|\/)[sS](?<seasonnumber>[0-9]+)[x,X]?[eE](?<epnumber>[0-9]+)[^\\\/]*$")
 756420                {
 756421                    IsNamed = true
 756422                },
 756423
 756424                new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<sea
 756425                {
 756426                    IsNamed = true
 756427                },
 756428
 756429                new EpisodeExpression(@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epn
 756430                {
 756431                    IsNamed = true
 756432                },
 756433
 756434                // "01.avi"
 756435                new EpisodeExpression(@".*[\\\/](?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))*\.\w+$")
 756436                {
 756437                    IsOptimistic = true,
 756438                    IsNamed = true
 756439                },
 756440
 756441                // "1-12 episode title"
 756442                new EpisodeExpression("([0-9]+)-([0-9]+)"),
 756443
 756444                // "01 - blah.avi", "01-blah.avi"
 756445                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\s?-\s?[^\\\/]*
 756446                {
 756447                    IsOptimistic = true,
 756448                    IsNamed = true
 756449                },
 756450
 756451                // "01.blah.avi"
 756452                new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\.[^\\\/]+$")
 756453                {
 756454                    IsOptimistic = true,
 756455                    IsNamed = true
 756456                },
 756457
 756458                // "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi",
 756459                new EpisodeExpression(@".*[\\\/][^\\\/]* - (?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\
 756460                {
 756461                    IsOptimistic = true,
 756462                    IsNamed = true
 756463                },
 756464
 756465                // "01 episode title.avi"
 756466                new EpisodeExpression(@"[Ss]eason[\._ ](?<seasonnumber>[0-9]+)[\\\/](?<epnumber>[0-9]{1,3})([^\\\/]*)$")
 756467                {
 756468                    IsOptimistic = true,
 756469                    IsNamed = true
 756470                },
 756471
 756472                // Series and season only expression
 756473                // "the show/season 1", "the show/s01"
 756474                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)\/[Ss](eason)?[\. _\-]*(?<seasonnumber>[0-9]+)")
 756475                {
 756476                    IsNamed = true
 756477                },
 756478
 756479                // Series and season only expression
 756480                // "the show S01", "the show season 1"
 756481                new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)[\. _\-]+[sS](eason)?[\. _\-]*(?<seasonnumber>[0-9]
 756482                {
 756483                    IsNamed = true
 756484                },
 756485
 756486                // Anime style expression
 756487                // "[Group][Series Name][21][1080p][FLAC][HASH]"
 756488                // "[Group] Series Name [04][BDRIP]"
 756489                new EpisodeExpression(@"(?:\[(?:[^\]]+)\]\s*)?(?<seriesname>\[[^\]]+\]|[^[\]]+)\s*\[(?<epnumber>[0-9]+)\
 756490                {
 756491                    IsNamed = true
 756492                },
 756493            ];
 494
 756495            VideoExtraRules =
 756496            [
 756497                new ExtraRule(
 756498                    ExtraType.Trailer,
 756499                    ExtraRuleType.DirectoryName,
 756500                    "trailers",
 756501                    MediaType.Video),
 756502
 756503                new ExtraRule(
 756504                    ExtraType.ThemeVideo,
 756505                    ExtraRuleType.DirectoryName,
 756506                    "backdrops",
 756507                    MediaType.Video),
 756508
 756509                new ExtraRule(
 756510                    ExtraType.ThemeSong,
 756511                    ExtraRuleType.DirectoryName,
 756512                    "theme-music",
 756513                    MediaType.Audio),
 756514
 756515                new ExtraRule(
 756516                    ExtraType.BehindTheScenes,
 756517                    ExtraRuleType.DirectoryName,
 756518                    "behind the scenes",
 756519                    MediaType.Video),
 756520
 756521                new ExtraRule(
 756522                    ExtraType.DeletedScene,
 756523                    ExtraRuleType.DirectoryName,
 756524                    "deleted scenes",
 756525                    MediaType.Video),
 756526
 756527                new ExtraRule(
 756528                    ExtraType.Interview,
 756529                    ExtraRuleType.DirectoryName,
 756530                    "interviews",
 756531                    MediaType.Video),
 756532
 756533                new ExtraRule(
 756534                    ExtraType.Scene,
 756535                    ExtraRuleType.DirectoryName,
 756536                    "scenes",
 756537                    MediaType.Video),
 756538
 756539                new ExtraRule(
 756540                    ExtraType.Sample,
 756541                    ExtraRuleType.DirectoryName,
 756542                    "samples",
 756543                    MediaType.Video),
 756544
 756545                new ExtraRule(
 756546                    ExtraType.Short,
 756547                    ExtraRuleType.DirectoryName,
 756548                    "shorts",
 756549                    MediaType.Video),
 756550
 756551                new ExtraRule(
 756552                    ExtraType.Featurette,
 756553                    ExtraRuleType.DirectoryName,
 756554                    "featurettes",
 756555                    MediaType.Video),
 756556
 756557                new ExtraRule(
 756558                    ExtraType.Unknown,
 756559                    ExtraRuleType.DirectoryName,
 756560                    "extras",
 756561                    MediaType.Video),
 756562
 756563                new ExtraRule(
 756564                    ExtraType.Unknown,
 756565                    ExtraRuleType.DirectoryName,
 756566                    "extra",
 756567                    MediaType.Video),
 756568
 756569                new ExtraRule(
 756570                    ExtraType.Unknown,
 756571                    ExtraRuleType.DirectoryName,
 756572                    "other",
 756573                    MediaType.Video),
 756574
 756575                new ExtraRule(
 756576                    ExtraType.Clip,
 756577                    ExtraRuleType.DirectoryName,
 756578                    "clips",
 756579                    MediaType.Video),
 756580
 756581                new ExtraRule(
 756582                    ExtraType.Trailer,
 756583                    ExtraRuleType.Filename,
 756584                    "trailer",
 756585                    MediaType.Video),
 756586
 756587                new ExtraRule(
 756588                    ExtraType.Sample,
 756589                    ExtraRuleType.Filename,
 756590                    "sample",
 756591                    MediaType.Video),
 756592
 756593                new ExtraRule(
 756594                    ExtraType.ThemeSong,
 756595                    ExtraRuleType.Filename,
 756596                    "theme",
 756597                    MediaType.Audio),
 756598
 756599                new ExtraRule(
 756600                    ExtraType.Trailer,
 756601                    ExtraRuleType.Suffix,
 756602                    "-trailer",
 756603                    MediaType.Video),
 756604
 756605                new ExtraRule(
 756606                    ExtraType.Trailer,
 756607                    ExtraRuleType.Suffix,
 756608                    ".trailer",
 756609                    MediaType.Video),
 756610
 756611                new ExtraRule(
 756612                    ExtraType.Trailer,
 756613                    ExtraRuleType.Suffix,
 756614                    "_trailer",
 756615                    MediaType.Video),
 756616
 756617                new ExtraRule(
 756618                    ExtraType.Trailer,
 756619                    ExtraRuleType.Suffix,
 756620                    "- trailer",
 756621                    MediaType.Video),
 756622
 756623                new ExtraRule(
 756624                    ExtraType.Sample,
 756625                    ExtraRuleType.Suffix,
 756626                    "-sample",
 756627                    MediaType.Video),
 756628
 756629                new ExtraRule(
 756630                    ExtraType.Sample,
 756631                    ExtraRuleType.Suffix,
 756632                    ".sample",
 756633                    MediaType.Video),
 756634
 756635                new ExtraRule(
 756636                    ExtraType.Sample,
 756637                    ExtraRuleType.Suffix,
 756638                    "_sample",
 756639                    MediaType.Video),
 756640
 756641                new ExtraRule(
 756642                    ExtraType.Sample,
 756643                    ExtraRuleType.Suffix,
 756644                    "- sample",
 756645                    MediaType.Video),
 756646
 756647                new ExtraRule(
 756648                    ExtraType.Scene,
 756649                    ExtraRuleType.Suffix,
 756650                    "-scene",
 756651                    MediaType.Video),
 756652
 756653                new ExtraRule(
 756654                    ExtraType.Clip,
 756655                    ExtraRuleType.Suffix,
 756656                    "-clip",
 756657                    MediaType.Video),
 756658
 756659                new ExtraRule(
 756660                    ExtraType.Interview,
 756661                    ExtraRuleType.Suffix,
 756662                    "-interview",
 756663                    MediaType.Video),
 756664
 756665                new ExtraRule(
 756666                    ExtraType.BehindTheScenes,
 756667                    ExtraRuleType.Suffix,
 756668                    "-behindthescenes",
 756669                    MediaType.Video),
 756670
 756671                new ExtraRule(
 756672                    ExtraType.DeletedScene,
 756673                    ExtraRuleType.Suffix,
 756674                    "-deleted",
 756675                    MediaType.Video),
 756676
 756677                new ExtraRule(
 756678                    ExtraType.DeletedScene,
 756679                    ExtraRuleType.Suffix,
 756680                    "-deletedscene",
 756681                    MediaType.Video),
 756682
 756683                new ExtraRule(
 756684                    ExtraType.Featurette,
 756685                    ExtraRuleType.Suffix,
 756686                    "-featurette",
 756687                    MediaType.Video),
 756688
 756689                new ExtraRule(
 756690                    ExtraType.Short,
 756691                    ExtraRuleType.Suffix,
 756692                    "-short",
 756693                    MediaType.Video),
 756694
 756695                new ExtraRule(
 756696                    ExtraType.Unknown,
 756697                    ExtraRuleType.Suffix,
 756698                    "-extra",
 756699                    MediaType.Video),
 756700
 756701                new ExtraRule(
 756702                    ExtraType.Unknown,
 756703                    ExtraRuleType.Suffix,
 756704                    "-other",
 756705                    MediaType.Video)
 756706            ];
 707
 756708            AllExtrasTypesFolderNames = VideoExtraRules
 756709                .Where(i => i.RuleType == ExtraRuleType.DirectoryName)
 756710                .ToDictionary(i => i.Token, i => i.ExtraType, StringComparer.OrdinalIgnoreCase);
 711
 756712            Format3DRules =
 756713            [
 756714                // Kodi rules:
 756715                new Format3DRule(
 756716                    precedingToken: "3d",
 756717                    token: "hsbs"),
 756718
 756719                new Format3DRule(
 756720                    precedingToken: "3d",
 756721                    token: "sbs"),
 756722
 756723                new Format3DRule(
 756724                    precedingToken: "3d",
 756725                    token: "htab"),
 756726
 756727                new Format3DRule(
 756728                    precedingToken: "3d",
 756729                    token: "tab"),
 756730
 756731                 // Media Browser rules:
 756732                new Format3DRule("fsbs"),
 756733                new Format3DRule("hsbs"),
 756734                new Format3DRule("sbs"),
 756735                new Format3DRule("ftab"),
 756736                new Format3DRule("htab"),
 756737                new Format3DRule("tab"),
 756738                new Format3DRule("sbs3d"),
 756739                new Format3DRule("mvc")
 756740            ];
 741
 756742            AudioBookPartsExpressions =
 756743            [
 756744                // Detect specified chapters, like CH 01
 756745                @"ch(?:apter)?[\s_-]?(?<chapter>[0-9]+)",
 756746                // Detect specified parts, like Part 02
 756747                @"p(?:ar)?t[\s_-]?(?<part>[0-9]+)",
 756748                // Chapter is often beginning of filename
 756749                "^(?<chapter>[0-9]+)",
 756750                // Part if often ending of filename
 756751                "(?<!ch(?:apter) )(?<part>[0-9]+)$",
 756752                // Sometimes named as 0001_005 (chapter_part)
 756753                "(?<chapter>[0-9]+)_(?<part>[0-9]+)",
 756754                // Some audiobooks are ripped from cd's, and will be named by disk number.
 756755                @"dis(?:c|k)[\s_-]?(?<chapter>[0-9]+)"
 756756            ];
 757
 756758            AudioBookNamesExpressions =
 756759            [
 756760                // Detect year usually in brackets after name Batman (2020)
 756761                @"^(?<name>.+?)\s*\(\s*(?<year>[0-9]{4})\s*\)\s*$",
 756762                @"^\s*(?<name>[^ ].*?)\s*$"
 756763            ];
 764
 756765            MultipleEpisodeExpressions = new[]
 756766            {
 756767                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endinge
 756768                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[xX][eE](?<endin
 756769                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )?[xXeE](?<endingepnumber>[
 756770                @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})(-[xE]?[eE]?(?<endingepnumber>[0-9
 756771                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 756772                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 756773                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 756774                @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[
 756775                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})((-| 
 756776                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})(-[xX
 756777            }.Select(i => new EpisodeExpression(i)
 756778            {
 756779                IsNamed = true
 756780            }).ToArray();
 781
 756782            Compile();
 756783        }
 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        {
 757915            CleanDateTimeRegexes = CleanDateTimes.Select(Compile).ToArray();
 757916            CleanStringRegexes = CleanStrings.Select(Compile).ToArray();
 757917        }
 918
 919        private Regex Compile(string exp)
 920        {
 6056921            return new Regex(exp, RegexOptions.IgnoreCase | RegexOptions.Compiled);
 922        }
 923    }
 924}