diff --git a/API.Tests/Parser/MangaParserTests.cs b/API.Tests/Parser/MangaParserTests.cs
index 917d1f467..7fb204ca7 100644
--- a/API.Tests/Parser/MangaParserTests.cs
+++ b/API.Tests/Parser/MangaParserTests.cs
@@ -67,6 +67,7 @@ namespace API.Tests.Parser
[InlineData("X-Men v1 #201 (September 2007).cbz", "1")]
[InlineData("Hentai Ouji to Warawanai Neko. - Vol. 06 Ch. 034.5", "6")]
[InlineData("The 100 Girlfriends Who Really, Really, Really, Really, Really Love You - Vol. 03 Ch. 023.5 - Volume 3 Extras.cbz", "3")]
+ [InlineData("The 100 Girlfriends Who Really, Really, Really, Really, Really Love You - Vol. 03.5 Ch. 023.5 - Volume 3 Extras.cbz", "3.5")]
public void ParseVolumeTest(string filename, string expected)
{
Assert.Equal(expected, API.Parser.Parser.ParseVolume(filename));
@@ -291,18 +292,6 @@ namespace API.Tests.Parser
Assert.Equal(expected, API.Parser.Parser.ParseMangaSpecial(inputFile));
}
-/*
- private static ParserInfo CreateParserInfo(string series, string chapter, string volume, bool isSpecial = false)
- {
- return new ParserInfo()
- {
- Chapters = chapter,
- Volumes = volume,
- IsSpecial = isSpecial,
- Series = series,
- };
- }
-*/
[Theory]
[InlineData("/manga/Btooom!/Vol.1/Chapter 1/1.cbz", "Btooom!~1~1")]
diff --git a/API/Controllers/ReadingListController.cs b/API/Controllers/ReadingListController.cs
index 1f22263c7..03a8d7c9d 100644
--- a/API/Controllers/ReadingListController.cs
+++ b/API/Controllers/ReadingListController.cs
@@ -437,7 +437,7 @@ namespace API.Controllers
var existingChapterExists = readingList.Items.Select(rli => rli.ChapterId).ToHashSet();
var chaptersForSeries = (await _unitOfWork.ChapterRepository.GetChaptersByIdsAsync(chapterIds))
- .OrderBy(c => int.Parse(c.Volume.Name))
+ .OrderBy(c => float.Parse(c.Volume.Name))
.ThenBy(x => double.Parse(x.Number), _chapterSortComparerForInChapterSorting);
var index = lastOrder + 1;
diff --git a/API/Entities/Volume.cs b/API/Entities/Volume.cs
index 3be7a4d6a..f4f0076db 100644
--- a/API/Entities/Volume.cs
+++ b/API/Entities/Volume.cs
@@ -8,6 +8,9 @@ namespace API.Entities
public class Volume : IEntityDate
{
public int Id { get; set; }
+ ///
+ /// A String representation of the volume number. Allows for floats
+ ///
public string Name { get; set; }
public int Number { get; set; }
public IList Chapters { get; set; }
diff --git a/API/Parser/Parser.cs b/API/Parser/Parser.cs
index 84a6bcb43..5c9c22f83 100644
--- a/API/Parser/Parser.cs
+++ b/API/Parser/Parser.cs
@@ -70,19 +70,19 @@ namespace API.Parser
@"(?.*)(\b|_)(?!\[)v(?\d+(-\d+)?)(?!\])",
MatchOptions,
RegexTimeout),
- // Kodomo no Jikan vol. 10
+ // Kodomo no Jikan vol. 10, [dmntsf.net] One Piece - Digital Colored Comics Vol. 20.5-21.5 Ch. 177
new Regex(
- @"(?.*)(\b|_)(vol\.? ?)(?\d+(-\d+)?)",
+ @"(?.*)(\b|_)(vol\.? ?)(?\d+(\.\d)?(-\d+)?(\.\d)?)",
MatchOptions,
RegexTimeout),
// Killing Bites Vol. 0001 Ch. 0001 - Galactica Scanlations (gb)
new Regex(
- @"(vol\.? ?)(?\d+)",
+ @"(vol\.? ?)(?\d+(\.\d)?)",
MatchOptions,
RegexTimeout),
// Tonikaku Cawaii [Volume 11].cbz
new Regex(
- @"(volume )(?\d+)",
+ @"(volume )(?\d+(\.\d)?)",
MatchOptions,
RegexTimeout),
// Tower Of God S01 014 (CBT) (digital).cbz
@@ -92,7 +92,7 @@ namespace API.Parser
RegexTimeout),
// vol_001-1.cbz for MangaPy default naming convention
new Regex(
- @"(vol_)(?\d+)",
+ @"(vol_)(?\d+(\.\d)?)",
MatchOptions,
RegexTimeout),
};
@@ -480,7 +480,7 @@ namespace API.Parser
RegexTimeout),
// Beelzebub_01_[Noodles].zip, Beelzebub_153b_RHS.zip
new Regex(
- @"^((?!v|vo|vol|Volume).)*(\s|_)(?\.?\d+(?:.\d+|-\d+)?)(?b)?(\s|_|\[|\()",
+ @"^((?!v|vo|vol|Volume).)*(\s|_)(?\.?\d+(?:.\d+|-\d+)?)(?b)?(\s|_|\[|\()",
MatchOptions,
RegexTimeout),
// Yumekui-Merry_DKThias_Chapter21.zip
@@ -810,12 +810,8 @@ namespace API.Parser
if (!match.Groups["Volume"].Success || match.Groups["Volume"] == Match.Empty) continue;
var value = match.Groups["Volume"].Value;
- if (!value.Contains("-")) return RemoveLeadingZeroes(match.Groups["Volume"].Value);
- var tokens = value.Split("-");
- var from = RemoveLeadingZeroes(tokens[0]);
- var to = RemoveLeadingZeroes(tokens[1]);
- return $"{@from}-{to}";
-
+ var hasPart = match.Groups["Part"].Success;
+ return FormatValue(value, hasPart);
}
}
@@ -832,18 +828,32 @@ namespace API.Parser
if (!match.Groups["Volume"].Success || match.Groups["Volume"] == Match.Empty) continue;
var value = match.Groups["Volume"].Value;
- if (!value.Contains("-")) return RemoveLeadingZeroes(match.Groups["Volume"].Value);
- var tokens = value.Split("-");
- var from = RemoveLeadingZeroes(tokens[0]);
- var to = RemoveLeadingZeroes(tokens[1]);
- return $"{@from}-{to}";
-
+ var hasPart = match.Groups["Part"].Success;
+ return FormatValue(value, hasPart);
}
}
return DefaultVolume;
}
+ private static string FormatValue(string value, bool hasPart)
+ {
+ if (!value.Contains("-"))
+ {
+ return RemoveLeadingZeroes(hasPart ? AddChapterPart(value) : value);
+ }
+
+ var tokens = value.Split("-");
+ var from = RemoveLeadingZeroes(tokens[0]);
+ if (tokens.Length == 2)
+ {
+ var to = RemoveLeadingZeroes(hasPart ? AddChapterPart(tokens[1]) : tokens[1]);
+ return $"{@from}-{to}";
+ }
+
+ return @from;
+ }
+
public static string ParseChapter(string filename)
{
foreach (var regex in MangaChapterRegex)
@@ -854,24 +864,9 @@ namespace API.Parser
if (!match.Groups["Chapter"].Success || match.Groups["Chapter"] == Match.Empty) continue;
var value = match.Groups["Chapter"].Value;
- var hasChapterPart = match.Groups["ChapterPart"].Success;
-
- if (!value.Contains("-"))
- {
- return RemoveLeadingZeroes(hasChapterPart ? AddChapterPart(value) : value);
- }
-
- var tokens = value.Split("-");
- var from = RemoveLeadingZeroes(tokens[0]);
- if (tokens.Length == 2)
- {
- var to = RemoveLeadingZeroes(hasChapterPart ? AddChapterPart(tokens[1]) : tokens[1]);
- return $"{@from}-{to}";
- }
-
- return from;
-
+ var hasPart = match.Groups["Part"].Success;
+ return FormatValue(value, hasPart);
}
}
@@ -898,16 +893,8 @@ namespace API.Parser
if (match.Groups["Chapter"].Success && match.Groups["Chapter"] != Match.Empty)
{
var value = match.Groups["Chapter"].Value;
-
- if (value.Contains("-"))
- {
- var tokens = value.Split("-");
- var from = RemoveLeadingZeroes(tokens[0]);
- var to = RemoveLeadingZeroes(tokens[1]);
- return $"{from}-{to}";
- }
-
- return RemoveLeadingZeroes(match.Groups["Chapter"].Value);
+ var hasPart = match.Groups["Part"].Success;
+ return FormatValue(value, hasPart);
}
}
@@ -1026,7 +1013,7 @@ namespace API.Parser
private static string PerformPadding(string number)
{
- var num = Int32.Parse(number);
+ var num = int.Parse(number);
return num switch
{
< 10 => "00" + num,
diff --git a/UI/Web/src/app/_services/action.service.ts b/UI/Web/src/app/_services/action.service.ts
index 867e2e0f8..3d654108f 100644
--- a/UI/Web/src/app/_services/action.service.ts
+++ b/UI/Web/src/app/_services/action.service.ts
@@ -245,10 +245,10 @@ export class ActionService implements OnDestroy {
markMultipleAsUnread(seriesId: number, volumes: Array, chapters?: Array, callback?: VoidActionCallback) {
this.readerService.markMultipleUnread(seriesId, volumes.map(v => v.id), chapters?.map(c => c.id)).pipe(take(1)).subscribe(() => {
volumes.forEach(volume => {
- volume.pagesRead = volume.pages;
- volume.chapters?.forEach(c => c.pagesRead = c.pages);
+ volume.pagesRead = 0;
+ volume.chapters?.forEach(c => c.pagesRead = 0);
});
- chapters?.forEach(c => c.pagesRead = c.pages);
+ chapters?.forEach(c => c.pagesRead = 0);
this.toastr.success('Marked as Read');
if (callback) {