diff --git a/backend/MangaMagnet.Core.Test/Local/Parsing/MangaFileNameParserTest.cs b/backend/MangaMagnet.Core.Test/Local/Parsing/MangaFileNameParserTest.cs index 9c03a8a..c0c893c 100644 --- a/backend/MangaMagnet.Core.Test/Local/Parsing/MangaFileNameParserTest.cs +++ b/backend/MangaMagnet.Core.Test/Local/Parsing/MangaFileNameParserTest.cs @@ -46,6 +46,23 @@ public void Parse_ShouldReturnReleaseGroup_WhenReleaseGroupIsPresent(string inpu public void Parse_ShouldReturnDigital_WhenReleaseIsDigital(string input) => AssertDigital(input, true); + [Theory] + [InlineData("Title v08 (f) (CM)", null)] + [InlineData("Title - More Title v17 (2023) (Digital) (Ushi) (F)", null)] + [InlineData("[0v3r] Image-A-Title v22 (2023) (Digital) (Upscaled) (0v3r) (f)", null)] + [InlineData("Title v01 (2019) (Digital) (F2) (XRA-Empire)", 2)] + [InlineData("[0v3r] Title v05 (F2) (2020) (Digital) (0v3r)", 2)] + public void Parse_ShouldReturnIsFixed_WhenReleaseIsFixed(string input, int? expectedFixedNumber) + => AssertFixed(input, true, expectedFixedNumber); + + private void AssertFixed(string input, bool expectedIsFixed, int? expectedFixedNumber) + { + var result = _parser.Parse(input); + + Assert.Equal(expectedFixedNumber, result.FixedNumber); + Assert.Equal(expectedIsFixed, result.IsFixed); + } + private void AssertDigital(string input, bool expected) { var result = _parser.Parse(input); diff --git a/backend/MangaMagnet.Core/Local/Parsing/FileParserResult.cs b/backend/MangaMagnet.Core/Local/Parsing/FileParserResult.cs index 74f3fe0..b3557b0 100644 --- a/backend/MangaMagnet.Core/Local/Parsing/FileParserResult.cs +++ b/backend/MangaMagnet.Core/Local/Parsing/FileParserResult.cs @@ -7,5 +7,7 @@ public record FileParserResult( int? VolumeNumber, double? ChapterNumber, string? ReleaseGroup, - bool IsDigital = false + bool IsDigital = false, + bool IsFixed = false, + int? FixedNumber = null ); diff --git a/backend/MangaMagnet.Core/Local/Parsing/MangaFileNameParser.cs b/backend/MangaMagnet.Core/Local/Parsing/MangaFileNameParser.cs index 7e3c756..37e06ab 100644 --- a/backend/MangaMagnet.Core/Local/Parsing/MangaFileNameParser.cs +++ b/backend/MangaMagnet.Core/Local/Parsing/MangaFileNameParser.cs @@ -17,44 +17,63 @@ public FileParserResult Parse(string fileName) foreach (var regex in volumeRegexes) { - var match = regex.Match(fileName); - if (!match.Success) continue; - logger.LogDebug("Matched {FileName} as a volume release with Regex {Regex}", fileName, regex); - - var volume = match.Groups["Volume"].Value; + var match = TryMatch(fileName, ParsedReleaseType.VOLUME, regex); + if (match is not null) return match; + } - var title = match.Groups["Title"].Value; - var year = match.Groups["Year"].ValueSpan; - var releaseGroup = match.Groups["ReleaseGroup"].Value; - var digital = match.Groups["Digital"].ValueSpan; + foreach (var regex in chapterRegexes) + { + var match = TryMatch(fileName, ParsedReleaseType.CHAPTER, regex); + if (match is not null) return match; + } - int? yearNumber = year.IsEmpty ? null : int.Parse(year); + throw new FileNameNotParsableException("File Name could not be parsed."); + } - var volumeNumber = int.Parse(volume); + private FileParserResult? TryMatch(string fileName, ParsedReleaseType type, Regex regex) + { + var match = regex.Match(fileName); + if (!match.Success) return null; - return new FileParserResult(title, ParsedReleaseType.VOLUME, yearNumber, volumeNumber, null, releaseGroup, !digital.IsEmpty); - } + logger.LogDebug("Matched {FileName} as a {Type} release with Regex {Regex}", fileName, type.ToString().ToLower(), regex); - foreach (var regex in chapterRegexes) - { - var match = regex.Match(fileName); - if (!match.Success) continue; - logger.LogDebug("Matched {FileName} as a chapter release with Regex {Regex}", fileName, regex); + var title = match.Groups["Title"].Value; + var year = match.Groups["Year"].ValueSpan; + var releaseGroup = match.Groups["ReleaseGroup"].Value; + var digital = match.Groups["Digital"].ValueSpan; - var chapter = match.Groups["Chapter"].ValueSpan; + int? yearNumber = year.IsEmpty ? null : int.Parse(year); - var title = match.Groups["Title"].Value; - var year = match.Groups["Year"].ValueSpan; - var releaseGroup = match.Groups["ReleaseGroup"].Value; - var digital = match.Groups["Digital"].ValueSpan; + var fixedMatch = RegexConstants.FixedRegex().Match(fileName); + if (fixedMatch.Success && fixedMatch.Groups["Number"].Value.Length > 0) + logger.LogDebug("Matched {FileName} as a fixed release with Regex {Regex}", fileName, RegexConstants.FixedRegex()); - int? yearNumber = year.IsEmpty ? null : int.Parse(year); + var containsFixedNumber = fixedMatch.Success && fixedMatch.Groups["Number"].ValueSpan.Length > 0; + int? fixedNumber = containsFixedNumber ? int.Parse(fixedMatch.Groups["Number"].ValueSpan) : null; - var chapterNumber = double.Parse(chapter); + int? volumeNumber = null; + double? chapterNumber = null; - return new FileParserResult(title, ParsedReleaseType.CHAPTER, yearNumber, null, chapterNumber, releaseGroup, !digital.IsEmpty); + switch (type) + { + case ParsedReleaseType.CHAPTER: + { + var chapter = match.Groups["Chapter"].ValueSpan; + chapterNumber = double.Parse(chapter); + break; + } + case ParsedReleaseType.VOLUME: + { + var volume = match.Groups["Volume"].Value; + volumeNumber = int.Parse(volume); + break; + } + case ParsedReleaseType.NONE: + break; + default: + throw new ArgumentOutOfRangeException(nameof(type), type, null); } - throw new FileNameNotParsableException("File Name could not be parsed."); + return new FileParserResult(title, type, yearNumber, volumeNumber, chapterNumber, releaseGroup, !digital.IsEmpty, fixedMatch.Success, fixedNumber); } } diff --git a/backend/MangaMagnet.Core/Local/Parsing/RegexConstants.cs b/backend/MangaMagnet.Core/Local/Parsing/RegexConstants.cs index 2520f7f..141195a 100644 --- a/backend/MangaMagnet.Core/Local/Parsing/RegexConstants.cs +++ b/backend/MangaMagnet.Core/Local/Parsing/RegexConstants.cs @@ -15,4 +15,7 @@ public static partial class RegexConstants [GeneratedRegex(@".*[ _.-]c?(?[0-9]+)", RegexOptions.IgnoreCase)] public static partial Regex ChapterReleaseRegex2(); + + [GeneratedRegex(@"[\[(](f(?\d+)?)[\])] ?", RegexOptions.IgnoreCase)] + public static partial Regex FixedRegex(); } diff --git a/backend/MangaMagnet.sln.DotSettings b/backend/MangaMagnet.sln.DotSettings index 4d51e00..90d10f9 100644 --- a/backend/MangaMagnet.sln.DotSettings +++ b/backend/MangaMagnet.sln.DotSettings @@ -1,4 +1,8 @@  False ALWAYS - True \ No newline at end of file + True + True + True + True + True \ No newline at end of file