Skip to content

Commit

Permalink
feat(MangaFileNameParser): add fixed parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
DevYukine committed Feb 10, 2024
1 parent 1e352ed commit f079011
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion backend/MangaMagnet.Core/Local/Parsing/FileParserResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
73 changes: 46 additions & 27 deletions backend/MangaMagnet.Core/Local/Parsing/MangaFileNameParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
3 changes: 3 additions & 0 deletions backend/MangaMagnet.Core/Local/Parsing/RegexConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ public static partial class RegexConstants

[GeneratedRegex(@".*[ _.-]c?(?<Chapter>[0-9]+)", RegexOptions.IgnoreCase)]
public static partial Regex ChapterReleaseRegex2();

[GeneratedRegex(@"[\[(](f(?<Number>\d+)?)[\])] ?", RegexOptions.IgnoreCase)]
public static partial Regex FixedRegex();
}
6 changes: 5 additions & 1 deletion backend/MangaMagnet.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EXPR_MEMBER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_EXPR_ACCESSOR_ON_SINGLE_LINE/@EntryValue">ALWAYS</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_ARROW_WITH_EXPRESSIONS/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_ARROW_WITH_EXPRESSIONS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

0 comments on commit f079011

Please sign in to comment.