diff --git a/API.Tests/ParserTest.cs b/API.Tests/ParserTest.cs
index 392cbd15d..6e126c2d8 100644
--- a/API.Tests/ParserTest.cs
+++ b/API.Tests/ParserTest.cs
@@ -303,6 +303,7 @@ namespace API.Tests
[InlineData("Scott Pilgrim 01 - Scott Pilgrim's Precious Little Life (2004)", "1")]
[InlineData("Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus)", "1")]
[InlineData("Scott Pilgrim 02 - Scott Pilgrim vs. The World (2005)", "2")]
+ [InlineData("Superman v1 024 (09-10 1943)", "1")]
public void ParseComicVolumeTest(string filename, string expected)
{
Assert.Equal(expected, ParseComicVolume(filename));
@@ -322,6 +323,7 @@ namespace API.Tests
[InlineData("Babe 01", "0")]
[InlineData("Scott Pilgrim 01 - Scott Pilgrim's Precious Little Life (2004)", "0")]
[InlineData("Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus)", "1")]
+ [InlineData("Superman v1 024 (09-10 1943)", "24")]
public void ParseComicChapterTest(string filename, string expected)
{
Assert.Equal(expected, ParseComicChapter(filename));
@@ -336,6 +338,22 @@ namespace API.Tests
{
Assert.Equal(expected, IsImage(filename));
}
+
+ [Theory]
+ [InlineData("C:/", "C:/Love Hina/Love Hina - Special.cbz", "Love Hina")]
+ [InlineData("C:/", "C:/Love Hina/Specials/Ani-Hina Art Collection.cbz", "Love Hina")]
+ [InlineData("C:/", "C:/Mujaki no Rakuen Something/Mujaki no Rakuen Vol12 ch76.cbz", "Mujaki no Rakuen")]
+ public void FallbackTest(string rootDir, string inputPath, string expectedSeries)
+ {
+ var actual = Parse(inputPath, rootDir);
+ if (actual == null)
+ {
+ Assert.NotNull(actual);
+ return;
+ }
+
+ Assert.Equal(expectedSeries, actual.Series);
+ }
[Fact]
diff --git a/API.Tests/Services/DirectoryServiceTests.cs b/API.Tests/Services/DirectoryServiceTests.cs
index 39ff717c5..7c21ae927 100644
--- a/API.Tests/Services/DirectoryServiceTests.cs
+++ b/API.Tests/Services/DirectoryServiceTests.cs
@@ -74,5 +74,17 @@ namespace API.Tests.Services
Assert.DoesNotContain(dirs, s => s.Contains("regex"));
}
+
+ [Theory]
+ [InlineData("C:/Manga/", "C:/Manga/Love Hina/Specials/Omake/", "Omake,Specials,Love Hina")]
+ [InlineData("C:/Manga/", "C:/Manga/Love Hina/Specials/Omake", "Omake,Specials,Love Hina")]
+ [InlineData("C:/Manga", "C:/Manga/Love Hina/Specials/Omake/", "Omake,Specials,Love Hina")]
+ [InlineData("C:/Manga", @"C:\Manga\Love Hina\Specials\Omake\", "Omake,Specials,Love Hina")]
+ [InlineData(@"/manga/", @"/manga/Love Hina/Specials/Omake/", "Omake,Specials,Love Hina")]
+ public void GetFoldersTillRoot_Test(string rootPath, string fullpath, string expectedArray)
+ {
+ var expected = expectedArray.Split(",");
+ Assert.Equal(expected, DirectoryService.GetFoldersTillRoot(rootPath, fullpath));
+ }
}
}
\ No newline at end of file
diff --git a/API/Parser/Parser.cs b/API/Parser/Parser.cs
index 1a9ac444b..b064a536e 100644
--- a/API/Parser/Parser.cs
+++ b/API/Parser/Parser.cs
@@ -3,6 +3,7 @@ using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using API.Entities.Enums;
+using API.Services;
namespace API.Parser
{
@@ -343,9 +344,7 @@ namespace API.Parser
public static ParserInfo Parse(string filePath, string rootPath, LibraryType type = LibraryType.Manga)
{
var fileName = Path.GetFileName(filePath);
- var directoryName = (new FileInfo(filePath)).Directory?.Name;
- var rootName = (new DirectoryInfo(rootPath)).Name;
-
+
var ret = new ParserInfo()
{
Chapters = type == LibraryType.Manga ? ParseChapter(fileName) : ParseComicChapter(fileName),
@@ -355,11 +354,32 @@ namespace API.Parser
Format = ParseFormat(filePath),
FullFilePath = filePath
};
-
- if (ret.Series == string.Empty && directoryName != null && directoryName != rootName)
+
+ if (ret.Series == string.Empty)
{
- ret.Series = ParseSeries(directoryName);
- if (ret.Series == string.Empty) ret.Series = CleanTitle(directoryName);
+ // Try to parse information out of each folder all the way to rootPath
+ var fallbackFolders = DirectoryService.GetFoldersTillRoot(rootPath, Path.GetDirectoryName(filePath)).ToList();
+ for (var i = 0; i < fallbackFolders.Count; i++)
+ {
+ var folder = fallbackFolders[i];
+ if (!string.IsNullOrEmpty(ParseMangaSpecial(folder))) continue;
+ if (ParseVolume(folder) != "0" || ParseChapter(folder) != "0") continue;
+
+ var series = ParseSeries(folder);
+
+ if ((string.IsNullOrEmpty(series) && i == fallbackFolders.Count - 1))
+ {
+ ret.Series = CleanTitle(folder);
+ break;
+ }
+
+ if (!string.IsNullOrEmpty(series))
+ {
+ ret.Series = series;
+ break;
+ }
+ }
+
}
var edition = ParseEdition(fileName);
@@ -562,7 +582,7 @@ namespace API.Parser
{
if (match.Success)
{
- title = title.Replace(match.Value, "");
+ title = title.Replace(match.Value, "").Trim();
}
}
}
@@ -574,7 +594,7 @@ namespace API.Parser
{
if (match.Success)
{
- title = title.Replace(match.Value, "");
+ title = title.Replace(match.Value, "").Trim();
}
}
}
@@ -591,7 +611,7 @@ namespace API.Parser
{
if (match.Success)
{
- title = title.Replace(match.Value, "");
+ title = title.Replace(match.Value, "").Trim();
}
}
}
diff --git a/API/Services/DirectoryService.cs b/API/Services/DirectoryService.cs
index 7ba691bc9..69a1b17dd 100644
--- a/API/Services/DirectoryService.cs
+++ b/API/Services/DirectoryService.cs
@@ -40,6 +40,40 @@ namespace API.Services
reSearchPattern.IsMatch(Path.GetExtension(file)));
}
+ ///
+ /// Returns a list of folders from end of fullPath to rootPath.
+ ///
+ /// Example) (C:/Manga/, C:/Manga/Love Hina/Specials/Omake/) returns [Omake, Specials, Love Hina]
+ ///
+ ///
+ ///
+ ///
+ public static IEnumerable GetFoldersTillRoot(string rootPath, string fullPath)
+ {
+ var separator = Path.AltDirectorySeparatorChar;
+ if (fullPath.Contains(Path.DirectorySeparatorChar))
+ {
+ fullPath = fullPath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
+ }
+
+ if (rootPath.Contains(Path.DirectorySeparatorChar))
+ {
+ rootPath = rootPath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
+ }
+
+ var path = fullPath.EndsWith(separator) ? fullPath.Substring(0, fullPath.Length - 1) : fullPath;
+ var root = rootPath.EndsWith(separator) ? rootPath.Substring(0, rootPath.Length - 1) : rootPath;
+ var paths = new List();
+ while (Path.GetDirectoryName(path) != Path.GetDirectoryName(root))
+ {
+ var folder = new DirectoryInfo(path).Name;
+ paths.Add(folder);
+ path = path.Replace(separator + folder, string.Empty);
+ }
+
+ return paths;
+ }
+
public bool Exists(string directory)
{
var di = new DirectoryInfo(directory);