mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Special Marker Changes (#306)
* SP# is now a way to force the file to be a special rather than pushing it into a Specials folder. * Made it so if there is a Special (for any Parse call), volume and chapters will be ignored. * Fixed a unit test missing Theory and fixed a regex case
This commit is contained in:
parent
46b60405b1
commit
584348c6ad
@ -145,6 +145,7 @@ namespace API.Tests.Parser
|
||||
[InlineData("X-Men v1 #201 (September 2007).cbz", "X-Men")]
|
||||
[InlineData("Kodoja #001 (March 2016)", "Kodoja")]
|
||||
[InlineData("Boku No Kokoro No Yabai Yatsu - Chapter 054 I Prayed At The Shrine (V0).cbz", "Boku No Kokoro No Yabai Yatsu")]
|
||||
[InlineData("Kiss x Sis - Ch.36 - A Cold Home Visit.cbz", "Kiss x Sis")]
|
||||
public void ParseSeriesTest(string filename, string expected)
|
||||
{
|
||||
Assert.Equal(expected, API.Parser.Parser.ParseSeries(filename));
|
||||
@ -242,8 +243,8 @@ namespace API.Tests.Parser
|
||||
[InlineData("Gifting The Wonderful World With Blessings! - 3 Side Stories [yuNS][Unknown]", true)]
|
||||
[InlineData("A Town Where You Live - Bonus Chapter.zip", true)]
|
||||
[InlineData("Yuki Merry - 4-Komga Anthology", false)]
|
||||
[InlineData("Beastars - SP01", true)]
|
||||
[InlineData("Beastars SP01", true)]
|
||||
[InlineData("Beastars - SP01", false)]
|
||||
[InlineData("Beastars SP01", false)]
|
||||
public void ParseMangaSpecialTest(string input, bool expected)
|
||||
{
|
||||
Assert.Equal(expected, !string.IsNullOrEmpty(API.Parser.Parser.ParseMangaSpecial(input)));
|
||||
|
@ -5,6 +5,16 @@ namespace API.Tests.Parser
|
||||
{
|
||||
public class ParserTests
|
||||
{
|
||||
|
||||
[Theory]
|
||||
[InlineData("Beastars - SP01", true)]
|
||||
[InlineData("Beastars SP01", true)]
|
||||
[InlineData("Beastars Special 01", false)]
|
||||
[InlineData("Beastars Extra 01", false)]
|
||||
public void HasSpecialTest(string input, bool expected)
|
||||
{
|
||||
Assert.Equal(expected, HasSpecialMarker(input));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("0001", "1")]
|
||||
|
@ -9,9 +9,12 @@ namespace API.Parser
|
||||
{
|
||||
public static class Parser
|
||||
{
|
||||
public static readonly string ArchiveFileExtensions = @"\.cbz|\.zip|\.rar|\.cbr|\.tar.gz|\.7zip|\.7z|.cb7";
|
||||
public static readonly string BookFileExtensions = @"\.epub";
|
||||
public static readonly string ImageFileExtensions = @"^(\.png|\.jpeg|\.jpg)";
|
||||
public const string DefaultChapter = "0";
|
||||
public const string DefaultVolume = "0";
|
||||
|
||||
public const string ArchiveFileExtensions = @"\.cbz|\.zip|\.rar|\.cbr|\.tar.gz|\.7zip|\.7z|.cb7";
|
||||
public const string BookFileExtensions = @"\.epub";
|
||||
public const string ImageFileExtensions = @"^(\.png|\.jpeg|\.jpg)";
|
||||
public static readonly Regex FontSrcUrlRegex = new Regex("(src:url\\(\"?'?)([a-z0-9/\\._]+)(\"?'?\\))", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
public static readonly Regex CssImportUrlRegex = new Regex("(@import\\s[\"|'])(?<Filename>[\\w\\d/\\._-]+)([\"|'];?)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
@ -92,7 +95,7 @@ namespace API.Parser
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
// Historys Strongest Disciple Kenichi_v11_c90-98.zip, Killing Bites Vol. 0001 Ch. 0001 - Galactica Scanlations (gb)
|
||||
new Regex(
|
||||
@"(?<Series>.*) (\b|_|-)v",
|
||||
@"(?<Series>.*) (\b|_|-)(v|ch\.?|c)\d+",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
//Ichinensei_ni_Nacchattara_v01_ch01_[Taruby]_v1.1.zip must be before [Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.1.zip
|
||||
// due to duplicate version identifiers in file.
|
||||
@ -374,12 +377,14 @@ namespace API.Parser
|
||||
new Regex(
|
||||
@"(?<Special>Specials?|OneShot|One\-Shot|Omake|Extra( Chapter)?|Art Collection|Side( |_)Stories|Bonus)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
// If SP\d+ is in the filename, we force treat it as a special regardless if volume or chapter might have been found.
|
||||
new Regex(
|
||||
@"(?<Special>SP\d+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
};
|
||||
|
||||
// If SP\d+ is in the filename, we force treat it as a special regardless if volume or chapter might have been found.
|
||||
private static readonly Regex SpecialMarkerRegex = new Regex(
|
||||
@"(?<Special>SP\d+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled
|
||||
);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Parses information out of a file path. Will fallback to using directory name if Series couldn't be parsed
|
||||
@ -428,7 +433,7 @@ namespace API.Parser
|
||||
{
|
||||
var folder = fallbackFolders[i];
|
||||
if (!string.IsNullOrEmpty(ParseMangaSpecial(folder))) continue;
|
||||
if (ParseVolume(folder) != "0" || ParseChapter(folder) != "0") continue;
|
||||
if (ParseVolume(folder) != DefaultVolume || ParseChapter(folder) != DefaultChapter) continue;
|
||||
|
||||
var series = ParseSeries(folder);
|
||||
|
||||
@ -457,10 +462,17 @@ namespace API.Parser
|
||||
var isSpecial = ParseMangaSpecial(fileName);
|
||||
// We must ensure that we can only parse a special out. As some files will have v20 c171-180+Omake and that
|
||||
// could cause a problem as Omake is a special term, but there is valid volume/chapter information.
|
||||
if (ret.Chapters == "0" && ret.Volumes == "0" && !string.IsNullOrEmpty(isSpecial))
|
||||
if (ret.Chapters == DefaultChapter && ret.Volumes == DefaultVolume && !string.IsNullOrEmpty(isSpecial))
|
||||
{
|
||||
ret.IsSpecial = true;
|
||||
}
|
||||
|
||||
if (HasSpecialMarker(fileName))
|
||||
{
|
||||
ret.IsSpecial = true;
|
||||
ret.Chapters = DefaultChapter;
|
||||
ret.Volumes = DefaultVolume;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -495,6 +507,25 @@ namespace API.Parser
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the file has SP marker.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasSpecialMarker(string filePath)
|
||||
{
|
||||
var matches = SpecialMarkerRegex.Matches(filePath);
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
if (match.Groups["Special"].Success && match.Groups["Special"].Value != string.Empty)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static string ParseMangaSpecial(string filePath)
|
||||
{
|
||||
foreach (var regex in MangaSpecialRegex)
|
||||
@ -564,7 +595,7 @@ namespace API.Parser
|
||||
}
|
||||
}
|
||||
|
||||
return "0";
|
||||
return DefaultVolume;
|
||||
}
|
||||
|
||||
public static string ParseComicVolume(string filename)
|
||||
@ -586,7 +617,7 @@ namespace API.Parser
|
||||
}
|
||||
}
|
||||
|
||||
return "0";
|
||||
return DefaultVolume;
|
||||
}
|
||||
|
||||
public static string ParseChapter(string filename)
|
||||
@ -614,7 +645,7 @@ namespace API.Parser
|
||||
}
|
||||
}
|
||||
|
||||
return "0";
|
||||
return DefaultChapter;
|
||||
}
|
||||
|
||||
private static string AddChapterPart(string value)
|
||||
@ -652,7 +683,7 @@ namespace API.Parser
|
||||
}
|
||||
}
|
||||
|
||||
return "0";
|
||||
return DefaultChapter;
|
||||
}
|
||||
|
||||
private static string RemoveEditionTagHolders(string title)
|
||||
|
@ -3,7 +3,7 @@
|
||||
namespace API.Parser
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents a single file
|
||||
/// This represents all parsed information from a single file
|
||||
/// </summary>
|
||||
public class ParserInfo
|
||||
{
|
||||
|
@ -466,7 +466,7 @@ namespace API.Services.Tasks
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == LibraryType.Book && Parser.Parser.IsEpub(path) && Parser.Parser.ParseVolume(info.Series) != "0")
|
||||
if (type == LibraryType.Book && Parser.Parser.IsEpub(path) && Parser.Parser.ParseVolume(info.Series) != Parser.Parser.DefaultVolume)
|
||||
{
|
||||
info = Parser.Parser.Parse(path, rootPath, type);
|
||||
var info2 = _bookService.ParseInfo(path);
|
||||
|
Loading…
x
Reference in New Issue
Block a user