mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Scan Loop Last Write Time Change (#1492)
* Refactored invite user flow to separate error handling on create user flow and email flow. This should help users that have unique situations. * Switch to using files to check LastWriteTime. Debug code in for Robbie to test on rclone * Updated Parser namespace. Changed the LastWriteTime to check all files and folders.
This commit is contained in:
parent
521b2adc14
commit
85790dd71c
@ -12,7 +12,7 @@ namespace API.Tests.Entities
|
|||||||
[InlineData("Darker than Black")]
|
[InlineData("Darker than Black")]
|
||||||
public void CreateSeries(string name)
|
public void CreateSeries(string name)
|
||||||
{
|
{
|
||||||
var key = API.Parser.Parser.Normalize(name);
|
var key = API.Services.Tasks.Scanner.Parser.Parser.Normalize(name);
|
||||||
var series = DbFactory.Series(name);
|
var series = DbFactory.Series(name);
|
||||||
Assert.Equal(0, series.Id);
|
Assert.Equal(0, series.Id);
|
||||||
Assert.Equal(0, series.Pages);
|
Assert.Equal(0, series.Pages);
|
||||||
|
@ -28,7 +28,7 @@ namespace API.Tests.Extensions
|
|||||||
Name = seriesInput[0],
|
Name = seriesInput[0],
|
||||||
LocalizedName = seriesInput[1],
|
LocalizedName = seriesInput[1],
|
||||||
OriginalName = seriesInput[2],
|
OriginalName = seriesInput[2],
|
||||||
NormalizedName = seriesInput.Length == 4 ? seriesInput[3] : API.Parser.Parser.Normalize(seriesInput[0]),
|
NormalizedName = seriesInput.Length == 4 ? seriesInput[3] : API.Services.Tasks.Scanner.Parser.Parser.Normalize(seriesInput[0]),
|
||||||
Metadata = new SeriesMetadata()
|
Metadata = new SeriesMetadata()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,14 +52,14 @@ namespace API.Tests.Extensions
|
|||||||
Name = seriesInput[0],
|
Name = seriesInput[0],
|
||||||
LocalizedName = seriesInput[1],
|
LocalizedName = seriesInput[1],
|
||||||
OriginalName = seriesInput[2],
|
OriginalName = seriesInput[2],
|
||||||
NormalizedName = seriesInput.Length == 4 ? seriesInput[3] : API.Parser.Parser.Normalize(seriesInput[0]),
|
NormalizedName = seriesInput.Length == 4 ? seriesInput[3] : API.Services.Tasks.Scanner.Parser.Parser.Normalize(seriesInput[0]),
|
||||||
Metadata = new SeriesMetadata(),
|
Metadata = new SeriesMetadata(),
|
||||||
};
|
};
|
||||||
|
|
||||||
var parserInfos = list.Select(s => new ParsedSeries()
|
var parserInfos = list.Select(s => new ParsedSeries()
|
||||||
{
|
{
|
||||||
Name = s,
|
Name = s,
|
||||||
NormalizedName = API.Parser.Parser.Normalize(s),
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize(s),
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
// This doesn't do any checks against format
|
// This doesn't do any checks against format
|
||||||
@ -78,7 +78,7 @@ namespace API.Tests.Extensions
|
|||||||
Name = seriesInput[0],
|
Name = seriesInput[0],
|
||||||
LocalizedName = seriesInput[1],
|
LocalizedName = seriesInput[1],
|
||||||
OriginalName = seriesInput[2],
|
OriginalName = seriesInput[2],
|
||||||
NormalizedName = seriesInput.Length == 4 ? seriesInput[3] : API.Parser.Parser.Normalize(seriesInput[0]),
|
NormalizedName = seriesInput.Length == 4 ? seriesInput[3] : API.Services.Tasks.Scanner.Parser.Parser.Normalize(seriesInput[0]),
|
||||||
Metadata = new SeriesMetadata()
|
Metadata = new SeriesMetadata()
|
||||||
};
|
};
|
||||||
var info = new ParserInfo();
|
var info = new ParserInfo();
|
||||||
|
@ -18,7 +18,7 @@ namespace API.Tests.Helpers
|
|||||||
Name = name,
|
Name = name,
|
||||||
SortName = name,
|
SortName = name,
|
||||||
LocalizedName = name,
|
LocalizedName = name,
|
||||||
NormalizedName = API.Parser.Parser.Normalize(name),
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize(name),
|
||||||
Volumes = new List<Volume>(),
|
Volumes = new List<Volume>(),
|
||||||
Metadata = new SeriesMetadata()
|
Metadata = new SeriesMetadata()
|
||||||
};
|
};
|
||||||
@ -31,7 +31,7 @@ namespace API.Tests.Helpers
|
|||||||
return new Volume()
|
return new Volume()
|
||||||
{
|
{
|
||||||
Name = volumeNumber,
|
Name = volumeNumber,
|
||||||
Number = (int) API.Parser.Parser.MinNumberFromRange(volumeNumber),
|
Number = (int) API.Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(volumeNumber),
|
||||||
Pages = pages,
|
Pages = pages,
|
||||||
Chapters = chaps
|
Chapters = chaps
|
||||||
};
|
};
|
||||||
@ -43,7 +43,7 @@ namespace API.Tests.Helpers
|
|||||||
{
|
{
|
||||||
IsSpecial = isSpecial,
|
IsSpecial = isSpecial,
|
||||||
Range = range,
|
Range = range,
|
||||||
Number = API.Parser.Parser.MinNumberFromRange(range) + string.Empty,
|
Number = API.Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(range) + string.Empty,
|
||||||
Files = files ?? new List<MangaFile>(),
|
Files = files ?? new List<MangaFile>(),
|
||||||
Pages = pageCount,
|
Pages = pageCount,
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ namespace API.Tests.Helpers
|
|||||||
return new CollectionTag()
|
return new CollectionTag()
|
||||||
{
|
{
|
||||||
Id = id,
|
Id = id,
|
||||||
NormalizedTitle = API.Parser.Parser.Normalize(title).ToUpper(),
|
NormalizedTitle = API.Services.Tasks.Scanner.Parser.Parser.Normalize(title).ToUpper(),
|
||||||
Title = title,
|
Title = title,
|
||||||
Summary = summary,
|
Summary = summary,
|
||||||
Promoted = promoted
|
Promoted = promoted
|
||||||
|
@ -29,12 +29,12 @@ namespace API.Tests.Helpers
|
|||||||
public static void AddToParsedInfo(IDictionary<ParsedSeries, IList<ParserInfo>> collectedSeries, ParserInfo info)
|
public static void AddToParsedInfo(IDictionary<ParsedSeries, IList<ParserInfo>> collectedSeries, ParserInfo info)
|
||||||
{
|
{
|
||||||
var existingKey = collectedSeries.Keys.FirstOrDefault(ps =>
|
var existingKey = collectedSeries.Keys.FirstOrDefault(ps =>
|
||||||
ps.Format == info.Format && ps.NormalizedName == API.Parser.Parser.Normalize(info.Series));
|
ps.Format == info.Format && ps.NormalizedName == API.Services.Tasks.Scanner.Parser.Parser.Normalize(info.Series));
|
||||||
existingKey ??= new ParsedSeries()
|
existingKey ??= new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = info.Format,
|
Format = info.Format,
|
||||||
Name = info.Series,
|
Name = info.Series,
|
||||||
NormalizedName = API.Parser.Parser.Normalize(info.Series)
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize(info.Series)
|
||||||
};
|
};
|
||||||
if (collectedSeries.GetType() == typeof(ConcurrentDictionary<,>))
|
if (collectedSeries.GetType() == typeof(ConcurrentDictionary<,>))
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ public class ParserInfoHelperTests
|
|||||||
Name = "1"
|
Name = "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Darker Than Black"),
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker Than Black"),
|
||||||
Metadata = new SeriesMetadata(),
|
Metadata = new SeriesMetadata(),
|
||||||
Format = MangaFormat.Epub
|
Format = MangaFormat.Epub
|
||||||
};
|
};
|
||||||
@ -63,7 +63,7 @@ public class ParserInfoHelperTests
|
|||||||
Name = "1"
|
Name = "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Darker Than Black"),
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker Than Black"),
|
||||||
Metadata = new SeriesMetadata(),
|
Metadata = new SeriesMetadata(),
|
||||||
Format = MangaFormat.Epub
|
Format = MangaFormat.Epub
|
||||||
};
|
};
|
||||||
|
@ -22,21 +22,21 @@ public class SeriesHelperTests
|
|||||||
{
|
{
|
||||||
Format = MangaFormat.Archive,
|
Format = MangaFormat.Archive,
|
||||||
Name = "Darker than Black",
|
Name = "Darker than Black",
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Darker than Black")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = MangaFormat.Archive,
|
Format = MangaFormat.Archive,
|
||||||
Name = "Darker than Black".ToLower(),
|
Name = "Darker than Black".ToLower(),
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Darker than Black")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = MangaFormat.Archive,
|
Format = MangaFormat.Archive,
|
||||||
Name = "Darker than Black".ToUpper(),
|
Name = "Darker than Black".ToUpper(),
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Darker than Black")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,21 +50,21 @@ public class SeriesHelperTests
|
|||||||
{
|
{
|
||||||
Format = MangaFormat.Image,
|
Format = MangaFormat.Image,
|
||||||
Name = "Darker than Black",
|
Name = "Darker than Black",
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Darker than Black")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Assert.False(SeriesHelper.FindSeries(series, new ParsedSeries()
|
Assert.False(SeriesHelper.FindSeries(series, new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = MangaFormat.Image,
|
Format = MangaFormat.Image,
|
||||||
Name = "Darker than Black".ToLower(),
|
Name = "Darker than Black".ToLower(),
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Darker than Black")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Assert.False(SeriesHelper.FindSeries(series, new ParsedSeries()
|
Assert.False(SeriesHelper.FindSeries(series, new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = MangaFormat.Image,
|
Format = MangaFormat.Image,
|
||||||
Name = "Darker than Black".ToUpper(),
|
Name = "Darker than Black".ToUpper(),
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Darker than Black")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,28 +78,28 @@ public class SeriesHelperTests
|
|||||||
{
|
{
|
||||||
Format = MangaFormat.Image,
|
Format = MangaFormat.Image,
|
||||||
Name = "Something Random",
|
Name = "Something Random",
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Something Random")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = MangaFormat.Image,
|
Format = MangaFormat.Image,
|
||||||
Name = "Something Random".ToLower(),
|
Name = "Something Random".ToLower(),
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Something Random")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = MangaFormat.Image,
|
Format = MangaFormat.Image,
|
||||||
Name = "Something Random".ToUpper(),
|
Name = "Something Random".ToUpper(),
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Something Random")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = MangaFormat.Image,
|
Format = MangaFormat.Image,
|
||||||
Name = "SomethingRandom".ToUpper(),
|
Name = "SomethingRandom".ToUpper(),
|
||||||
NormalizedName = API.Parser.Parser.Normalize("SomethingRandom")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("SomethingRandom")
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,28 +113,28 @@ public class SeriesHelperTests
|
|||||||
{
|
{
|
||||||
Format = MangaFormat.Image,
|
Format = MangaFormat.Image,
|
||||||
Name = "Something Random",
|
Name = "Something Random",
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Something Random")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = MangaFormat.Image,
|
Format = MangaFormat.Image,
|
||||||
Name = "Something Random".ToLower(),
|
Name = "Something Random".ToLower(),
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Something Random")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = MangaFormat.Image,
|
Format = MangaFormat.Image,
|
||||||
Name = "Something Random".ToUpper(),
|
Name = "Something Random".ToUpper(),
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Something Random")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = MangaFormat.Image,
|
Format = MangaFormat.Image,
|
||||||
Name = "SomethingRandom".ToUpper(),
|
Name = "SomethingRandom".ToUpper(),
|
||||||
NormalizedName = API.Parser.Parser.Normalize("SomethingRandom")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("SomethingRandom")
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,14 +148,14 @@ public class SeriesHelperTests
|
|||||||
{
|
{
|
||||||
Format = MangaFormat.Archive,
|
Format = MangaFormat.Archive,
|
||||||
Name = "My Dress-Up Darling",
|
Name = "My Dress-Up Darling",
|
||||||
NormalizedName = API.Parser.Parser.Normalize("My Dress-Up Darling")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("My Dress-Up Darling")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
|
||||||
{
|
{
|
||||||
Format = MangaFormat.Archive,
|
Format = MangaFormat.Archive,
|
||||||
Name = "Sono Bisque Doll wa Koi wo Suru".ToLower(),
|
Name = "Sono Bisque Doll wa Koi wo Suru".ToLower(),
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Sono Bisque Doll wa Koi wo Suru")
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Sono Bisque Doll wa Koi wo Suru")
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -10,7 +10,7 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("Faust - Volume 01 [Del Rey][Scans_Compressed]", "Faust")]
|
[InlineData("Faust - Volume 01 [Del Rey][Scans_Compressed]", "Faust")]
|
||||||
public void ParseSeriesTest(string filename, string expected)
|
public void ParseSeriesTest(string filename, string expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, API.Parser.Parser.ParseSeries(filename));
|
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseSeries(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@ -18,7 +18,7 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("Faust - Volume 01 [Del Rey][Scans_Compressed]", "1")]
|
[InlineData("Faust - Volume 01 [Del Rey][Scans_Compressed]", "1")]
|
||||||
public void ParseVolumeTest(string filename, string expected)
|
public void ParseVolumeTest(string filename, string expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, API.Parser.Parser.ParseVolume(filename));
|
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseVolume(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
// [Theory]
|
// [Theory]
|
||||||
|
@ -79,7 +79,7 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("Fables 2010 Vol. 1 Legends in Exile", "Fables 2010")]
|
[InlineData("Fables 2010 Vol. 1 Legends in Exile", "Fables 2010")]
|
||||||
public void ParseComicSeriesTest(string filename, string expected)
|
public void ParseComicSeriesTest(string filename, string expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, API.Parser.Parser.ParseComicSeries(filename));
|
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseComicSeries(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@ -126,7 +126,7 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("Adventure Time TPB (2012)/Adventure Time v01 (2012).cbz", "1")]
|
[InlineData("Adventure Time TPB (2012)/Adventure Time v01 (2012).cbz", "1")]
|
||||||
public void ParseComicVolumeTest(string filename, string expected)
|
public void ParseComicVolumeTest(string filename, string expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, API.Parser.Parser.ParseComicVolume(filename));
|
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseComicVolume(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@ -171,7 +171,7 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("Adventure Time TPB (2012)/Adventure Time v01 (2012).cbz", "0")]
|
[InlineData("Adventure Time TPB (2012)/Adventure Time v01 (2012).cbz", "0")]
|
||||||
public void ParseComicChapterTest(string filename, string expected)
|
public void ParseComicChapterTest(string filename, string expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, API.Parser.Parser.ParseComicChapter(filename));
|
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseComicChapter(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -190,7 +190,7 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("Adventure Time 2013_-_Annual #001 (2013)", true)]
|
[InlineData("Adventure Time 2013_-_Annual #001 (2013)", true)]
|
||||||
public void ParseComicSpecialTest(string input, bool expected)
|
public void ParseComicSpecialTest(string input, bool expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, !string.IsNullOrEmpty(API.Parser.Parser.ParseComicSpecial(input)));
|
Assert.Equal(expected, !string.IsNullOrEmpty(API.Services.Tasks.Scanner.Parser.Parser.ParseComicSpecial(input)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("スライム倒して300年、知らないうちにレベルMAXになってました 1-3巻", "1-3")]
|
[InlineData("スライム倒して300年、知らないうちにレベルMAXになってました 1-3巻", "1-3")]
|
||||||
public void ParseVolumeTest(string filename, string expected)
|
public void ParseVolumeTest(string filename, string expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, API.Parser.Parser.ParseVolume(filename));
|
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseVolume(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@ -183,7 +183,7 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("Highschool of the Dead - 02", "Highschool of the Dead")]
|
[InlineData("Highschool of the Dead - 02", "Highschool of the Dead")]
|
||||||
public void ParseSeriesTest(string filename, string expected)
|
public void ParseSeriesTest(string filename, string expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, API.Parser.Parser.ParseSeries(filename));
|
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseSeries(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@ -261,7 +261,7 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("[ハレム]ナナとカオル ~高校生のSMごっこ~ 第10話", "10")]
|
[InlineData("[ハレム]ナナとカオル ~高校生のSMごっこ~ 第10話", "10")]
|
||||||
public void ParseChaptersTest(string filename, string expected)
|
public void ParseChaptersTest(string filename, string expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, API.Parser.Parser.ParseChapter(filename));
|
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseChapter(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -277,7 +277,7 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("Love Hina Omnibus v05 (2015) (Digital-HD) (Asgard-Empire).cbz", "Omnibus")]
|
[InlineData("Love Hina Omnibus v05 (2015) (Digital-HD) (Asgard-Empire).cbz", "Omnibus")]
|
||||||
public void ParseEditionTest(string input, string expected)
|
public void ParseEditionTest(string input, string expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, API.Parser.Parser.ParseEdition(input));
|
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseEdition(input));
|
||||||
}
|
}
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("Beelzebub Special OneShot - Minna no Kochikame x Beelzebub (2016) [Mangastream].cbz", true)]
|
[InlineData("Beelzebub Special OneShot - Minna no Kochikame x Beelzebub (2016) [Mangastream].cbz", true)]
|
||||||
@ -296,7 +296,7 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("The League of Extra-ordinary Gentlemen", false)]
|
[InlineData("The League of Extra-ordinary Gentlemen", false)]
|
||||||
public void ParseMangaSpecialTest(string input, bool expected)
|
public void ParseMangaSpecialTest(string input, bool expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, !string.IsNullOrEmpty(API.Parser.Parser.ParseMangaSpecial(input)));
|
Assert.Equal(expected, !string.IsNullOrEmpty(API.Services.Tasks.Scanner.Parser.Parser.ParseMangaSpecial(input)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@ -305,14 +305,14 @@ namespace API.Tests.Parser
|
|||||||
[InlineData("image.txt", MangaFormat.Unknown)]
|
[InlineData("image.txt", MangaFormat.Unknown)]
|
||||||
public void ParseFormatTest(string inputFile, MangaFormat expected)
|
public void ParseFormatTest(string inputFile, MangaFormat expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, API.Parser.Parser.ParseFormat(inputFile));
|
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseFormat(inputFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("Gifting The Wonderful World With Blessings! - 3 Side Stories [yuNS][Unknown].epub", "Side Stories")]
|
[InlineData("Gifting The Wonderful World With Blessings! - 3 Side Stories [yuNS][Unknown].epub", "Side Stories")]
|
||||||
public void ParseSpecialTest(string inputFile, string expected)
|
public void ParseSpecialTest(string inputFile, string expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, API.Parser.Parser.ParseMangaSpecial(inputFile));
|
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseMangaSpecial(inputFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using static API.Parser.Parser;
|
using static API.Services.Tasks.Scanner.Parser.Parser;
|
||||||
|
|
||||||
namespace API.Tests.Parser
|
namespace API.Tests.Parser
|
||||||
{
|
{
|
||||||
|
@ -198,7 +198,7 @@ namespace API.Tests.Services
|
|||||||
var imageService = new ImageService(Substitute.For<ILogger<ImageService>>(), _directoryService);
|
var imageService = new ImageService(Substitute.For<ILogger<ImageService>>(), _directoryService);
|
||||||
var archiveService = Substitute.For<ArchiveService>(_logger,
|
var archiveService = Substitute.For<ArchiveService>(_logger,
|
||||||
new DirectoryService(_directoryServiceLogger, new FileSystem()), imageService);
|
new DirectoryService(_directoryServiceLogger, new FileSystem()), imageService);
|
||||||
var testDirectory = API.Parser.Parser.NormalizePath(Path.GetFullPath(Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/CoverImages")));
|
var testDirectory = API.Services.Tasks.Scanner.Parser.Parser.NormalizePath(Path.GetFullPath(Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/CoverImages")));
|
||||||
|
|
||||||
var outputDir = Path.Join(testDirectory, "output");
|
var outputDir = Path.Join(testDirectory, "output");
|
||||||
_directoryService.ClearDirectory(outputDir);
|
_directoryService.ClearDirectory(outputDir);
|
||||||
|
@ -147,7 +147,7 @@ public class BackupServiceTests
|
|||||||
|
|
||||||
var backupLogFiles = backupService.GetLogFiles(0, LogDirectory).ToList();
|
var backupLogFiles = backupService.GetLogFiles(0, LogDirectory).ToList();
|
||||||
Assert.Single(backupLogFiles);
|
Assert.Single(backupLogFiles);
|
||||||
Assert.Equal(API.Parser.Parser.NormalizePath($"{LogDirectory}kavita.log"), API.Parser.Parser.NormalizePath(backupLogFiles.First()));
|
Assert.Equal(API.Services.Tasks.Scanner.Parser.Parser.NormalizePath($"{LogDirectory}kavita.log"), API.Services.Tasks.Scanner.Parser.Parser.NormalizePath(backupLogFiles.First()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -168,8 +168,8 @@ public class BackupServiceTests
|
|||||||
|
|
||||||
var backupService = new BackupService(_logger, _unitOfWork, ds, configuration, _messageHub);
|
var backupService = new BackupService(_logger, _unitOfWork, ds, configuration, _messageHub);
|
||||||
|
|
||||||
var backupLogFiles = backupService.GetLogFiles(1, LogDirectory).Select(API.Parser.Parser.NormalizePath).ToList();
|
var backupLogFiles = backupService.GetLogFiles(1, LogDirectory).Select(API.Services.Tasks.Scanner.Parser.Parser.NormalizePath).ToList();
|
||||||
Assert.NotEmpty(backupLogFiles.Where(file => file.Equals(API.Parser.Parser.NormalizePath($"{LogDirectory}kavita.log")) || file.Equals(API.Parser.Parser.NormalizePath($"{LogDirectory}kavita1.log"))));
|
Assert.NotEmpty(backupLogFiles.Where(file => file.Equals(API.Services.Tasks.Scanner.Parser.Parser.NormalizePath($"{LogDirectory}kavita.log")) || file.Equals(API.Services.Tasks.Scanner.Parser.Parser.NormalizePath($"{LogDirectory}kavita1.log"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -401,7 +401,7 @@ public class BookmarkServiceTests
|
|||||||
|
|
||||||
var files = await bookmarkService.GetBookmarkFilesById(new[] {1});
|
var files = await bookmarkService.GetBookmarkFilesById(new[] {1});
|
||||||
var actualFiles = ds.GetFiles(BookmarkDirectory, searchOption: SearchOption.AllDirectories);
|
var actualFiles = ds.GetFiles(BookmarkDirectory, searchOption: SearchOption.AllDirectories);
|
||||||
Assert.Equal(files.Select(API.Parser.Parser.NormalizePath).ToList(), actualFiles.Select(API.Parser.Parser.NormalizePath).ToList());
|
Assert.Equal(files.Select(API.Services.Tasks.Scanner.Parser.Parser.NormalizePath).ToList(), actualFiles.Select(API.Services.Tasks.Scanner.Parser.Parser.NormalizePath).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -312,13 +312,13 @@ public class CleanupServiceTests
|
|||||||
new ReadingList()
|
new ReadingList()
|
||||||
{
|
{
|
||||||
Title = "Something",
|
Title = "Something",
|
||||||
NormalizedTitle = API.Parser.Parser.Normalize("Something"),
|
NormalizedTitle = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something"),
|
||||||
CoverImage = $"{ImageService.GetReadingListFormat(1)}.jpg"
|
CoverImage = $"{ImageService.GetReadingListFormat(1)}.jpg"
|
||||||
},
|
},
|
||||||
new ReadingList()
|
new ReadingList()
|
||||||
{
|
{
|
||||||
Title = "Something 2",
|
Title = "Something 2",
|
||||||
NormalizedTitle = API.Parser.Parser.Normalize("Something 2"),
|
NormalizedTitle = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something 2"),
|
||||||
CoverImage = $"{ImageService.GetReadingListFormat(2)}.jpg"
|
CoverImage = $"{ImageService.GetReadingListFormat(2)}.jpg"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ namespace API.Tests.Services
|
|||||||
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
||||||
var files = new List<string>();
|
var files = new List<string>();
|
||||||
var fileCount = ds.TraverseTreeParallelForEach(testDirectory, s => files.Add(s),
|
var fileCount = ds.TraverseTreeParallelForEach(testDirectory, s => files.Add(s),
|
||||||
API.Parser.Parser.ArchiveFileExtensions, _logger);
|
API.Services.Tasks.Scanner.Parser.Parser.ArchiveFileExtensions, _logger);
|
||||||
|
|
||||||
Assert.Equal(28, fileCount);
|
Assert.Equal(28, fileCount);
|
||||||
Assert.Equal(28, files.Count);
|
Assert.Equal(28, files.Count);
|
||||||
@ -59,7 +59,7 @@ namespace API.Tests.Services
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var fileCount = ds.TraverseTreeParallelForEach("/manga/", s => files.Add(s),
|
var fileCount = ds.TraverseTreeParallelForEach("/manga/", s => files.Add(s),
|
||||||
API.Parser.Parser.ImageFileExtensions, _logger);
|
API.Services.Tasks.Scanner.Parser.Parser.ImageFileExtensions, _logger);
|
||||||
Assert.Equal(1, fileCount);
|
Assert.Equal(1, fileCount);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -90,7 +90,7 @@ namespace API.Tests.Services
|
|||||||
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
||||||
var files = new List<string>();
|
var files = new List<string>();
|
||||||
var fileCount = ds.TraverseTreeParallelForEach(testDirectory, s => files.Add(s),
|
var fileCount = ds.TraverseTreeParallelForEach(testDirectory, s => files.Add(s),
|
||||||
API.Parser.Parser.ArchiveFileExtensions, _logger);
|
API.Services.Tasks.Scanner.Parser.Parser.ArchiveFileExtensions, _logger);
|
||||||
|
|
||||||
Assert.Equal(28, fileCount);
|
Assert.Equal(28, fileCount);
|
||||||
Assert.Equal(28, files.Count);
|
Assert.Equal(28, files.Count);
|
||||||
@ -111,7 +111,7 @@ namespace API.Tests.Services
|
|||||||
fileSystem.AddFile($"{testDirectory}file_{29}.jpg", new MockFileData(""));
|
fileSystem.AddFile($"{testDirectory}file_{29}.jpg", new MockFileData(""));
|
||||||
|
|
||||||
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
||||||
var files = ds.GetFilesWithExtension(testDirectory, API.Parser.Parser.ArchiveFileExtensions);
|
var files = ds.GetFilesWithExtension(testDirectory, API.Services.Tasks.Scanner.Parser.Parser.ArchiveFileExtensions);
|
||||||
|
|
||||||
Assert.Equal(10, files.Length);
|
Assert.Equal(10, files.Length);
|
||||||
Assert.All(files, s => fileSystem.Path.GetExtension(s).Equals(".zip"));
|
Assert.All(files, s => fileSystem.Path.GetExtension(s).Equals(".zip"));
|
||||||
@ -150,7 +150,7 @@ namespace API.Tests.Services
|
|||||||
fileSystem.AddFile($"{testDirectory}file_{29}.jpg", new MockFileData(""));
|
fileSystem.AddFile($"{testDirectory}file_{29}.jpg", new MockFileData(""));
|
||||||
|
|
||||||
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
||||||
var files = ds.GetFiles(testDirectory, API.Parser.Parser.ArchiveFileExtensions).ToList();
|
var files = ds.GetFiles(testDirectory, API.Services.Tasks.Scanner.Parser.Parser.ArchiveFileExtensions).ToList();
|
||||||
|
|
||||||
Assert.Equal(10, files.Count());
|
Assert.Equal(10, files.Count());
|
||||||
Assert.All(files, s => fileSystem.Path.GetExtension(s).Equals(".zip"));
|
Assert.All(files, s => fileSystem.Path.GetExtension(s).Equals(".zip"));
|
||||||
@ -586,12 +586,12 @@ namespace API.Tests.Services
|
|||||||
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
||||||
ds.CopyFilesToDirectory(new []{MockUnixSupport.Path($"{testDirectory}file.zip")}, "/manga/output/");
|
ds.CopyFilesToDirectory(new []{MockUnixSupport.Path($"{testDirectory}file.zip")}, "/manga/output/");
|
||||||
ds.CopyFilesToDirectory(new []{MockUnixSupport.Path($"{testDirectory}file.zip")}, "/manga/output/");
|
ds.CopyFilesToDirectory(new []{MockUnixSupport.Path($"{testDirectory}file.zip")}, "/manga/output/");
|
||||||
var outputFiles = ds.GetFiles("/manga/output/").Select(API.Parser.Parser.NormalizePath).ToList();
|
var outputFiles = ds.GetFiles("/manga/output/").Select(API.Services.Tasks.Scanner.Parser.Parser.NormalizePath).ToList();
|
||||||
Assert.Equal(4, outputFiles.Count()); // we have 2 already there and 2 copies
|
Assert.Equal(4, outputFiles.Count()); // we have 2 already there and 2 copies
|
||||||
// For some reason, this has C:/ on directory even though everything is emulated (System.IO.Abstractions issue, not changing)
|
// For some reason, this has C:/ on directory even though everything is emulated (System.IO.Abstractions issue, not changing)
|
||||||
// https://github.com/TestableIO/System.IO.Abstractions/issues/831
|
// https://github.com/TestableIO/System.IO.Abstractions/issues/831
|
||||||
Assert.True(outputFiles.Contains(API.Parser.Parser.NormalizePath("/manga/output/file (3).zip"))
|
Assert.True(outputFiles.Contains(API.Services.Tasks.Scanner.Parser.Parser.NormalizePath("/manga/output/file (3).zip"))
|
||||||
|| outputFiles.Contains(API.Parser.Parser.NormalizePath("C:/manga/output/file (3).zip")));
|
|| outputFiles.Contains(API.Services.Tasks.Scanner.Parser.Parser.NormalizePath("C:/manga/output/file (3).zip")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -253,7 +253,7 @@ public class ParseScannedFilesTests
|
|||||||
var foundParsedSeries = new ParsedSeries()
|
var foundParsedSeries = new ParsedSeries()
|
||||||
{
|
{
|
||||||
Name = parsedFiles.First().Series,
|
Name = parsedFiles.First().Series,
|
||||||
NormalizedName = API.Parser.Parser.Normalize(parsedFiles.First().Series),
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize(parsedFiles.First().Series),
|
||||||
Format = parsedFiles.First().Format
|
Format = parsedFiles.First().Format
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ namespace API.Tests.Services
|
|||||||
Name = "1"
|
Name = "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Darker Than Black"),
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker Than Black"),
|
||||||
Metadata = new SeriesMetadata(),
|
Metadata = new SeriesMetadata(),
|
||||||
Format = MangaFormat.Epub
|
Format = MangaFormat.Epub
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ namespace API.Tests.Services
|
|||||||
Name = "Cage of Eden",
|
Name = "Cage of Eden",
|
||||||
LocalizedName = "Cage of Eden",
|
LocalizedName = "Cage of Eden",
|
||||||
OriginalName = "Cage of Eden",
|
OriginalName = "Cage of Eden",
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Cage of Eden"),
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Cage of Eden"),
|
||||||
Metadata = new SeriesMetadata(),
|
Metadata = new SeriesMetadata(),
|
||||||
Format = MangaFormat.Archive
|
Format = MangaFormat.Archive
|
||||||
},
|
},
|
||||||
@ -70,7 +70,7 @@ namespace API.Tests.Services
|
|||||||
Name = "Darker Than Black",
|
Name = "Darker Than Black",
|
||||||
LocalizedName = "Darker Than Black",
|
LocalizedName = "Darker Than Black",
|
||||||
OriginalName = "Darker Than Black",
|
OriginalName = "Darker Than Black",
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Darker Than Black"),
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker Than Black"),
|
||||||
Metadata = new SeriesMetadata(),
|
Metadata = new SeriesMetadata(),
|
||||||
Format = MangaFormat.Archive
|
Format = MangaFormat.Archive
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ public class SiteThemeServiceTests
|
|||||||
await siteThemeService.Scan();
|
await siteThemeService.Scan();
|
||||||
|
|
||||||
var customThemes = (await _unitOfWork.SiteThemeRepository.GetThemeDtos()).Where(t =>
|
var customThemes = (await _unitOfWork.SiteThemeRepository.GetThemeDtos()).Where(t =>
|
||||||
API.Parser.Parser.Normalize(t.Name).Equals(API.Parser.Parser.Normalize("custom")));
|
API.Services.Tasks.Scanner.Parser.Parser.Normalize(t.Name).Equals(API.Services.Tasks.Scanner.Parser.Parser.Normalize("custom")));
|
||||||
Assert.Single(customThemes);
|
Assert.Single(customThemes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ public class SiteThemeServiceTests
|
|||||||
await siteThemeService.Scan();
|
await siteThemeService.Scan();
|
||||||
|
|
||||||
var customThemes = (await _unitOfWork.SiteThemeRepository.GetThemeDtos()).Where(t =>
|
var customThemes = (await _unitOfWork.SiteThemeRepository.GetThemeDtos()).Where(t =>
|
||||||
API.Parser.Parser.Normalize(t.Name).Equals(API.Parser.Parser.Normalize("custom")));
|
API.Services.Tasks.Scanner.Parser.Parser.Normalize(t.Name).Equals(API.Services.Tasks.Scanner.Parser.Parser.Normalize("custom")));
|
||||||
|
|
||||||
Assert.Empty(customThemes);
|
Assert.Empty(customThemes);
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@ public class SiteThemeServiceTests
|
|||||||
_context.SiteTheme.Add(new SiteTheme()
|
_context.SiteTheme.Add(new SiteTheme()
|
||||||
{
|
{
|
||||||
Name = "Custom",
|
Name = "Custom",
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Custom"),
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Custom"),
|
||||||
Provider = ThemeProvider.User,
|
Provider = ThemeProvider.User,
|
||||||
FileName = "custom.css",
|
FileName = "custom.css",
|
||||||
IsDefault = false
|
IsDefault = false
|
||||||
@ -219,7 +219,7 @@ public class SiteThemeServiceTests
|
|||||||
_context.SiteTheme.Add(new SiteTheme()
|
_context.SiteTheme.Add(new SiteTheme()
|
||||||
{
|
{
|
||||||
Name = "Custom",
|
Name = "Custom",
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Custom"),
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Custom"),
|
||||||
Provider = ThemeProvider.User,
|
Provider = ThemeProvider.User,
|
||||||
FileName = "custom.css",
|
FileName = "custom.css",
|
||||||
IsDefault = false
|
IsDefault = false
|
||||||
@ -247,7 +247,7 @@ public class SiteThemeServiceTests
|
|||||||
_context.SiteTheme.Add(new SiteTheme()
|
_context.SiteTheme.Add(new SiteTheme()
|
||||||
{
|
{
|
||||||
Name = "Custom",
|
Name = "Custom",
|
||||||
NormalizedName = API.Parser.Parser.Normalize("Custom"),
|
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Custom"),
|
||||||
Provider = ThemeProvider.User,
|
Provider = ThemeProvider.User,
|
||||||
FileName = "custom.css",
|
FileName = "custom.css",
|
||||||
IsDefault = false
|
IsDefault = false
|
||||||
|
@ -472,12 +472,27 @@ namespace API.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||||
if (string.IsNullOrEmpty(token)) return BadRequest("There was an issue sending email");
|
if (string.IsNullOrEmpty(token))
|
||||||
|
{
|
||||||
|
_logger.LogError("There was an issue generating a token for the email");
|
||||||
|
return BadRequest("There was an creating the invite user");
|
||||||
|
}
|
||||||
|
|
||||||
|
user.ConfirmationToken = token;
|
||||||
|
await _unitOfWork.CommitAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "There was an error during invite user flow, unable to create user. Deleting user for retry");
|
||||||
|
_unitOfWork.UserRepository.Delete(user);
|
||||||
|
await _unitOfWork.CommitAsync();
|
||||||
|
}
|
||||||
|
|
||||||
var emailLink = GenerateEmailLink(token, "confirm-email", dto.Email);
|
try
|
||||||
|
{
|
||||||
|
var emailLink = GenerateEmailLink(user.ConfirmationToken, "confirm-email", dto.Email);
|
||||||
_logger.LogCritical("[Invite User]: Email Link for {UserName}: {Link}", user.UserName, emailLink);
|
_logger.LogCritical("[Invite User]: Email Link for {UserName}: {Link}", user.UserName, emailLink);
|
||||||
_logger.LogCritical("[Invite User]: Token {UserName}: {Token}", user.UserName, token);
|
_logger.LogCritical("[Invite User]: Token {UserName}: {Token}", user.UserName, user.ConfirmationToken);
|
||||||
var host = _environment.IsDevelopment() ? "localhost:4200" : Request.Host.ToString();
|
var host = _environment.IsDevelopment() ? "localhost:4200" : Request.Host.ToString();
|
||||||
var accessible = await _emailService.CheckIfAccessible(host);
|
var accessible = await _emailService.CheckIfAccessible(host);
|
||||||
if (accessible)
|
if (accessible)
|
||||||
@ -490,12 +505,12 @@ namespace API.Controllers
|
|||||||
InvitingUser = adminUser.UserName,
|
InvitingUser = adminUser.UserName,
|
||||||
ServerConfirmationLink = emailLink
|
ServerConfirmationLink = emailLink
|
||||||
});
|
});
|
||||||
} catch(Exception) {/* Swallow exception */}
|
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
user.ConfirmationToken = token;
|
{
|
||||||
|
/* Swallow exception */
|
||||||
await _unitOfWork.CommitAsync();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(new InviteUserResponse
|
return Ok(new InviteUserResponse
|
||||||
{
|
{
|
||||||
@ -503,10 +518,9 @@ namespace API.Controllers
|
|||||||
EmailSent = accessible
|
EmailSent = accessible
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_unitOfWork.UserRepository.Delete(user);
|
_logger.LogError(ex, "There was an error during invite user flow, unable to send an email");
|
||||||
await _unitOfWork.CommitAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return BadRequest("There was an error setting up your account. Please check the logs");
|
return BadRequest("There was an error setting up your account. Please check the logs");
|
||||||
|
@ -76,7 +76,7 @@ namespace API.Controllers
|
|||||||
|
|
||||||
existingTag.Promoted = updatedTag.Promoted;
|
existingTag.Promoted = updatedTag.Promoted;
|
||||||
existingTag.Title = updatedTag.Title.Trim();
|
existingTag.Title = updatedTag.Title.Trim();
|
||||||
existingTag.NormalizedTitle = Parser.Parser.Normalize(updatedTag.Title).ToUpper();
|
existingTag.NormalizedTitle = Services.Tasks.Scanner.Parser.Parser.Normalize(updatedTag.Title).ToUpper();
|
||||||
existingTag.Summary = updatedTag.Summary.Trim();
|
existingTag.Summary = updatedTag.Summary.Trim();
|
||||||
|
|
||||||
if (_unitOfWork.HasChanges())
|
if (_unitOfWork.HasChanges())
|
||||||
|
@ -218,12 +218,12 @@ namespace API.Controllers
|
|||||||
if (!isAdmin) return BadRequest("API key must belong to an admin");
|
if (!isAdmin) return BadRequest("API key must belong to an admin");
|
||||||
if (dto.FolderPath.Contains("..")) return BadRequest("Invalid Path");
|
if (dto.FolderPath.Contains("..")) return BadRequest("Invalid Path");
|
||||||
|
|
||||||
dto.FolderPath = Parser.Parser.NormalizePath(dto.FolderPath);
|
dto.FolderPath = Services.Tasks.Scanner.Parser.Parser.NormalizePath(dto.FolderPath);
|
||||||
|
|
||||||
var libraryFolder = (await _unitOfWork.LibraryRepository.GetLibraryDtosAsync())
|
var libraryFolder = (await _unitOfWork.LibraryRepository.GetLibraryDtosAsync())
|
||||||
.SelectMany(l => l.Folders)
|
.SelectMany(l => l.Folders)
|
||||||
.Distinct()
|
.Distinct()
|
||||||
.Select(Parser.Parser.NormalizePath);
|
.Select(Services.Tasks.Scanner.Parser.Parser.NormalizePath);
|
||||||
|
|
||||||
var seriesFolder = _directoryService.FindHighestDirectoriesFromFiles(libraryFolder,
|
var seriesFolder = _directoryService.FindHighestDirectoriesFromFiles(libraryFolder,
|
||||||
new List<string>() {dto.FolderPath});
|
new List<string>() {dto.FolderPath});
|
||||||
|
@ -179,17 +179,17 @@ namespace API.Controllers
|
|||||||
info.Title += " - " + info.ChapterTitle;
|
info.Title += " - " + info.ChapterTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.IsSpecial && dto.VolumeNumber.Equals(Parser.Parser.DefaultVolume))
|
if (info.IsSpecial && dto.VolumeNumber.Equals(Services.Tasks.Scanner.Parser.Parser.DefaultVolume))
|
||||||
{
|
{
|
||||||
info.Subtitle = info.FileName;
|
info.Subtitle = info.FileName;
|
||||||
} else if (!info.IsSpecial && info.VolumeNumber.Equals(Parser.Parser.DefaultVolume))
|
} else if (!info.IsSpecial && info.VolumeNumber.Equals(Services.Tasks.Scanner.Parser.Parser.DefaultVolume))
|
||||||
{
|
{
|
||||||
info.Subtitle = _readerService.FormatChapterName(info.LibraryType, true, true) + info.ChapterNumber;
|
info.Subtitle = _readerService.FormatChapterName(info.LibraryType, true, true) + info.ChapterNumber;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info.Subtitle = "Volume " + info.VolumeNumber;
|
info.Subtitle = "Volume " + info.VolumeNumber;
|
||||||
if (!info.ChapterNumber.Equals(Parser.Parser.DefaultChapter))
|
if (!info.ChapterNumber.Equals(Services.Tasks.Scanner.Parser.Parser.DefaultChapter))
|
||||||
{
|
{
|
||||||
info.Subtitle += " " + _readerService.FormatChapterName(info.LibraryType, true, true) +
|
info.Subtitle += " " + _readerService.FormatChapterName(info.LibraryType, true, true) +
|
||||||
info.ChapterNumber;
|
info.ChapterNumber;
|
||||||
|
@ -219,7 +219,7 @@ namespace API.Controllers
|
|||||||
if (!string.IsNullOrEmpty(dto.Title))
|
if (!string.IsNullOrEmpty(dto.Title))
|
||||||
{
|
{
|
||||||
readingList.Title = dto.Title; // Should I check if this is unique?
|
readingList.Title = dto.Title; // Should I check if this is unique?
|
||||||
readingList.NormalizedTitle = Parser.Parser.Normalize(readingList.Title);
|
readingList.NormalizedTitle = Services.Tasks.Scanner.Parser.Parser.Normalize(readingList.Title);
|
||||||
}
|
}
|
||||||
if (!string.IsNullOrEmpty(dto.Title))
|
if (!string.IsNullOrEmpty(dto.Title))
|
||||||
{
|
{
|
||||||
|
@ -156,14 +156,14 @@ namespace API.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
series.Name = updateSeries.Name.Trim();
|
series.Name = updateSeries.Name.Trim();
|
||||||
series.NormalizedName = Parser.Parser.Normalize(series.Name);
|
series.NormalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(series.Name);
|
||||||
if (!string.IsNullOrEmpty(updateSeries.SortName.Trim()))
|
if (!string.IsNullOrEmpty(updateSeries.SortName.Trim()))
|
||||||
{
|
{
|
||||||
series.SortName = updateSeries.SortName.Trim();
|
series.SortName = updateSeries.SortName.Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
series.LocalizedName = updateSeries.LocalizedName.Trim();
|
series.LocalizedName = updateSeries.LocalizedName.Trim();
|
||||||
series.NormalizedLocalizedName = Parser.Parser.Normalize(series.LocalizedName);
|
series.NormalizedLocalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(series.LocalizedName);
|
||||||
|
|
||||||
series.NameLocked = updateSeries.NameLocked;
|
series.NameLocked = updateSeries.NameLocked;
|
||||||
series.SortNameLocked = updateSeries.SortNameLocked;
|
series.SortNameLocked = updateSeries.SortNameLocked;
|
||||||
|
@ -23,8 +23,8 @@ namespace API.Data
|
|||||||
Name = name,
|
Name = name,
|
||||||
OriginalName = name,
|
OriginalName = name,
|
||||||
LocalizedName = name,
|
LocalizedName = name,
|
||||||
NormalizedName = Parser.Parser.Normalize(name),
|
NormalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(name),
|
||||||
NormalizedLocalizedName = Parser.Parser.Normalize(name),
|
NormalizedLocalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(name),
|
||||||
SortName = name,
|
SortName = name,
|
||||||
Volumes = new List<Volume>(),
|
Volumes = new List<Volume>(),
|
||||||
Metadata = SeriesMetadata(Array.Empty<CollectionTag>())
|
Metadata = SeriesMetadata(Array.Empty<CollectionTag>())
|
||||||
@ -42,8 +42,8 @@ namespace API.Data
|
|||||||
Name = name,
|
Name = name,
|
||||||
OriginalName = name,
|
OriginalName = name,
|
||||||
LocalizedName = localizedName,
|
LocalizedName = localizedName,
|
||||||
NormalizedName = Parser.Parser.Normalize(name),
|
NormalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(name),
|
||||||
NormalizedLocalizedName = Parser.Parser.Normalize(localizedName),
|
NormalizedLocalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(localizedName),
|
||||||
SortName = name,
|
SortName = name,
|
||||||
Volumes = new List<Volume>(),
|
Volumes = new List<Volume>(),
|
||||||
Metadata = SeriesMetadata(Array.Empty<CollectionTag>())
|
Metadata = SeriesMetadata(Array.Empty<CollectionTag>())
|
||||||
@ -55,7 +55,7 @@ namespace API.Data
|
|||||||
return new Volume()
|
return new Volume()
|
||||||
{
|
{
|
||||||
Name = volumeNumber,
|
Name = volumeNumber,
|
||||||
Number = (int) Parser.Parser.MinNumberFromRange(volumeNumber),
|
Number = (int) Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(volumeNumber),
|
||||||
Chapters = new List<Chapter>()
|
Chapters = new List<Chapter>()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ namespace API.Data
|
|||||||
var specialTitle = specialTreatment ? info.Filename : info.Chapters;
|
var specialTitle = specialTreatment ? info.Filename : info.Chapters;
|
||||||
return new Chapter()
|
return new Chapter()
|
||||||
{
|
{
|
||||||
Number = specialTreatment ? "0" : Parser.Parser.MinNumberFromRange(info.Chapters) + string.Empty,
|
Number = specialTreatment ? "0" : Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(info.Chapters) + string.Empty,
|
||||||
Range = specialTreatment ? info.Filename : info.Chapters,
|
Range = specialTreatment ? info.Filename : info.Chapters,
|
||||||
Title = (specialTreatment && info.Format == MangaFormat.Epub)
|
Title = (specialTreatment && info.Format == MangaFormat.Epub)
|
||||||
? info.Title
|
? info.Title
|
||||||
@ -95,7 +95,7 @@ namespace API.Data
|
|||||||
return new CollectionTag()
|
return new CollectionTag()
|
||||||
{
|
{
|
||||||
Id = id,
|
Id = id,
|
||||||
NormalizedTitle = API.Parser.Parser.Normalize(title?.Trim()).ToUpper(),
|
NormalizedTitle = Services.Tasks.Scanner.Parser.Parser.Normalize(title?.Trim()).ToUpper(),
|
||||||
Title = title?.Trim(),
|
Title = title?.Trim(),
|
||||||
Summary = summary?.Trim(),
|
Summary = summary?.Trim(),
|
||||||
Promoted = promoted
|
Promoted = promoted
|
||||||
@ -106,7 +106,7 @@ namespace API.Data
|
|||||||
{
|
{
|
||||||
return new ReadingList()
|
return new ReadingList()
|
||||||
{
|
{
|
||||||
NormalizedTitle = API.Parser.Parser.Normalize(title?.Trim()).ToUpper(),
|
NormalizedTitle = Services.Tasks.Scanner.Parser.Parser.Normalize(title?.Trim()).ToUpper(),
|
||||||
Title = title?.Trim(),
|
Title = title?.Trim(),
|
||||||
Summary = summary?.Trim(),
|
Summary = summary?.Trim(),
|
||||||
Promoted = promoted,
|
Promoted = promoted,
|
||||||
@ -130,7 +130,7 @@ namespace API.Data
|
|||||||
return new Genre()
|
return new Genre()
|
||||||
{
|
{
|
||||||
Title = name.Trim().SentenceCase(),
|
Title = name.Trim().SentenceCase(),
|
||||||
NormalizedTitle = Parser.Parser.Normalize(name),
|
NormalizedTitle = Services.Tasks.Scanner.Parser.Parser.Normalize(name),
|
||||||
ExternalTag = external
|
ExternalTag = external
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -140,7 +140,7 @@ namespace API.Data
|
|||||||
return new Tag()
|
return new Tag()
|
||||||
{
|
{
|
||||||
Title = name.Trim().SentenceCase(),
|
Title = name.Trim().SentenceCase(),
|
||||||
NormalizedTitle = Parser.Parser.Normalize(name),
|
NormalizedTitle = Services.Tasks.Scanner.Parser.Parser.Normalize(name),
|
||||||
ExternalTag = external
|
ExternalTag = external
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ namespace API.Data
|
|||||||
return new Person()
|
return new Person()
|
||||||
{
|
{
|
||||||
Name = name.Trim(),
|
Name = name.Trim(),
|
||||||
NormalizedName = Parser.Parser.Normalize(name),
|
NormalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(name),
|
||||||
Role = role
|
Role = role
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -107,16 +107,16 @@ namespace API.Data.Metadata
|
|||||||
info.SeriesSort = info.SeriesSort.Trim();
|
info.SeriesSort = info.SeriesSort.Trim();
|
||||||
info.LocalizedSeries = info.LocalizedSeries.Trim();
|
info.LocalizedSeries = info.LocalizedSeries.Trim();
|
||||||
|
|
||||||
info.Writer = Parser.Parser.CleanAuthor(info.Writer);
|
info.Writer = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Writer);
|
||||||
info.Colorist = Parser.Parser.CleanAuthor(info.Colorist);
|
info.Colorist = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Colorist);
|
||||||
info.Editor = Parser.Parser.CleanAuthor(info.Editor);
|
info.Editor = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Editor);
|
||||||
info.Inker = Parser.Parser.CleanAuthor(info.Inker);
|
info.Inker = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Inker);
|
||||||
info.Letterer = Parser.Parser.CleanAuthor(info.Letterer);
|
info.Letterer = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Letterer);
|
||||||
info.Penciller = Parser.Parser.CleanAuthor(info.Penciller);
|
info.Penciller = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Penciller);
|
||||||
info.Publisher = Parser.Parser.CleanAuthor(info.Publisher);
|
info.Publisher = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Publisher);
|
||||||
info.Characters = Parser.Parser.CleanAuthor(info.Characters);
|
info.Characters = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Characters);
|
||||||
info.Translator = Parser.Parser.CleanAuthor(info.Translator);
|
info.Translator = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Translator);
|
||||||
info.CoverArtist = Parser.Parser.CleanAuthor(info.CoverArtist);
|
info.CoverArtist = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.CoverArtist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ public static class MigrateBookmarks
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var files = directoryService.GetFilesWithExtension(chapterExtractPath, Parser.Parser.ImageFileExtensions);
|
var files = directoryService.GetFilesWithExtension(chapterExtractPath, Services.Tasks.Scanner.Parser.Parser.ImageFileExtensions);
|
||||||
// Filter out images that aren't in bookmarks
|
// Filter out images that aren't in bookmarks
|
||||||
Array.Sort(files, numericComparer);
|
Array.Sort(files, numericComparer);
|
||||||
foreach (var chapterPage in chapterPages)
|
foreach (var chapterPage in chapterPages)
|
||||||
|
@ -21,7 +21,7 @@ public static class MigrateNormalizedLocalizedName
|
|||||||
|
|
||||||
foreach (var series in await dataContext.Series.ToListAsync())
|
foreach (var series in await dataContext.Series.ToListAsync())
|
||||||
{
|
{
|
||||||
series.NormalizedLocalizedName = Parser.Parser.Normalize(series.LocalizedName ?? string.Empty);
|
series.NormalizedLocalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(series.LocalizedName ?? string.Empty);
|
||||||
logger.LogInformation("Updated {SeriesName} normalized localized name: {LocalizedName}", series.Name, series.NormalizedLocalizedName);
|
logger.LogInformation("Updated {SeriesName} normalized localized name: {LocalizedName}", series.Name, series.NormalizedLocalizedName);
|
||||||
unitOfWork.SeriesRepository.Update(series);
|
unitOfWork.SeriesRepository.Update(series);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ public class GenreRepository : IGenreRepository
|
|||||||
|
|
||||||
public async Task<Genre> FindByNameAsync(string genreName)
|
public async Task<Genre> FindByNameAsync(string genreName)
|
||||||
{
|
{
|
||||||
var normalizedName = Parser.Parser.Normalize(genreName);
|
var normalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(genreName);
|
||||||
return await _context.Genre
|
return await _context.Genre
|
||||||
.FirstOrDefaultAsync(g => g.NormalizedTitle.Equals(normalizedName));
|
.FirstOrDefaultAsync(g => g.NormalizedTitle.Equals(normalizedName));
|
||||||
}
|
}
|
||||||
|
@ -334,13 +334,13 @@ public class LibraryRepository : ILibraryRepository
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<bool> DoAnySeriesFoldersMatch(IEnumerable<string> folders)
|
public async Task<bool> DoAnySeriesFoldersMatch(IEnumerable<string> folders)
|
||||||
{
|
{
|
||||||
var normalized = folders.Select(Parser.Parser.NormalizePath);
|
var normalized = folders.Select(Services.Tasks.Scanner.Parser.Parser.NormalizePath);
|
||||||
return await _context.Series.AnyAsync(s => normalized.Contains(s.FolderPath));
|
return await _context.Series.AnyAsync(s => normalized.Contains(s.FolderPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Library? GetLibraryByFolder(string folder)
|
public Library? GetLibraryByFolder(string folder)
|
||||||
{
|
{
|
||||||
var normalized = Parser.Parser.NormalizePath(folder);
|
var normalized = Services.Tasks.Scanner.Parser.Parser.NormalizePath(folder);
|
||||||
return _context.Library
|
return _context.Library
|
||||||
.Include(l => l.Folders)
|
.Include(l => l.Folders)
|
||||||
.AsSplitQuery()
|
.AsSplitQuery()
|
||||||
|
@ -42,7 +42,7 @@ public class PersonRepository : IPersonRepository
|
|||||||
|
|
||||||
public async Task<Person> FindByNameAsync(string name)
|
public async Task<Person> FindByNameAsync(string name)
|
||||||
{
|
{
|
||||||
var normalizedName = Parser.Parser.Normalize(name);
|
var normalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(name);
|
||||||
return await _context.Person
|
return await _context.Person
|
||||||
.Where(p => normalizedName.Equals(p.NormalizedName))
|
.Where(p => normalizedName.Equals(p.NormalizedName))
|
||||||
.SingleOrDefaultAsync();
|
.SingleOrDefaultAsync();
|
||||||
|
@ -301,7 +301,7 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
{
|
{
|
||||||
const int maxRecords = 15;
|
const int maxRecords = 15;
|
||||||
var result = new SearchResultGroupDto();
|
var result = new SearchResultGroupDto();
|
||||||
var searchQueryNormalized = Parser.Parser.Normalize(searchQuery);
|
var searchQueryNormalized = Services.Tasks.Scanner.Parser.Parser.Normalize(searchQuery);
|
||||||
|
|
||||||
var seriesIds = _context.Series
|
var seriesIds = _context.Series
|
||||||
.Where(s => libraryIds.Contains(s.LibraryId))
|
.Where(s => libraryIds.Contains(s.LibraryId))
|
||||||
@ -1151,7 +1151,7 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<int> GetSeriesIdByFolder(string folder)
|
public async Task<int> GetSeriesIdByFolder(string folder)
|
||||||
{
|
{
|
||||||
var normalized = Parser.Parser.NormalizePath(folder);
|
var normalized = Services.Tasks.Scanner.Parser.Parser.NormalizePath(folder);
|
||||||
var series = await _context.Series
|
var series = await _context.Series
|
||||||
.Where(s => s.FolderPath.Equals(normalized))
|
.Where(s => s.FolderPath.Equals(normalized))
|
||||||
.SingleOrDefaultAsync();
|
.SingleOrDefaultAsync();
|
||||||
@ -1165,7 +1165,7 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<Series> GetSeriesByFolderPath(string folder)
|
public async Task<Series> GetSeriesByFolderPath(string folder)
|
||||||
{
|
{
|
||||||
var normalized = Parser.Parser.NormalizePath(folder);
|
var normalized = Services.Tasks.Scanner.Parser.Parser.NormalizePath(folder);
|
||||||
return await _context.Series.SingleOrDefaultAsync(s => s.FolderPath.Equals(normalized));
|
return await _context.Series.SingleOrDefaultAsync(s => s.FolderPath.Equals(normalized));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1178,7 +1178,7 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<Series> GetFullSeriesByName(string series, int libraryId)
|
public Task<Series> GetFullSeriesByName(string series, int libraryId)
|
||||||
{
|
{
|
||||||
var localizedSeries = Parser.Parser.Normalize(series);
|
var localizedSeries = Services.Tasks.Scanner.Parser.Parser.Normalize(series);
|
||||||
return _context.Series
|
return _context.Series
|
||||||
.Where(s => (s.NormalizedName.Equals(localizedSeries)
|
.Where(s => (s.NormalizedName.Equals(localizedSeries)
|
||||||
|| s.LocalizedName.Equals(series)) && s.LibraryId == libraryId)
|
|| s.LocalizedName.Equals(series)) && s.LibraryId == libraryId)
|
||||||
@ -1221,8 +1221,8 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<Series> GetFullSeriesByAnyName(string seriesName, string localizedName, int libraryId, MangaFormat format, bool withFullIncludes = true)
|
public Task<Series> GetFullSeriesByAnyName(string seriesName, string localizedName, int libraryId, MangaFormat format, bool withFullIncludes = true)
|
||||||
{
|
{
|
||||||
var normalizedSeries = Parser.Parser.Normalize(seriesName);
|
var normalizedSeries = Services.Tasks.Scanner.Parser.Parser.Normalize(seriesName);
|
||||||
var normalizedLocalized = Parser.Parser.Normalize(localizedName);
|
var normalizedLocalized = Services.Tasks.Scanner.Parser.Parser.Normalize(localizedName);
|
||||||
var query = _context.Series
|
var query = _context.Series
|
||||||
.Where(s => s.LibraryId == libraryId)
|
.Where(s => s.LibraryId == libraryId)
|
||||||
.Where(s => s.Format == format && format != MangaFormat.Unknown)
|
.Where(s => s.Format == format && format != MangaFormat.Unknown)
|
||||||
|
@ -43,7 +43,7 @@ public class TagRepository : ITagRepository
|
|||||||
|
|
||||||
public async Task<Tag> FindByNameAsync(string tagName)
|
public async Task<Tag> FindByNameAsync(string tagName)
|
||||||
{
|
{
|
||||||
var normalizedName = Parser.Parser.Normalize(tagName);
|
var normalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(tagName);
|
||||||
return await _context.Tag
|
return await _context.Tag
|
||||||
.FirstOrDefaultAsync(g => g.NormalizedTitle.Equals(normalizedName));
|
.FirstOrDefaultAsync(g => g.NormalizedTitle.Equals(normalizedName));
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ namespace API.Data
|
|||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Name = "Dark",
|
Name = "Dark",
|
||||||
NormalizedName = Parser.Parser.Normalize("Dark"),
|
NormalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize("Dark"),
|
||||||
Provider = ThemeProvider.System,
|
Provider = ThemeProvider.System,
|
||||||
FileName = "dark.scss",
|
FileName = "dark.scss",
|
||||||
IsDefault = true,
|
IsDefault = true,
|
||||||
|
@ -9,13 +9,13 @@ namespace API.Entities.Enums
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Image file
|
/// Image file
|
||||||
/// See <see cref="Parser.Parser.ImageFileExtensions"/> for supported extensions
|
/// See <see cref="Services.Tasks.Scanner.Parser.Parser.ImageFileExtensions"/> for supported extensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Description("Image")]
|
[Description("Image")]
|
||||||
Image = 0,
|
Image = 0,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Archive based file
|
/// Archive based file
|
||||||
/// See <see cref="Parser.Parser.ArchiveFileExtensions"/> for supported extensions
|
/// See <see cref="Services.Tasks.Scanner.Parser.Parser.ArchiveFileExtensions"/> for supported extensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Description("Archive")]
|
[Description("Archive")]
|
||||||
Archive = 1,
|
Archive = 1,
|
||||||
|
@ -14,11 +14,11 @@ public class Series : IEntityDate, IHasReadTimeEstimate
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used internally for name matching. <see cref="Parser.Parser.Normalize"/>
|
/// Used internally for name matching. <see cref="Services.Tasks.Scanner.Parser.Parser.Normalize"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string NormalizedName { get; set; }
|
public string NormalizedName { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used internally for localized name matching. <see cref="Parser.Parser.Normalize"/>
|
/// Used internally for localized name matching. <see cref="Services.Tasks.Scanner.Parser.Parser.Normalize"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string NormalizedLocalizedName { get; set; }
|
public string NormalizedLocalizedName { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -57,7 +57,7 @@ public class Series : IEntityDate, IHasReadTimeEstimate
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Highest path (that is under library root) that contains the series.
|
/// Highest path (that is under library root) that contains the series.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks><see cref="Parser.Parser.NormalizePath"/> must be used before setting</remarks>
|
/// <remarks><see cref="Services.Tasks.Scanner.Parser.Parser.NormalizePath"/> must be used before setting</remarks>
|
||||||
public string FolderPath { get; set; }
|
public string FolderPath { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Last time the folder was scanned
|
/// Last time the folder was scanned
|
||||||
|
@ -16,8 +16,8 @@ namespace API.Extensions
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static bool NameInList(this Series series, IEnumerable<string> list)
|
public static bool NameInList(this Series series, IEnumerable<string> list)
|
||||||
{
|
{
|
||||||
return list.Any(name => Parser.Parser.Normalize(name) == series.NormalizedName || Parser.Parser.Normalize(name) == Parser.Parser.Normalize(series.Name)
|
return list.Any(name => Services.Tasks.Scanner.Parser.Parser.Normalize(name) == series.NormalizedName || Services.Tasks.Scanner.Parser.Parser.Normalize(name) == Services.Tasks.Scanner.Parser.Parser.Normalize(series.Name)
|
||||||
|| name == series.Name || name == series.LocalizedName || name == series.OriginalName || Parser.Parser.Normalize(name) == Parser.Parser.Normalize(series.OriginalName));
|
|| name == series.Name || name == series.LocalizedName || name == series.OriginalName || Services.Tasks.Scanner.Parser.Parser.Normalize(name) == Services.Tasks.Scanner.Parser.Parser.Normalize(series.OriginalName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -28,8 +28,8 @@ namespace API.Extensions
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static bool NameInList(this Series series, IEnumerable<ParsedSeries> list)
|
public static bool NameInList(this Series series, IEnumerable<ParsedSeries> list)
|
||||||
{
|
{
|
||||||
return list.Any(name => Parser.Parser.Normalize(name.Name) == series.NormalizedName || Parser.Parser.Normalize(name.Name) == Parser.Parser.Normalize(series.Name)
|
return list.Any(name => Services.Tasks.Scanner.Parser.Parser.Normalize(name.Name) == series.NormalizedName || Services.Tasks.Scanner.Parser.Parser.Normalize(name.Name) == Services.Tasks.Scanner.Parser.Parser.Normalize(series.Name)
|
||||||
|| name.Name == series.Name || name.Name == series.LocalizedName || name.Name == series.OriginalName || Parser.Parser.Normalize(name.Name) == Parser.Parser.Normalize(series.OriginalName) && series.Format == name.Format);
|
|| name.Name == series.Name || name.Name == series.LocalizedName || name.Name == series.OriginalName || Services.Tasks.Scanner.Parser.Parser.Normalize(name.Name) == Services.Tasks.Scanner.Parser.Parser.Normalize(series.OriginalName) && series.Format == name.Format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -41,9 +41,9 @@ namespace API.Extensions
|
|||||||
public static bool NameInParserInfo(this Series series, ParserInfo info)
|
public static bool NameInParserInfo(this Series series, ParserInfo info)
|
||||||
{
|
{
|
||||||
if (info == null) return false;
|
if (info == null) return false;
|
||||||
return Parser.Parser.Normalize(info.Series) == series.NormalizedName || Parser.Parser.Normalize(info.Series) == Parser.Parser.Normalize(series.Name)
|
return Services.Tasks.Scanner.Parser.Parser.Normalize(info.Series) == series.NormalizedName || Services.Tasks.Scanner.Parser.Parser.Normalize(info.Series) == Services.Tasks.Scanner.Parser.Parser.Normalize(series.Name)
|
||||||
|| info.Series == series.Name || info.Series == series.LocalizedName || info.Series == series.OriginalName
|
|| info.Series == series.Name || info.Series == series.LocalizedName || info.Series == series.OriginalName
|
||||||
|| Parser.Parser.Normalize(info.Series) == Parser.Parser.Normalize(series.OriginalName);
|
|| Services.Tasks.Scanner.Parser.Parser.Normalize(info.Series) == Services.Tasks.Scanner.Parser.Parser.Normalize(series.OriginalName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ public static class GenreHelper
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(name.Trim())) continue;
|
if (string.IsNullOrEmpty(name.Trim())) continue;
|
||||||
|
|
||||||
var normalizedName = Parser.Parser.Normalize(name);
|
var normalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(name);
|
||||||
var genre = allGenres.FirstOrDefault(p =>
|
var genre = allGenres.FirstOrDefault(p =>
|
||||||
p.NormalizedTitle.Equals(normalizedName) && p.ExternalTag == isExternal);
|
p.NormalizedTitle.Equals(normalizedName) && p.ExternalTag == isExternal);
|
||||||
if (genre == null)
|
if (genre == null)
|
||||||
@ -57,7 +57,7 @@ public static class GenreHelper
|
|||||||
public static void AddGenreIfNotExists(ICollection<Genre> metadataGenres, Genre genre)
|
public static void AddGenreIfNotExists(ICollection<Genre> metadataGenres, Genre genre)
|
||||||
{
|
{
|
||||||
var existingGenre = metadataGenres.FirstOrDefault(p =>
|
var existingGenre = metadataGenres.FirstOrDefault(p =>
|
||||||
p.NormalizedTitle == Parser.Parser.Normalize(genre.Title));
|
p.NormalizedTitle == Services.Tasks.Scanner.Parser.Parser.Normalize(genre.Title));
|
||||||
if (existingGenre == null)
|
if (existingGenre == null)
|
||||||
{
|
{
|
||||||
metadataGenres.Add(genre);
|
metadataGenres.Add(genre);
|
||||||
@ -67,7 +67,7 @@ public static class GenreHelper
|
|||||||
public static void AddGenreIfNotExists(BlockingCollection<Genre> metadataGenres, Genre genre)
|
public static void AddGenreIfNotExists(BlockingCollection<Genre> metadataGenres, Genre genre)
|
||||||
{
|
{
|
||||||
var existingGenre = metadataGenres.FirstOrDefault(p =>
|
var existingGenre = metadataGenres.FirstOrDefault(p =>
|
||||||
p.NormalizedTitle == Parser.Parser.Normalize(genre.Title));
|
p.NormalizedTitle == Services.Tasks.Scanner.Parser.Parser.Normalize(genre.Title));
|
||||||
if (existingGenre == null)
|
if (existingGenre == null)
|
||||||
{
|
{
|
||||||
metadataGenres.Add(genre);
|
metadataGenres.Add(genre);
|
||||||
|
@ -22,14 +22,14 @@ public static class ParserInfoHelpers
|
|||||||
foreach (var pSeries in parsedSeries.Keys)
|
foreach (var pSeries in parsedSeries.Keys)
|
||||||
{
|
{
|
||||||
var name = pSeries.Name;
|
var name = pSeries.Name;
|
||||||
var normalizedName = Parser.Parser.Normalize(name);
|
var normalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(name);
|
||||||
|
|
||||||
//if (series.NameInParserInfo(pSeries.))
|
//if (series.NameInParserInfo(pSeries.))
|
||||||
if (normalizedName == series.NormalizedName ||
|
if (normalizedName == series.NormalizedName ||
|
||||||
normalizedName == Parser.Parser.Normalize(series.Name) ||
|
normalizedName == Services.Tasks.Scanner.Parser.Parser.Normalize(series.Name) ||
|
||||||
name == series.Name || name == series.LocalizedName ||
|
name == series.Name || name == series.LocalizedName ||
|
||||||
name == series.OriginalName ||
|
name == series.OriginalName ||
|
||||||
normalizedName == Parser.Parser.Normalize(series.OriginalName))
|
normalizedName == Services.Tasks.Scanner.Parser.Parser.Normalize(series.OriginalName))
|
||||||
{
|
{
|
||||||
format = pSeries.Format;
|
format = pSeries.Format;
|
||||||
if (format == series.Format)
|
if (format == series.Format)
|
||||||
|
@ -26,7 +26,7 @@ public static class PersonHelper
|
|||||||
|
|
||||||
foreach (var name in names)
|
foreach (var name in names)
|
||||||
{
|
{
|
||||||
var normalizedName = Parser.Parser.Normalize(name);
|
var normalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(name);
|
||||||
var person = allPeopleTypeRole.FirstOrDefault(p =>
|
var person = allPeopleTypeRole.FirstOrDefault(p =>
|
||||||
p.NormalizedName.Equals(normalizedName));
|
p.NormalizedName.Equals(normalizedName));
|
||||||
if (person == null)
|
if (person == null)
|
||||||
@ -49,7 +49,7 @@ public static class PersonHelper
|
|||||||
/// <param name="action">Callback which will be executed for each person removed</param>
|
/// <param name="action">Callback which will be executed for each person removed</param>
|
||||||
public static void RemovePeople(ICollection<Person> existingPeople, IEnumerable<string> people, PersonRole role, Action<Person> action = null)
|
public static void RemovePeople(ICollection<Person> existingPeople, IEnumerable<string> people, PersonRole role, Action<Person> action = null)
|
||||||
{
|
{
|
||||||
var normalizedPeople = people.Select(Parser.Parser.Normalize).ToList();
|
var normalizedPeople = people.Select(Services.Tasks.Scanner.Parser.Parser.Normalize).ToList();
|
||||||
if (normalizedPeople.Count == 0)
|
if (normalizedPeople.Count == 0)
|
||||||
{
|
{
|
||||||
var peopleToRemove = existingPeople.Where(p => p.Role == role).ToList();
|
var peopleToRemove = existingPeople.Where(p => p.Role == role).ToList();
|
||||||
@ -99,7 +99,7 @@ public static class PersonHelper
|
|||||||
public static void AddPersonIfNotExists(ICollection<Person> metadataPeople, Person person)
|
public static void AddPersonIfNotExists(ICollection<Person> metadataPeople, Person person)
|
||||||
{
|
{
|
||||||
var existingPerson = metadataPeople.SingleOrDefault(p =>
|
var existingPerson = metadataPeople.SingleOrDefault(p =>
|
||||||
p.NormalizedName == Parser.Parser.Normalize(person.Name) && p.Role == person.Role);
|
p.NormalizedName == Services.Tasks.Scanner.Parser.Parser.Normalize(person.Name) && p.Role == person.Role);
|
||||||
if (existingPerson == null)
|
if (existingPerson == null)
|
||||||
{
|
{
|
||||||
metadataPeople.Add(person);
|
metadataPeople.Add(person);
|
||||||
@ -114,7 +114,7 @@ public static class PersonHelper
|
|||||||
public static void AddPersonIfNotExists(BlockingCollection<Person> metadataPeople, Person person)
|
public static void AddPersonIfNotExists(BlockingCollection<Person> metadataPeople, Person person)
|
||||||
{
|
{
|
||||||
var existingPerson = metadataPeople.SingleOrDefault(p =>
|
var existingPerson = metadataPeople.SingleOrDefault(p =>
|
||||||
p.NormalizedName == Parser.Parser.Normalize(person.Name) && p.Role == person.Role);
|
p.NormalizedName == Services.Tasks.Scanner.Parser.Parser.Normalize(person.Name) && p.Role == person.Role);
|
||||||
if (existingPerson == null)
|
if (existingPerson == null)
|
||||||
{
|
{
|
||||||
metadataPeople.Add(person);
|
metadataPeople.Add(person);
|
||||||
|
@ -17,8 +17,8 @@ public static class SeriesHelper
|
|||||||
public static bool FindSeries(Series series, ParsedSeries parsedInfoKey)
|
public static bool FindSeries(Series series, ParsedSeries parsedInfoKey)
|
||||||
{
|
{
|
||||||
return (series.NormalizedName.Equals(parsedInfoKey.NormalizedName) ||
|
return (series.NormalizedName.Equals(parsedInfoKey.NormalizedName) ||
|
||||||
Parser.Parser.Normalize(series.LocalizedName).Equals(parsedInfoKey.NormalizedName) ||
|
Services.Tasks.Scanner.Parser.Parser.Normalize(series.LocalizedName).Equals(parsedInfoKey.NormalizedName) ||
|
||||||
Parser.Parser.Normalize(series.OriginalName).Equals(parsedInfoKey.NormalizedName))
|
Services.Tasks.Scanner.Parser.Parser.Normalize(series.OriginalName).Equals(parsedInfoKey.NormalizedName))
|
||||||
&& (series.Format == parsedInfoKey.Format || series.Format == MangaFormat.Unknown);
|
&& (series.Format == parsedInfoKey.Format || series.Format == MangaFormat.Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ public static class TagHelper
|
|||||||
if (string.IsNullOrEmpty(name.Trim())) continue;
|
if (string.IsNullOrEmpty(name.Trim())) continue;
|
||||||
|
|
||||||
var added = false;
|
var added = false;
|
||||||
var normalizedName = Parser.Parser.Normalize(name);
|
var normalizedName = Services.Tasks.Scanner.Parser.Parser.Normalize(name);
|
||||||
|
|
||||||
var genre = allTags.FirstOrDefault(p =>
|
var genre = allTags.FirstOrDefault(p =>
|
||||||
p.NormalizedTitle.Equals(normalizedName) && p.ExternalTag == isExternal);
|
p.NormalizedTitle.Equals(normalizedName) && p.ExternalTag == isExternal);
|
||||||
@ -59,7 +59,7 @@ public static class TagHelper
|
|||||||
public static void AddTagIfNotExists(ICollection<Tag> metadataTags, Tag tag)
|
public static void AddTagIfNotExists(ICollection<Tag> metadataTags, Tag tag)
|
||||||
{
|
{
|
||||||
var existingGenre = metadataTags.FirstOrDefault(p =>
|
var existingGenre = metadataTags.FirstOrDefault(p =>
|
||||||
p.NormalizedTitle == Parser.Parser.Normalize(tag.Title));
|
p.NormalizedTitle == Services.Tasks.Scanner.Parser.Parser.Normalize(tag.Title));
|
||||||
if (existingGenre == null)
|
if (existingGenre == null)
|
||||||
{
|
{
|
||||||
metadataTags.Add(tag);
|
metadataTags.Add(tag);
|
||||||
@ -69,7 +69,7 @@ public static class TagHelper
|
|||||||
public static void AddTagIfNotExists(BlockingCollection<Tag> metadataTags, Tag tag)
|
public static void AddTagIfNotExists(BlockingCollection<Tag> metadataTags, Tag tag)
|
||||||
{
|
{
|
||||||
var existingGenre = metadataTags.FirstOrDefault(p =>
|
var existingGenre = metadataTags.FirstOrDefault(p =>
|
||||||
p.NormalizedTitle == Parser.Parser.Normalize(tag.Title));
|
p.NormalizedTitle == Services.Tasks.Scanner.Parser.Parser.Normalize(tag.Title));
|
||||||
if (existingGenre == null)
|
if (existingGenre == null)
|
||||||
{
|
{
|
||||||
metadataTags.Add(tag);
|
metadataTags.Add(tag);
|
||||||
@ -86,7 +86,7 @@ public static class TagHelper
|
|||||||
/// <param name="action">Callback which will be executed for each tag removed</param>
|
/// <param name="action">Callback which will be executed for each tag removed</param>
|
||||||
public static void RemoveTags(ICollection<Tag> existingTags, IEnumerable<string> tags, bool isExternal, Action<Tag> action = null)
|
public static void RemoveTags(ICollection<Tag> existingTags, IEnumerable<string> tags, bool isExternal, Action<Tag> action = null)
|
||||||
{
|
{
|
||||||
var normalizedTags = tags.Select(Parser.Parser.Normalize).ToList();
|
var normalizedTags = tags.Select(Services.Tasks.Scanner.Parser.Parser.Normalize).ToList();
|
||||||
foreach (var person in normalizedTags)
|
foreach (var person in normalizedTags)
|
||||||
{
|
{
|
||||||
var existingTag = existingTags.FirstOrDefault(p => p.ExternalTag == isExternal && person.Equals(p.NormalizedTitle));
|
var existingTag = existingTags.FirstOrDefault(p => p.ExternalTag == isExternal && person.Equals(p.NormalizedTitle));
|
||||||
|
@ -60,7 +60,7 @@ namespace API.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ArchiveLibrary CanOpen(string archivePath)
|
public virtual ArchiveLibrary CanOpen(string archivePath)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(archivePath) || !(File.Exists(archivePath) && Parser.Parser.IsArchive(archivePath) || Parser.Parser.IsEpub(archivePath))) return ArchiveLibrary.NotSupported;
|
if (string.IsNullOrEmpty(archivePath) || !(File.Exists(archivePath) && Tasks.Scanner.Parser.Parser.IsArchive(archivePath) || Tasks.Scanner.Parser.Parser.IsEpub(archivePath))) return ArchiveLibrary.NotSupported;
|
||||||
|
|
||||||
var ext = _directoryService.FileSystem.Path.GetExtension(archivePath).ToUpper();
|
var ext = _directoryService.FileSystem.Path.GetExtension(archivePath).ToUpper();
|
||||||
if (ext.Equals(".CBR") || ext.Equals(".RAR")) return ArchiveLibrary.SharpCompress;
|
if (ext.Equals(".CBR") || ext.Equals(".RAR")) return ArchiveLibrary.SharpCompress;
|
||||||
@ -100,14 +100,14 @@ namespace API.Services
|
|||||||
case ArchiveLibrary.Default:
|
case ArchiveLibrary.Default:
|
||||||
{
|
{
|
||||||
using var archive = ZipFile.OpenRead(archivePath);
|
using var archive = ZipFile.OpenRead(archivePath);
|
||||||
return archive.Entries.Count(e => !Parser.Parser.HasBlacklistedFolderInPath(e.FullName) && Parser.Parser.IsImage(e.FullName));
|
return archive.Entries.Count(e => !Tasks.Scanner.Parser.Parser.HasBlacklistedFolderInPath(e.FullName) && Tasks.Scanner.Parser.Parser.IsImage(e.FullName));
|
||||||
}
|
}
|
||||||
case ArchiveLibrary.SharpCompress:
|
case ArchiveLibrary.SharpCompress:
|
||||||
{
|
{
|
||||||
using var archive = ArchiveFactory.Open(archivePath);
|
using var archive = ArchiveFactory.Open(archivePath);
|
||||||
return archive.Entries.Count(entry => !entry.IsDirectory &&
|
return archive.Entries.Count(entry => !entry.IsDirectory &&
|
||||||
!Parser.Parser.HasBlacklistedFolderInPath(Path.GetDirectoryName(entry.Key) ?? string.Empty)
|
!Tasks.Scanner.Parser.Parser.HasBlacklistedFolderInPath(Path.GetDirectoryName(entry.Key) ?? string.Empty)
|
||||||
&& Parser.Parser.IsImage(entry.Key));
|
&& Tasks.Scanner.Parser.Parser.IsImage(entry.Key));
|
||||||
}
|
}
|
||||||
case ArchiveLibrary.NotSupported:
|
case ArchiveLibrary.NotSupported:
|
||||||
_logger.LogWarning("[GetNumberOfPagesFromArchive] This archive cannot be read: {ArchivePath}. Defaulting to 0 pages", archivePath);
|
_logger.LogWarning("[GetNumberOfPagesFromArchive] This archive cannot be read: {ArchivePath}. Defaulting to 0 pages", archivePath);
|
||||||
@ -132,9 +132,9 @@ namespace API.Services
|
|||||||
public static string FindFolderEntry(IEnumerable<string> entryFullNames)
|
public static string FindFolderEntry(IEnumerable<string> entryFullNames)
|
||||||
{
|
{
|
||||||
var result = entryFullNames
|
var result = entryFullNames
|
||||||
.Where(path => !(Path.EndsInDirectorySeparator(path) || Parser.Parser.HasBlacklistedFolderInPath(path) || path.StartsWith(Parser.Parser.MacOsMetadataFileStartsWith)))
|
.Where(path => !(Path.EndsInDirectorySeparator(path) || Tasks.Scanner.Parser.Parser.HasBlacklistedFolderInPath(path) || path.StartsWith(Tasks.Scanner.Parser.Parser.MacOsMetadataFileStartsWith)))
|
||||||
.OrderByNatural(Path.GetFileNameWithoutExtension)
|
.OrderByNatural(Path.GetFileNameWithoutExtension)
|
||||||
.FirstOrDefault(Parser.Parser.IsCoverImage);
|
.FirstOrDefault(Tasks.Scanner.Parser.Parser.IsCoverImage);
|
||||||
|
|
||||||
return string.IsNullOrEmpty(result) ? null : result;
|
return string.IsNullOrEmpty(result) ? null : result;
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ namespace API.Services
|
|||||||
// First check if there are any files that are not in a nested folder before just comparing by filename. This is needed
|
// First check if there are any files that are not in a nested folder before just comparing by filename. This is needed
|
||||||
// because NaturalSortComparer does not work with paths and doesn't seem 001.jpg as before chapter 1/001.jpg.
|
// because NaturalSortComparer does not work with paths and doesn't seem 001.jpg as before chapter 1/001.jpg.
|
||||||
var fullNames = entryFullNames
|
var fullNames = entryFullNames
|
||||||
.Where(path => !(Path.EndsInDirectorySeparator(path) || Parser.Parser.HasBlacklistedFolderInPath(path) || path.StartsWith(Parser.Parser.MacOsMetadataFileStartsWith)) && Parser.Parser.IsImage(path))
|
.Where(path => !(Path.EndsInDirectorySeparator(path) || Tasks.Scanner.Parser.Parser.HasBlacklistedFolderInPath(path) || path.StartsWith(Tasks.Scanner.Parser.Parser.MacOsMetadataFileStartsWith)) && Tasks.Scanner.Parser.Parser.IsImage(path))
|
||||||
.OrderByNatural(c => c.GetFullPathWithoutExtension())
|
.OrderByNatural(c => c.GetFullPathWithoutExtension())
|
||||||
.ToList();
|
.ToList();
|
||||||
if (fullNames.Count == 0) return null;
|
if (fullNames.Count == 0) return null;
|
||||||
@ -187,7 +187,7 @@ namespace API.Services
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates byte array of cover image.
|
/// Generates byte array of cover image.
|
||||||
/// Given a path to a compressed file <see cref="Parser.Parser.ArchiveFileExtensions"/>, will ensure the first image (respects directory structure) is returned unless
|
/// Given a path to a compressed file <see cref="Tasks.Scanner.Parser.Parser.ArchiveFileExtensions"/>, will ensure the first image (respects directory structure) is returned unless
|
||||||
/// a folder/cover.(image extension) exists in the the compressed file (if duplicate, the first is chosen)
|
/// a folder/cover.(image extension) exists in the the compressed file (if duplicate, the first is chosen)
|
||||||
///
|
///
|
||||||
/// This skips over any __MACOSX folder/file iteration.
|
/// This skips over any __MACOSX folder/file iteration.
|
||||||
@ -265,7 +265,7 @@ namespace API.Services
|
|||||||
// Sometimes ZipArchive will list the directory and others it will just keep it in the FullName
|
// Sometimes ZipArchive will list the directory and others it will just keep it in the FullName
|
||||||
return archive.Entries.Count > 0 &&
|
return archive.Entries.Count > 0 &&
|
||||||
!Path.HasExtension(archive.Entries.ElementAt(0).FullName) ||
|
!Path.HasExtension(archive.Entries.ElementAt(0).FullName) ||
|
||||||
archive.Entries.Any(e => e.FullName.Contains(Path.AltDirectorySeparatorChar) && !Parser.Parser.HasBlacklistedFolderInPath(e.FullName));
|
archive.Entries.Any(e => e.FullName.Contains(Path.AltDirectorySeparatorChar) && !Tasks.Scanner.Parser.Parser.HasBlacklistedFolderInPath(e.FullName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -322,7 +322,7 @@ namespace API.Services
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Parser.Parser.IsArchive(archivePath) || Parser.Parser.IsEpub(archivePath)) return true;
|
if (Tasks.Scanner.Parser.Parser.IsArchive(archivePath) || Tasks.Scanner.Parser.Parser.IsEpub(archivePath)) return true;
|
||||||
|
|
||||||
_logger.LogWarning("Archive {ArchivePath} is not a valid archive", archivePath);
|
_logger.LogWarning("Archive {ArchivePath} is not a valid archive", archivePath);
|
||||||
return false;
|
return false;
|
||||||
@ -331,10 +331,10 @@ namespace API.Services
|
|||||||
private static bool ValidComicInfoArchiveEntry(string fullName, string name)
|
private static bool ValidComicInfoArchiveEntry(string fullName, string name)
|
||||||
{
|
{
|
||||||
var filenameWithoutExtension = Path.GetFileNameWithoutExtension(name).ToLower();
|
var filenameWithoutExtension = Path.GetFileNameWithoutExtension(name).ToLower();
|
||||||
return !Parser.Parser.HasBlacklistedFolderInPath(fullName)
|
return !Tasks.Scanner.Parser.Parser.HasBlacklistedFolderInPath(fullName)
|
||||||
&& filenameWithoutExtension.Equals(ComicInfoFilename, StringComparison.InvariantCultureIgnoreCase)
|
&& filenameWithoutExtension.Equals(ComicInfoFilename, StringComparison.InvariantCultureIgnoreCase)
|
||||||
&& !filenameWithoutExtension.StartsWith(Parser.Parser.MacOsMetadataFileStartsWith)
|
&& !filenameWithoutExtension.StartsWith(Tasks.Scanner.Parser.Parser.MacOsMetadataFileStartsWith)
|
||||||
&& Parser.Parser.IsXml(name);
|
&& Tasks.Scanner.Parser.Parser.IsXml(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -467,8 +467,8 @@ namespace API.Services
|
|||||||
{
|
{
|
||||||
using var archive = ArchiveFactory.Open(archivePath);
|
using var archive = ArchiveFactory.Open(archivePath);
|
||||||
ExtractArchiveEntities(archive.Entries.Where(entry => !entry.IsDirectory
|
ExtractArchiveEntities(archive.Entries.Where(entry => !entry.IsDirectory
|
||||||
&& !Parser.Parser.HasBlacklistedFolderInPath(Path.GetDirectoryName(entry.Key) ?? string.Empty)
|
&& !Tasks.Scanner.Parser.Parser.HasBlacklistedFolderInPath(Path.GetDirectoryName(entry.Key) ?? string.Empty)
|
||||||
&& Parser.Parser.IsImage(entry.Key)), extractPath);
|
&& Tasks.Scanner.Parser.Parser.IsImage(entry.Key)), extractPath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ArchiveLibrary.NotSupported:
|
case ArchiveLibrary.NotSupported:
|
||||||
|
@ -167,7 +167,7 @@ namespace API.Services
|
|||||||
// @Import statements will be handled by browser, so we must inline the css into the original file that request it, so they can be Scoped
|
// @Import statements will be handled by browser, so we must inline the css into the original file that request it, so they can be Scoped
|
||||||
var prepend = filename.Length > 0 ? filename.Replace(Path.GetFileName(filename), string.Empty) : string.Empty;
|
var prepend = filename.Length > 0 ? filename.Replace(Path.GetFileName(filename), string.Empty) : string.Empty;
|
||||||
var importBuilder = new StringBuilder();
|
var importBuilder = new StringBuilder();
|
||||||
foreach (Match match in Parser.Parser.CssImportUrlRegex.Matches(stylesheetHtml))
|
foreach (Match match in Tasks.Scanner.Parser.Parser.CssImportUrlRegex.Matches(stylesheetHtml))
|
||||||
{
|
{
|
||||||
if (!match.Success) continue;
|
if (!match.Success) continue;
|
||||||
|
|
||||||
@ -218,7 +218,7 @@ namespace API.Services
|
|||||||
|
|
||||||
private static void EscapeCssImportReferences(ref string stylesheetHtml, string apiBase, string prepend)
|
private static void EscapeCssImportReferences(ref string stylesheetHtml, string apiBase, string prepend)
|
||||||
{
|
{
|
||||||
foreach (Match match in Parser.Parser.CssImportUrlRegex.Matches(stylesheetHtml))
|
foreach (Match match in Tasks.Scanner.Parser.Parser.CssImportUrlRegex.Matches(stylesheetHtml))
|
||||||
{
|
{
|
||||||
if (!match.Success) continue;
|
if (!match.Success) continue;
|
||||||
var importFile = match.Groups["Filename"].Value;
|
var importFile = match.Groups["Filename"].Value;
|
||||||
@ -228,7 +228,7 @@ namespace API.Services
|
|||||||
|
|
||||||
private static void EscapeFontFamilyReferences(ref string stylesheetHtml, string apiBase, string prepend)
|
private static void EscapeFontFamilyReferences(ref string stylesheetHtml, string apiBase, string prepend)
|
||||||
{
|
{
|
||||||
foreach (Match match in Parser.Parser.FontSrcUrlRegex.Matches(stylesheetHtml))
|
foreach (Match match in Tasks.Scanner.Parser.Parser.FontSrcUrlRegex.Matches(stylesheetHtml))
|
||||||
{
|
{
|
||||||
if (!match.Success) continue;
|
if (!match.Success) continue;
|
||||||
var importFile = match.Groups["Filename"].Value;
|
var importFile = match.Groups["Filename"].Value;
|
||||||
@ -238,7 +238,7 @@ namespace API.Services
|
|||||||
|
|
||||||
private static void EscapeCssImageReferences(ref string stylesheetHtml, string apiBase, EpubBookRef book)
|
private static void EscapeCssImageReferences(ref string stylesheetHtml, string apiBase, EpubBookRef book)
|
||||||
{
|
{
|
||||||
var matches = Parser.Parser.CssImageUrlRegex.Matches(stylesheetHtml);
|
var matches = Tasks.Scanner.Parser.Parser.CssImageUrlRegex.Matches(stylesheetHtml);
|
||||||
foreach (Match match in matches)
|
foreach (Match match in matches)
|
||||||
{
|
{
|
||||||
if (!match.Success) continue;
|
if (!match.Success) continue;
|
||||||
@ -394,7 +394,7 @@ namespace API.Services
|
|||||||
|
|
||||||
public ComicInfo GetComicInfo(string filePath)
|
public ComicInfo GetComicInfo(string filePath)
|
||||||
{
|
{
|
||||||
if (!IsValidFile(filePath) || Parser.Parser.IsPdf(filePath)) return null;
|
if (!IsValidFile(filePath) || Tasks.Scanner.Parser.Parser.IsPdf(filePath)) return null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -425,7 +425,7 @@ namespace API.Services
|
|||||||
var info = new ComicInfo()
|
var info = new ComicInfo()
|
||||||
{
|
{
|
||||||
Summary = epubBook.Schema.Package.Metadata.Description,
|
Summary = epubBook.Schema.Package.Metadata.Description,
|
||||||
Writer = string.Join(",", epubBook.Schema.Package.Metadata.Creators.Select(c => Parser.Parser.CleanAuthor(c.Creator))),
|
Writer = string.Join(",", epubBook.Schema.Package.Metadata.Creators.Select(c => Tasks.Scanner.Parser.Parser.CleanAuthor(c.Creator))),
|
||||||
Publisher = string.Join(",", epubBook.Schema.Package.Metadata.Publishers),
|
Publisher = string.Join(",", epubBook.Schema.Package.Metadata.Publishers),
|
||||||
Month = month,
|
Month = month,
|
||||||
Day = day,
|
Day = day,
|
||||||
@ -468,7 +468,7 @@ namespace API.Services
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Parser.Parser.IsBook(filePath)) return true;
|
if (Tasks.Scanner.Parser.Parser.IsBook(filePath)) return true;
|
||||||
|
|
||||||
_logger.LogWarning("[BookService] Book {EpubFile} is not a valid EPUB/PDF", filePath);
|
_logger.LogWarning("[BookService] Book {EpubFile} is not a valid EPUB/PDF", filePath);
|
||||||
return false;
|
return false;
|
||||||
@ -480,7 +480,7 @@ namespace API.Services
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Parser.Parser.IsPdf(filePath))
|
if (Tasks.Scanner.Parser.Parser.IsPdf(filePath))
|
||||||
{
|
{
|
||||||
using var docReader = DocLib.Instance.GetDocReader(filePath, new PageDimensions(1080, 1920));
|
using var docReader = DocLib.Instance.GetDocReader(filePath, new PageDimensions(1080, 1920));
|
||||||
return docReader.GetPageCount();
|
return docReader.GetPageCount();
|
||||||
@ -536,7 +536,7 @@ namespace API.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ParserInfo ParseInfo(string filePath)
|
public ParserInfo ParseInfo(string filePath)
|
||||||
{
|
{
|
||||||
if (!Parser.Parser.IsEpub(filePath)) return null;
|
if (!Tasks.Scanner.Parser.Parser.IsEpub(filePath)) return null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -601,7 +601,7 @@ namespace API.Services
|
|||||||
}
|
}
|
||||||
var info = new ParserInfo()
|
var info = new ParserInfo()
|
||||||
{
|
{
|
||||||
Chapters = Parser.Parser.DefaultChapter,
|
Chapters = Tasks.Scanner.Parser.Parser.DefaultChapter,
|
||||||
Edition = string.Empty,
|
Edition = string.Empty,
|
||||||
Format = MangaFormat.Epub,
|
Format = MangaFormat.Epub,
|
||||||
Filename = Path.GetFileName(filePath),
|
Filename = Path.GetFileName(filePath),
|
||||||
@ -628,7 +628,7 @@ namespace API.Services
|
|||||||
|
|
||||||
return new ParserInfo()
|
return new ParserInfo()
|
||||||
{
|
{
|
||||||
Chapters = Parser.Parser.DefaultChapter,
|
Chapters = Tasks.Scanner.Parser.Parser.DefaultChapter,
|
||||||
Edition = string.Empty,
|
Edition = string.Empty,
|
||||||
Format = MangaFormat.Epub,
|
Format = MangaFormat.Epub,
|
||||||
Filename = Path.GetFileName(filePath),
|
Filename = Path.GetFileName(filePath),
|
||||||
@ -636,7 +636,7 @@ namespace API.Services
|
|||||||
FullFilePath = filePath,
|
FullFilePath = filePath,
|
||||||
IsSpecial = false,
|
IsSpecial = false,
|
||||||
Series = epubBook.Title.Trim(),
|
Series = epubBook.Title.Trim(),
|
||||||
Volumes = Parser.Parser.DefaultVolume,
|
Volumes = Tasks.Scanner.Parser.Parser.DefaultVolume,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -876,7 +876,7 @@ namespace API.Services
|
|||||||
{
|
{
|
||||||
if (!IsValidFile(fileFilePath)) return string.Empty;
|
if (!IsValidFile(fileFilePath)) return string.Empty;
|
||||||
|
|
||||||
if (Parser.Parser.IsPdf(fileFilePath))
|
if (Tasks.Scanner.Parser.Parser.IsPdf(fileFilePath))
|
||||||
{
|
{
|
||||||
return GetPdfCoverImage(fileFilePath, fileName, outputDirectory);
|
return GetPdfCoverImage(fileFilePath, fileName, outputDirectory);
|
||||||
}
|
}
|
||||||
@ -887,7 +887,7 @@ namespace API.Services
|
|||||||
{
|
{
|
||||||
// Try to get the cover image from OPF file, if not set, try to parse it from all the files, then result to the first one.
|
// Try to get the cover image from OPF file, if not set, try to parse it from all the files, then result to the first one.
|
||||||
var coverImageContent = epubBook.Content.Cover
|
var coverImageContent = epubBook.Content.Cover
|
||||||
?? epubBook.Content.Images.Values.FirstOrDefault(file => Parser.Parser.IsCoverImage(file.FileName))
|
?? epubBook.Content.Images.Values.FirstOrDefault(file => Tasks.Scanner.Parser.Parser.IsCoverImage(file.FileName))
|
||||||
?? epubBook.Content.Images.Values.FirstOrDefault();
|
?? epubBook.Content.Images.Values.FirstOrDefault();
|
||||||
|
|
||||||
if (coverImageContent == null) return string.Empty;
|
if (coverImageContent == null) return string.Empty;
|
||||||
|
@ -51,7 +51,7 @@ public class BookmarkService : IBookmarkService
|
|||||||
var bookmarkDirectory =
|
var bookmarkDirectory =
|
||||||
(await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.BookmarkDirectory)).Value;
|
(await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.BookmarkDirectory)).Value;
|
||||||
|
|
||||||
var bookmarkFilesToDelete = bookmarks.Select(b => Parser.Parser.NormalizePath(
|
var bookmarkFilesToDelete = bookmarks.Select(b => Tasks.Scanner.Parser.Parser.NormalizePath(
|
||||||
_directoryService.FileSystem.Path.Join(bookmarkDirectory,
|
_directoryService.FileSystem.Path.Join(bookmarkDirectory,
|
||||||
b.FileName))).ToList();
|
b.FileName))).ToList();
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ public class BookmarkService : IBookmarkService
|
|||||||
|
|
||||||
var bookmarks = await _unitOfWork.UserRepository.GetAllBookmarksByIds(bookmarkIds.ToList());
|
var bookmarks = await _unitOfWork.UserRepository.GetAllBookmarksByIds(bookmarkIds.ToList());
|
||||||
return bookmarks
|
return bookmarks
|
||||||
.Select(b => Parser.Parser.NormalizePath(_directoryService.FileSystem.Path.Join(bookmarkDirectory,
|
.Select(b => Tasks.Scanner.Parser.Parser.NormalizePath(_directoryService.FileSystem.Path.Join(bookmarkDirectory,
|
||||||
b.FileName)));
|
b.FileName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ namespace API.Services
|
|||||||
{
|
{
|
||||||
// Calculate what chapter the page belongs to
|
// Calculate what chapter the page belongs to
|
||||||
var path = GetBookmarkCachePath(seriesId);
|
var path = GetBookmarkCachePath(seriesId);
|
||||||
var files = _directoryService.GetFilesWithExtension(path, Parser.Parser.ImageFileExtensions);
|
var files = _directoryService.GetFilesWithExtension(path, Tasks.Scanner.Parser.Parser.ImageFileExtensions);
|
||||||
files = files
|
files = files
|
||||||
.AsEnumerable()
|
.AsEnumerable()
|
||||||
.OrderByNatural(Path.GetFileNameWithoutExtension)
|
.OrderByNatural(Path.GetFileNameWithoutExtension)
|
||||||
@ -214,7 +214,7 @@ namespace API.Services
|
|||||||
// Calculate what chapter the page belongs to
|
// Calculate what chapter the page belongs to
|
||||||
var path = GetCachePath(chapter.Id);
|
var path = GetCachePath(chapter.Id);
|
||||||
// TODO: We can optimize this by extracting and renaming, so we don't need to scan for the files and can do a direct access
|
// TODO: We can optimize this by extracting and renaming, so we don't need to scan for the files and can do a direct access
|
||||||
var files = _directoryService.GetFilesWithExtension(path, Parser.Parser.ImageFileExtensions)
|
var files = _directoryService.GetFilesWithExtension(path, Tasks.Scanner.Parser.Parser.ImageFileExtensions)
|
||||||
.OrderByNatural(Path.GetFileNameWithoutExtension)
|
.OrderByNatural(Path.GetFileNameWithoutExtension)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Abstractions;
|
using System.IO.Abstractions;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -116,7 +117,7 @@ namespace API.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Given a set of regex search criteria, get files in the given path.
|
/// Given a set of regex search criteria, get files in the given path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This will always exclude <see cref="Parser.Parser.MacOsMetadataFileStartsWith"/> patterns</remarks>
|
/// <remarks>This will always exclude <see cref="Tasks.Scanner.Parser.Parser.MacOsMetadataFileStartsWith"/> patterns</remarks>
|
||||||
/// <param name="path">Directory to search</param>
|
/// <param name="path">Directory to search</param>
|
||||||
/// <param name="searchPatternExpression">Regex version of search pattern (ie \.mp3|\.mp4). Defaults to * meaning all files.</param>
|
/// <param name="searchPatternExpression">Regex version of search pattern (ie \.mp3|\.mp4). Defaults to * meaning all files.</param>
|
||||||
/// <param name="searchOption">SearchOption to use, defaults to TopDirectoryOnly</param>
|
/// <param name="searchOption">SearchOption to use, defaults to TopDirectoryOnly</param>
|
||||||
@ -130,7 +131,7 @@ namespace API.Services
|
|||||||
|
|
||||||
return FileSystem.Directory.EnumerateFiles(path, "*", searchOption)
|
return FileSystem.Directory.EnumerateFiles(path, "*", searchOption)
|
||||||
.Where(file =>
|
.Where(file =>
|
||||||
reSearchPattern.IsMatch(FileSystem.Path.GetExtension(file)) && !FileSystem.Path.GetFileName(file).StartsWith(Parser.Parser.MacOsMetadataFileStartsWith));
|
reSearchPattern.IsMatch(FileSystem.Path.GetExtension(file)) && !FileSystem.Path.GetFileName(file).StartsWith(Tasks.Scanner.Parser.Parser.MacOsMetadataFileStartsWith));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -207,12 +208,12 @@ namespace API.Services
|
|||||||
{
|
{
|
||||||
var fileName = FileSystem.Path.GetFileName(file);
|
var fileName = FileSystem.Path.GetFileName(file);
|
||||||
return reSearchPattern.IsMatch(fileName) &&
|
return reSearchPattern.IsMatch(fileName) &&
|
||||||
!fileName.StartsWith(Parser.Parser.MacOsMetadataFileStartsWith);
|
!fileName.StartsWith(Tasks.Scanner.Parser.Parser.MacOsMetadataFileStartsWith);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return FileSystem.Directory.EnumerateFiles(path, "*", searchOption).Where(file =>
|
return FileSystem.Directory.EnumerateFiles(path, "*", searchOption).Where(file =>
|
||||||
!FileSystem.Path.GetFileName(file).StartsWith(Parser.Parser.MacOsMetadataFileStartsWith));
|
!FileSystem.Path.GetFileName(file).StartsWith(Tasks.Scanner.Parser.Parser.MacOsMetadataFileStartsWith));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -496,10 +497,10 @@ namespace API.Services
|
|||||||
{
|
{
|
||||||
var stopLookingForDirectories = false;
|
var stopLookingForDirectories = false;
|
||||||
var dirs = new Dictionary<string, string>();
|
var dirs = new Dictionary<string, string>();
|
||||||
foreach (var folder in libraryFolders.Select(Parser.Parser.NormalizePath))
|
foreach (var folder in libraryFolders.Select(Tasks.Scanner.Parser.Parser.NormalizePath))
|
||||||
{
|
{
|
||||||
if (stopLookingForDirectories) break;
|
if (stopLookingForDirectories) break;
|
||||||
foreach (var file in filePaths.Select(Parser.Parser.NormalizePath))
|
foreach (var file in filePaths.Select(Tasks.Scanner.Parser.Parser.NormalizePath))
|
||||||
{
|
{
|
||||||
if (!file.Contains(folder)) continue;
|
if (!file.Contains(folder)) continue;
|
||||||
|
|
||||||
@ -512,7 +513,7 @@ namespace API.Services
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fullPath = Parser.Parser.NormalizePath(Path.Join(folder, parts.Last()));
|
var fullPath = Tasks.Scanner.Parser.Parser.NormalizePath(Path.Join(folder, parts.Last()));
|
||||||
if (!dirs.ContainsKey(fullPath))
|
if (!dirs.ContainsKey(fullPath))
|
||||||
{
|
{
|
||||||
dirs.Add(fullPath, string.Empty);
|
dirs.Add(fullPath, string.Empty);
|
||||||
@ -579,7 +580,7 @@ namespace API.Services
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return Parser.Parser.NormalizePath(Directory.GetParent(fileOrFolder)?.FullName);
|
return Tasks.Scanner.Parser.Parser.NormalizePath(Directory.GetParent(fileOrFolder)?.FullName);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@ -621,12 +622,12 @@ namespace API.Services
|
|||||||
// Get the matcher from either ignore or global (default setup)
|
// Get the matcher from either ignore or global (default setup)
|
||||||
if (matcher == null)
|
if (matcher == null)
|
||||||
{
|
{
|
||||||
files.AddRange(GetFilesWithCertainExtensions(folderPath, Parser.Parser.SupportedExtensions));
|
files.AddRange(GetFilesWithCertainExtensions(folderPath, Tasks.Scanner.Parser.Parser.SupportedExtensions));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var foundFiles = GetFilesWithCertainExtensions(folderPath,
|
var foundFiles = GetFilesWithCertainExtensions(folderPath,
|
||||||
Parser.Parser.SupportedExtensions)
|
Tasks.Scanner.Parser.Parser.SupportedExtensions)
|
||||||
.Where(file => !matcher.ExcludeMatches(FileSystem.FileInfo.FromFileName(file).Name));
|
.Where(file => !matcher.ExcludeMatches(FileSystem.FileInfo.FromFileName(file).Name));
|
||||||
files.AddRange(foundFiles);
|
files.AddRange(foundFiles);
|
||||||
}
|
}
|
||||||
@ -635,18 +636,14 @@ namespace API.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recursively scans a folder and returns the max last write time on any folders
|
/// Recursively scans a folder and returns the max last write time on any folders and files
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="folderPath"></param>
|
/// <param name="folderPath"></param>
|
||||||
/// <returns>Max Last Write Time</returns>
|
/// <returns>Max Last Write Time</returns>
|
||||||
public DateTime GetLastWriteTime(string folderPath)
|
public DateTime GetLastWriteTime(string folderPath)
|
||||||
{
|
{
|
||||||
if (!FileSystem.Directory.Exists(folderPath)) throw new IOException($"{folderPath} does not exist");
|
if (!FileSystem.Directory.Exists(folderPath)) throw new IOException($"{folderPath} does not exist");
|
||||||
|
return Directory.GetFileSystemEntries(folderPath, "*.*", SearchOption.AllDirectories).Max(path => FileSystem.File.GetLastWriteTime(path));
|
||||||
var directories = GetAllDirectories(folderPath).ToList();
|
|
||||||
if (directories.Count == 0) return FileSystem.Directory.GetLastWriteTime(folderPath);
|
|
||||||
|
|
||||||
return directories.Max(d => FileSystem.Directory.GetLastWriteTime(d));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -848,7 +845,7 @@ namespace API.Services
|
|||||||
/// <param name="directoryName">Fully qualified directory</param>
|
/// <param name="directoryName">Fully qualified directory</param>
|
||||||
public void RemoveNonImages(string directoryName)
|
public void RemoveNonImages(string directoryName)
|
||||||
{
|
{
|
||||||
DeleteFiles(GetFiles(directoryName, searchOption:SearchOption.AllDirectories).Where(file => !Parser.Parser.IsImage(file)));
|
DeleteFiles(GetFiles(directoryName, searchOption:SearchOption.AllDirectories).Where(file => !Tasks.Scanner.Parser.Parser.IsImage(file)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -921,9 +918,9 @@ namespace API.Services
|
|||||||
foreach (var file in directory.EnumerateFiles().OrderByNatural(file => file.FullName))
|
foreach (var file in directory.EnumerateFiles().OrderByNatural(file => file.FullName))
|
||||||
{
|
{
|
||||||
if (file.Directory == null) continue;
|
if (file.Directory == null) continue;
|
||||||
var paddedIndex = Parser.Parser.PadZeros(directoryIndex + "");
|
var paddedIndex = Tasks.Scanner.Parser.Parser.PadZeros(directoryIndex + "");
|
||||||
// We need to rename the files so that after flattening, they are in the order we found them
|
// We need to rename the files so that after flattening, they are in the order we found them
|
||||||
var newName = $"{paddedIndex}_{Parser.Parser.PadZeros(fileIndex + "")}{file.Extension}";
|
var newName = $"{paddedIndex}_{Tasks.Scanner.Parser.Parser.PadZeros(fileIndex + "")}{file.Extension}";
|
||||||
var newPath = Path.Join(root.FullName, newName);
|
var newPath = Path.Join(root.FullName, newName);
|
||||||
if (!File.Exists(newPath)) file.MoveTo(newPath);
|
if (!File.Exists(newPath)) file.MoveTo(newPath);
|
||||||
fileIndex++;
|
fileIndex++;
|
||||||
@ -935,7 +932,7 @@ namespace API.Services
|
|||||||
foreach (var subDirectory in directory.EnumerateDirectories().OrderByNatural(d => d.FullName))
|
foreach (var subDirectory in directory.EnumerateDirectories().OrderByNatural(d => d.FullName))
|
||||||
{
|
{
|
||||||
// We need to check if the directory is not a blacklisted (ie __MACOSX)
|
// We need to check if the directory is not a blacklisted (ie __MACOSX)
|
||||||
if (Parser.Parser.HasBlacklistedFolderInPath(subDirectory.FullName)) continue;
|
if (Tasks.Scanner.Parser.Parser.HasBlacklistedFolderInPath(subDirectory.FullName)) continue;
|
||||||
|
|
||||||
FlattenDirectory(root, subDirectory, ref directoryIndex);
|
FlattenDirectory(root, subDirectory, ref directoryIndex);
|
||||||
}
|
}
|
||||||
|
@ -82,9 +82,16 @@ public class EmailService : IEmailService
|
|||||||
public async Task<bool> CheckIfAccessible(string host)
|
public async Task<bool> CheckIfAccessible(string host)
|
||||||
{
|
{
|
||||||
// This is the only exception for using the default because we need an external service to check if the server is accessible for emails
|
// This is the only exception for using the default because we need an external service to check if the server is accessible for emails
|
||||||
|
try
|
||||||
|
{
|
||||||
if (IsLocalIpAddress(host)) return false;
|
if (IsLocalIpAddress(host)) return false;
|
||||||
return await SendEmailWithGet(DefaultApiUrl + "/api/email/reachable?host=" + host);
|
return await SendEmailWithGet(DefaultApiUrl + "/api/email/reachable?host=" + host);
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<bool> SendMigrationEmail(EmailMigrationDto data)
|
public async Task<bool> SendMigrationEmail(EmailMigrationDto data)
|
||||||
{
|
{
|
||||||
|
@ -63,7 +63,7 @@ public class ImageService : IImageService
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
_directoryService.CopyDirectoryToDirectory(Path.GetDirectoryName(fileFilePath), targetDirectory,
|
_directoryService.CopyDirectoryToDirectory(Path.GetDirectoryName(fileFilePath), targetDirectory,
|
||||||
Parser.Parser.ImageFileExtensions);
|
Tasks.Scanner.Parser.Parser.ImageFileExtensions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ public class ReaderService : IReaderService
|
|||||||
|
|
||||||
public static string FormatBookmarkFolderPath(string baseDirectory, int userId, int seriesId, int chapterId)
|
public static string FormatBookmarkFolderPath(string baseDirectory, int userId, int seriesId, int chapterId)
|
||||||
{
|
{
|
||||||
return Parser.Parser.NormalizePath(Path.Join(baseDirectory, $"{userId}", $"{seriesId}", $"{chapterId}"));
|
return Tasks.Scanner.Parser.Parser.NormalizePath(Path.Join(baseDirectory, $"{userId}", $"{seriesId}", $"{chapterId}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -496,7 +496,7 @@ public class ReaderService : IReaderService
|
|||||||
{
|
{
|
||||||
var chapters = volume.Chapters
|
var chapters = volume.Chapters
|
||||||
.OrderBy(c => float.Parse(c.Number))
|
.OrderBy(c => float.Parse(c.Number))
|
||||||
.Where(c => !c.IsSpecial && Parser.Parser.MaxNumberFromRange(c.Range) <= chapterNumber);
|
.Where(c => !c.IsSpecial && Tasks.Scanner.Parser.Parser.MaxNumberFromRange(c.Range) <= chapterNumber);
|
||||||
await MarkChaptersAsRead(user, volume.SeriesId, chapters);
|
await MarkChaptersAsRead(user, volume.SeriesId, chapters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,12 +40,12 @@ public class ReadingItemService : IReadingItemService
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ComicInfo? GetComicInfo(string filePath)
|
public ComicInfo? GetComicInfo(string filePath)
|
||||||
{
|
{
|
||||||
if (Parser.Parser.IsEpub(filePath))
|
if (Tasks.Scanner.Parser.Parser.IsEpub(filePath))
|
||||||
{
|
{
|
||||||
return _bookService.GetComicInfo(filePath);
|
return _bookService.GetComicInfo(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Parser.Parser.IsComicInfoExtension(filePath))
|
if (Tasks.Scanner.Parser.Parser.IsComicInfoExtension(filePath))
|
||||||
{
|
{
|
||||||
return _archiveService.GetComicInfo(filePath);
|
return _archiveService.GetComicInfo(filePath);
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ public class ReadingItemService : IReadingItemService
|
|||||||
|
|
||||||
|
|
||||||
// This catches when original library type is Manga/Comic and when parsing with non
|
// This catches when original library type is Manga/Comic and when parsing with non
|
||||||
if (Parser.Parser.IsEpub(path) && Parser.Parser.ParseVolume(info.Series) != Parser.Parser.DefaultVolume) // Shouldn't this be info.Volume != DefaultVolume?
|
if (Tasks.Scanner.Parser.Parser.IsEpub(path) && Tasks.Scanner.Parser.Parser.ParseVolume(info.Series) != Tasks.Scanner.Parser.Parser.DefaultVolume) // Shouldn't this be info.Volume != DefaultVolume?
|
||||||
{
|
{
|
||||||
info = _defaultParser.Parse(path, rootPath, LibraryType.Book);
|
info = _defaultParser.Parse(path, rootPath, LibraryType.Book);
|
||||||
var info2 = Parse(path, rootPath, type);
|
var info2 = Parse(path, rootPath, type);
|
||||||
@ -98,11 +98,11 @@ public class ReadingItemService : IReadingItemService
|
|||||||
info.SeriesSort = info.ComicInfo.TitleSort.Trim();
|
info.SeriesSort = info.ComicInfo.TitleSort.Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(info.ComicInfo.Format) && Parser.Parser.HasComicInfoSpecial(info.ComicInfo.Format))
|
if (!string.IsNullOrEmpty(info.ComicInfo.Format) && Tasks.Scanner.Parser.Parser.HasComicInfoSpecial(info.ComicInfo.Format))
|
||||||
{
|
{
|
||||||
info.IsSpecial = true;
|
info.IsSpecial = true;
|
||||||
info.Chapters = Parser.Parser.DefaultChapter;
|
info.Chapters = Tasks.Scanner.Parser.Parser.DefaultChapter;
|
||||||
info.Volumes = Parser.Parser.DefaultVolume;
|
info.Volumes = Tasks.Scanner.Parser.Parser.DefaultVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(info.ComicInfo.SeriesSort))
|
if (!string.IsNullOrEmpty(info.ComicInfo.SeriesSort))
|
||||||
@ -200,6 +200,6 @@ public class ReadingItemService : IReadingItemService
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ParserInfo Parse(string path, string rootPath, LibraryType type)
|
public ParserInfo Parse(string path, string rootPath, LibraryType type)
|
||||||
{
|
{
|
||||||
return Parser.Parser.IsEpub(path) ? _bookService.ParseInfo(path) : _defaultParser.Parse(path, rootPath, type);
|
return Tasks.Scanner.Parser.Parser.IsEpub(path) ? _bookService.ParseInfo(path) : _defaultParser.Parse(path, rootPath, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ public class ReadingListService : IReadingListService
|
|||||||
|
|
||||||
var existingChapterExists = readingList.Items.Select(rli => rli.ChapterId).ToHashSet();
|
var existingChapterExists = readingList.Items.Select(rli => rli.ChapterId).ToHashSet();
|
||||||
var chaptersForSeries = (await _unitOfWork.ChapterRepository.GetChaptersByIdsAsync(chapterIds))
|
var chaptersForSeries = (await _unitOfWork.ChapterRepository.GetChaptersByIdsAsync(chapterIds))
|
||||||
.OrderBy(c => Parser.Parser.MinNumberFromRange(c.Volume.Name))
|
.OrderBy(c => Tasks.Scanner.Parser.Parser.MinNumberFromRange(c.Volume.Name))
|
||||||
.ThenBy(x => double.Parse(x.Number), _chapterSortComparerForInChapterSorting);
|
.ThenBy(x => double.Parse(x.Number), _chapterSortComparerForInChapterSorting);
|
||||||
|
|
||||||
var index = lastOrder + 1;
|
var index = lastOrder + 1;
|
||||||
|
@ -254,7 +254,7 @@ public class SeriesService : ISeriesService
|
|||||||
// At this point, all tags that aren't in dto have been removed.
|
// At this point, all tags that aren't in dto have been removed.
|
||||||
foreach (var tagTitle in tags.Select(t => t.Title))
|
foreach (var tagTitle in tags.Select(t => t.Title))
|
||||||
{
|
{
|
||||||
var normalizedTitle = Parser.Parser.Normalize(tagTitle);
|
var normalizedTitle = Tasks.Scanner.Parser.Parser.Normalize(tagTitle);
|
||||||
var existingTag = allTags.SingleOrDefault(t => t.NormalizedTitle == normalizedTitle);
|
var existingTag = allTags.SingleOrDefault(t => t.NormalizedTitle == normalizedTitle);
|
||||||
if (existingTag != null)
|
if (existingTag != null)
|
||||||
{
|
{
|
||||||
@ -295,7 +295,7 @@ public class SeriesService : ISeriesService
|
|||||||
// At this point, all tags that aren't in dto have been removed.
|
// At this point, all tags that aren't in dto have been removed.
|
||||||
foreach (var tagTitle in tags.Select(t => t.Title))
|
foreach (var tagTitle in tags.Select(t => t.Title))
|
||||||
{
|
{
|
||||||
var normalizedTitle = Parser.Parser.Normalize(tagTitle);
|
var normalizedTitle = Tasks.Scanner.Parser.Parser.Normalize(tagTitle);
|
||||||
var existingTag = allTags.SingleOrDefault(t => t.NormalizedTitle.Equals(normalizedTitle));
|
var existingTag = allTags.SingleOrDefault(t => t.NormalizedTitle.Equals(normalizedTitle));
|
||||||
if (existingTag != null)
|
if (existingTag != null)
|
||||||
{
|
{
|
||||||
@ -465,7 +465,7 @@ public class SeriesService : ISeriesService
|
|||||||
|
|
||||||
var libraryType = await _unitOfWork.LibraryRepository.GetLibraryTypeAsync(series.LibraryId);
|
var libraryType = await _unitOfWork.LibraryRepository.GetLibraryTypeAsync(series.LibraryId);
|
||||||
var volumes = (await _unitOfWork.VolumeRepository.GetVolumesDtoAsync(seriesId, userId))
|
var volumes = (await _unitOfWork.VolumeRepository.GetVolumesDtoAsync(seriesId, userId))
|
||||||
.OrderBy(v => Parser.Parser.MinNumberFromRange(v.Name))
|
.OrderBy(v => Tasks.Scanner.Parser.Parser.MinNumberFromRange(v.Name))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// For books, the Name of the Volume is remapped to the actual name of the book, rather than Volume number.
|
// For books, the Name of the Volume is remapped to the actual name of the book, rather than Volume number.
|
||||||
@ -542,7 +542,7 @@ public class SeriesService : ISeriesService
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private static bool ShouldIncludeChapter(ChapterDto chapter)
|
private static bool ShouldIncludeChapter(ChapterDto chapter)
|
||||||
{
|
{
|
||||||
return !chapter.IsSpecial && !chapter.Number.Equals(Parser.Parser.DefaultChapter);
|
return !chapter.IsSpecial && !chapter.Number.Equals(Tasks.Scanner.Parser.Parser.DefaultChapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RenameVolumeName(ChapterDto firstChapter, VolumeDto volume, LibraryType libraryType)
|
public static void RenameVolumeName(ChapterDto firstChapter, VolumeDto volume, LibraryType libraryType)
|
||||||
@ -551,7 +551,7 @@ public class SeriesService : ISeriesService
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(firstChapter.TitleName))
|
if (string.IsNullOrEmpty(firstChapter.TitleName))
|
||||||
{
|
{
|
||||||
if (firstChapter.Range.Equals(Parser.Parser.DefaultVolume)) return;
|
if (firstChapter.Range.Equals(Tasks.Scanner.Parser.Parser.DefaultVolume)) return;
|
||||||
var title = Path.GetFileNameWithoutExtension(firstChapter.Range);
|
var title = Path.GetFileNameWithoutExtension(firstChapter.Range);
|
||||||
if (string.IsNullOrEmpty(title)) return;
|
if (string.IsNullOrEmpty(title)) return;
|
||||||
volume.Name += $" - {title}";
|
volume.Name += $" - {title}";
|
||||||
@ -572,7 +572,7 @@ public class SeriesService : ISeriesService
|
|||||||
{
|
{
|
||||||
if (isSpecial)
|
if (isSpecial)
|
||||||
{
|
{
|
||||||
return Parser.Parser.CleanSpecialTitle(chapterTitle);
|
return Tasks.Scanner.Parser.Parser.CleanSpecialTitle(chapterTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
var hashSpot = withHash ? "#" : string.Empty;
|
var hashSpot = withHash ? "#" : string.Empty;
|
||||||
|
@ -168,7 +168,7 @@ public class TaskScheduler : ITaskScheduler
|
|||||||
|
|
||||||
public void ScanFolder(string folderPath)
|
public void ScanFolder(string folderPath)
|
||||||
{
|
{
|
||||||
_scannerService.ScanFolder(Parser.Parser.NormalizePath(folderPath));
|
_scannerService.ScanFolder(Tasks.Scanner.Parser.Parser.NormalizePath(folderPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -36,15 +36,15 @@ public class DefaultParser : IDefaultParser
|
|||||||
var fileName = _directoryService.FileSystem.Path.GetFileNameWithoutExtension(filePath);
|
var fileName = _directoryService.FileSystem.Path.GetFileNameWithoutExtension(filePath);
|
||||||
ParserInfo ret;
|
ParserInfo ret;
|
||||||
|
|
||||||
if (Parser.IsEpub(filePath))
|
if (Services.Tasks.Scanner.Parser.Parser.IsEpub(filePath))
|
||||||
{
|
{
|
||||||
ret = new ParserInfo()
|
ret = new ParserInfo()
|
||||||
{
|
{
|
||||||
Chapters = Parser.ParseChapter(fileName) ?? Parser.ParseComicChapter(fileName),
|
Chapters = Services.Tasks.Scanner.Parser.Parser.ParseChapter(fileName) ?? Services.Tasks.Scanner.Parser.Parser.ParseComicChapter(fileName),
|
||||||
Series = Parser.ParseSeries(fileName) ?? Parser.ParseComicSeries(fileName),
|
Series = Services.Tasks.Scanner.Parser.Parser.ParseSeries(fileName) ?? Services.Tasks.Scanner.Parser.Parser.ParseComicSeries(fileName),
|
||||||
Volumes = Parser.ParseVolume(fileName) ?? Parser.ParseComicVolume(fileName),
|
Volumes = Services.Tasks.Scanner.Parser.Parser.ParseVolume(fileName) ?? Services.Tasks.Scanner.Parser.Parser.ParseComicVolume(fileName),
|
||||||
Filename = Path.GetFileName(filePath),
|
Filename = Path.GetFileName(filePath),
|
||||||
Format = Parser.ParseFormat(filePath),
|
Format = Services.Tasks.Scanner.Parser.Parser.ParseFormat(filePath),
|
||||||
FullFilePath = filePath
|
FullFilePath = filePath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -52,65 +52,65 @@ public class DefaultParser : IDefaultParser
|
|||||||
{
|
{
|
||||||
ret = new ParserInfo()
|
ret = new ParserInfo()
|
||||||
{
|
{
|
||||||
Chapters = type == LibraryType.Comic ? Parser.ParseComicChapter(fileName) : Parser.ParseChapter(fileName),
|
Chapters = type == LibraryType.Comic ? Services.Tasks.Scanner.Parser.Parser.ParseComicChapter(fileName) : Services.Tasks.Scanner.Parser.Parser.ParseChapter(fileName),
|
||||||
Series = type == LibraryType.Comic ? Parser.ParseComicSeries(fileName) : Parser.ParseSeries(fileName),
|
Series = type == LibraryType.Comic ? Services.Tasks.Scanner.Parser.Parser.ParseComicSeries(fileName) : Services.Tasks.Scanner.Parser.Parser.ParseSeries(fileName),
|
||||||
Volumes = type == LibraryType.Comic ? Parser.ParseComicVolume(fileName) : Parser.ParseVolume(fileName),
|
Volumes = type == LibraryType.Comic ? Services.Tasks.Scanner.Parser.Parser.ParseComicVolume(fileName) : Services.Tasks.Scanner.Parser.Parser.ParseVolume(fileName),
|
||||||
Filename = Path.GetFileName(filePath),
|
Filename = Path.GetFileName(filePath),
|
||||||
Format = Parser.ParseFormat(filePath),
|
Format = Services.Tasks.Scanner.Parser.Parser.ParseFormat(filePath),
|
||||||
Title = Path.GetFileNameWithoutExtension(fileName),
|
Title = Path.GetFileNameWithoutExtension(fileName),
|
||||||
FullFilePath = filePath
|
FullFilePath = filePath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Parser.IsImage(filePath) && Parser.IsCoverImage(filePath)) return null;
|
if (Services.Tasks.Scanner.Parser.Parser.IsImage(filePath) && Services.Tasks.Scanner.Parser.Parser.IsCoverImage(filePath)) return null;
|
||||||
|
|
||||||
if (Parser.IsImage(filePath))
|
if (Services.Tasks.Scanner.Parser.Parser.IsImage(filePath))
|
||||||
{
|
{
|
||||||
// Reset Chapters, Volumes, and Series as images are not good to parse information out of. Better to use folders.
|
// Reset Chapters, Volumes, and Series as images are not good to parse information out of. Better to use folders.
|
||||||
ret.Volumes = Parser.DefaultVolume;
|
ret.Volumes = Services.Tasks.Scanner.Parser.Parser.DefaultVolume;
|
||||||
ret.Chapters = Parser.DefaultChapter;
|
ret.Chapters = Services.Tasks.Scanner.Parser.Parser.DefaultChapter;
|
||||||
ret.Series = string.Empty;
|
ret.Series = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret.Series == string.Empty || Parser.IsImage(filePath))
|
if (ret.Series == string.Empty || Services.Tasks.Scanner.Parser.Parser.IsImage(filePath))
|
||||||
{
|
{
|
||||||
// Try to parse information out of each folder all the way to rootPath
|
// Try to parse information out of each folder all the way to rootPath
|
||||||
ParseFromFallbackFolders(filePath, rootPath, type, ref ret);
|
ParseFromFallbackFolders(filePath, rootPath, type, ref ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
var edition = Parser.ParseEdition(fileName);
|
var edition = Services.Tasks.Scanner.Parser.Parser.ParseEdition(fileName);
|
||||||
if (!string.IsNullOrEmpty(edition))
|
if (!string.IsNullOrEmpty(edition))
|
||||||
{
|
{
|
||||||
ret.Series = Parser.CleanTitle(ret.Series.Replace(edition, ""), type is LibraryType.Comic);
|
ret.Series = Services.Tasks.Scanner.Parser.Parser.CleanTitle(ret.Series.Replace(edition, ""), type is LibraryType.Comic);
|
||||||
ret.Edition = edition;
|
ret.Edition = edition;
|
||||||
}
|
}
|
||||||
|
|
||||||
var isSpecial = type == LibraryType.Comic ? Parser.ParseComicSpecial(fileName) : Parser.ParseMangaSpecial(fileName);
|
var isSpecial = type == LibraryType.Comic ? Services.Tasks.Scanner.Parser.Parser.ParseComicSpecial(fileName) : Services.Tasks.Scanner.Parser.Parser.ParseMangaSpecial(fileName);
|
||||||
// We must ensure that we can only parse a special out. As some files will have v20 c171-180+Omake and that
|
// 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.
|
// could cause a problem as Omake is a special term, but there is valid volume/chapter information.
|
||||||
if (ret.Chapters == Parser.DefaultChapter && ret.Volumes == Parser.DefaultVolume && !string.IsNullOrEmpty(isSpecial))
|
if (ret.Chapters == Services.Tasks.Scanner.Parser.Parser.DefaultChapter && ret.Volumes == Services.Tasks.Scanner.Parser.Parser.DefaultVolume && !string.IsNullOrEmpty(isSpecial))
|
||||||
{
|
{
|
||||||
ret.IsSpecial = true;
|
ret.IsSpecial = true;
|
||||||
ParseFromFallbackFolders(filePath, rootPath, type, ref ret); // NOTE: This can cause some complications, we should try to be a bit less aggressive to fallback to folder
|
ParseFromFallbackFolders(filePath, rootPath, type, ref ret); // NOTE: This can cause some complications, we should try to be a bit less aggressive to fallback to folder
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are a special with marker, we need to ensure we use the correct series name. we can do this by falling back to Folder name
|
// If we are a special with marker, we need to ensure we use the correct series name. we can do this by falling back to Folder name
|
||||||
if (Parser.HasSpecialMarker(fileName))
|
if (Services.Tasks.Scanner.Parser.Parser.HasSpecialMarker(fileName))
|
||||||
{
|
{
|
||||||
ret.IsSpecial = true;
|
ret.IsSpecial = true;
|
||||||
ret.Chapters = Parser.DefaultChapter;
|
ret.Chapters = Services.Tasks.Scanner.Parser.Parser.DefaultChapter;
|
||||||
ret.Volumes = Parser.DefaultVolume;
|
ret.Volumes = Services.Tasks.Scanner.Parser.Parser.DefaultVolume;
|
||||||
|
|
||||||
ParseFromFallbackFolders(filePath, rootPath, type, ref ret);
|
ParseFromFallbackFolders(filePath, rootPath, type, ref ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(ret.Series))
|
if (string.IsNullOrEmpty(ret.Series))
|
||||||
{
|
{
|
||||||
ret.Series = Parser.CleanTitle(fileName, type is LibraryType.Comic);
|
ret.Series = Services.Tasks.Scanner.Parser.Parser.CleanTitle(fileName, type is LibraryType.Comic);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pdfs may have .pdf in the series name, remove that
|
// Pdfs may have .pdf in the series name, remove that
|
||||||
if (Parser.IsPdf(filePath) && ret.Series.ToLower().EndsWith(".pdf"))
|
if (Services.Tasks.Scanner.Parser.Parser.IsPdf(filePath) && ret.Series.ToLower().EndsWith(".pdf"))
|
||||||
{
|
{
|
||||||
ret.Series = ret.Series.Substring(0, ret.Series.Length - ".pdf".Length);
|
ret.Series = ret.Series.Substring(0, ret.Series.Length - ".pdf".Length);
|
||||||
}
|
}
|
||||||
@ -131,18 +131,18 @@ public class DefaultParser : IDefaultParser
|
|||||||
for (var i = 0; i < fallbackFolders.Count; i++)
|
for (var i = 0; i < fallbackFolders.Count; i++)
|
||||||
{
|
{
|
||||||
var folder = fallbackFolders[i];
|
var folder = fallbackFolders[i];
|
||||||
if (!string.IsNullOrEmpty(Parser.ParseMangaSpecial(folder))) continue;
|
if (!string.IsNullOrEmpty(Services.Tasks.Scanner.Parser.Parser.ParseMangaSpecial(folder))) continue;
|
||||||
|
|
||||||
var parsedVolume = type is LibraryType.Manga ? Parser.ParseVolume(folder) : Parser.ParseComicVolume(folder);
|
var parsedVolume = type is LibraryType.Manga ? Services.Tasks.Scanner.Parser.Parser.ParseVolume(folder) : Services.Tasks.Scanner.Parser.Parser.ParseComicVolume(folder);
|
||||||
var parsedChapter = type is LibraryType.Manga ? Parser.ParseChapter(folder) : Parser.ParseComicChapter(folder);
|
var parsedChapter = type is LibraryType.Manga ? Services.Tasks.Scanner.Parser.Parser.ParseChapter(folder) : Services.Tasks.Scanner.Parser.Parser.ParseComicChapter(folder);
|
||||||
|
|
||||||
if (!parsedVolume.Equals(Parser.DefaultVolume) || !parsedChapter.Equals(Parser.DefaultChapter))
|
if (!parsedVolume.Equals(Services.Tasks.Scanner.Parser.Parser.DefaultVolume) || !parsedChapter.Equals(Services.Tasks.Scanner.Parser.Parser.DefaultChapter))
|
||||||
{
|
{
|
||||||
if ((string.IsNullOrEmpty(ret.Volumes) || ret.Volumes.Equals(Parser.DefaultVolume)) && !parsedVolume.Equals(Parser.DefaultVolume))
|
if ((string.IsNullOrEmpty(ret.Volumes) || ret.Volumes.Equals(Services.Tasks.Scanner.Parser.Parser.DefaultVolume)) && !parsedVolume.Equals(Services.Tasks.Scanner.Parser.Parser.DefaultVolume))
|
||||||
{
|
{
|
||||||
ret.Volumes = parsedVolume;
|
ret.Volumes = parsedVolume;
|
||||||
}
|
}
|
||||||
if ((string.IsNullOrEmpty(ret.Chapters) || ret.Chapters.Equals(Parser.DefaultChapter)) && !parsedChapter.Equals(Parser.DefaultChapter))
|
if ((string.IsNullOrEmpty(ret.Chapters) || ret.Chapters.Equals(Services.Tasks.Scanner.Parser.Parser.DefaultChapter)) && !parsedChapter.Equals(Services.Tasks.Scanner.Parser.Parser.DefaultChapter))
|
||||||
{
|
{
|
||||||
ret.Chapters = parsedChapter;
|
ret.Chapters = parsedChapter;
|
||||||
}
|
}
|
||||||
@ -151,11 +151,11 @@ public class DefaultParser : IDefaultParser
|
|||||||
// Generally users group in series folders. Let's try to parse series from the top folder
|
// Generally users group in series folders. Let's try to parse series from the top folder
|
||||||
if (!folder.Equals(ret.Series) && i == fallbackFolders.Count - 1)
|
if (!folder.Equals(ret.Series) && i == fallbackFolders.Count - 1)
|
||||||
{
|
{
|
||||||
var series = Parser.ParseSeries(folder);
|
var series = Services.Tasks.Scanner.Parser.Parser.ParseSeries(folder);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(series))
|
if (string.IsNullOrEmpty(series))
|
||||||
{
|
{
|
||||||
ret.Series = Parser.CleanTitle(folder, type is LibraryType.Comic);
|
ret.Series = Services.Tasks.Scanner.Parser.Parser.CleanTitle(folder, type is LibraryType.Comic);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ using System.Linq;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using API.Entities.Enums;
|
using API.Entities.Enums;
|
||||||
|
|
||||||
namespace API.Parser
|
namespace API.Services.Tasks.Scanner.Parser
|
||||||
{
|
{
|
||||||
public static class Parser
|
public static class Parser
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using API.Data.Metadata;
|
using API.Data.Metadata;
|
||||||
using API.Entities.Enums;
|
using API.Entities.Enums;
|
||||||
|
using API.Services.Tasks.Scanner.Parser;
|
||||||
|
|
||||||
namespace API.Parser
|
namespace API.Parser
|
||||||
{
|
{
|
||||||
|
@ -111,11 +111,11 @@ public class ScannerService : IScannerService
|
|||||||
|
|
||||||
var libraries = (await _unitOfWork.LibraryRepository.GetLibraryDtosAsync()).ToList();
|
var libraries = (await _unitOfWork.LibraryRepository.GetLibraryDtosAsync()).ToList();
|
||||||
var libraryFolders = libraries.SelectMany(l => l.Folders);
|
var libraryFolders = libraries.SelectMany(l => l.Folders);
|
||||||
var libraryFolder = libraryFolders.Select(Parser.Parser.NormalizePath).SingleOrDefault(f => f.Contains(parentDirectory));
|
var libraryFolder = libraryFolders.Select(Scanner.Parser.Parser.NormalizePath).SingleOrDefault(f => f.Contains(parentDirectory));
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(libraryFolder)) return;
|
if (string.IsNullOrEmpty(libraryFolder)) return;
|
||||||
|
|
||||||
var library = libraries.FirstOrDefault(l => l.Folders.Select(Parser.Parser.NormalizePath).Contains(libraryFolder));
|
var library = libraries.FirstOrDefault(l => l.Folders.Select(Scanner.Parser.Parser.NormalizePath).Contains(libraryFolder));
|
||||||
if (library != null)
|
if (library != null)
|
||||||
{
|
{
|
||||||
BackgroundJob.Enqueue(() => ScanLibrary(library.Id, false));
|
BackgroundJob.Enqueue(() => ScanLibrary(library.Id, false));
|
||||||
@ -188,7 +188,7 @@ public class ScannerService : IScannerService
|
|||||||
var foundParsedSeries = new ParsedSeries()
|
var foundParsedSeries = new ParsedSeries()
|
||||||
{
|
{
|
||||||
Name = parsedFiles.First().Series,
|
Name = parsedFiles.First().Series,
|
||||||
NormalizedName = Parser.Parser.Normalize(parsedFiles.First().Series),
|
NormalizedName = Scanner.Parser.Parser.Normalize(parsedFiles.First().Series),
|
||||||
Format = parsedFiles.First().Format
|
Format = parsedFiles.First().Format
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -457,7 +457,7 @@ public class ScannerService : IScannerService
|
|||||||
var foundParsedSeries = new ParsedSeries()
|
var foundParsedSeries = new ParsedSeries()
|
||||||
{
|
{
|
||||||
Name = parsedFiles.First().Series,
|
Name = parsedFiles.First().Series,
|
||||||
NormalizedName = Parser.Parser.Normalize(parsedFiles.First().Series),
|
NormalizedName = Scanner.Parser.Parser.Normalize(parsedFiles.First().Series),
|
||||||
Format = parsedFiles.First().Format
|
Format = parsedFiles.First().Format
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -466,7 +466,7 @@ public class ScannerService : IScannerService
|
|||||||
seenSeries.AddRange(parsedFiles.Select(pf => new ParsedSeries()
|
seenSeries.AddRange(parsedFiles.Select(pf => new ParsedSeries()
|
||||||
{
|
{
|
||||||
Name = pf.Series,
|
Name = pf.Series,
|
||||||
NormalizedName = Parser.Parser.Normalize(pf.Series),
|
NormalizedName = Scanner.Parser.Parser.Normalize(pf.Series),
|
||||||
Format = pf.Format
|
Format = pf.Format
|
||||||
}));
|
}));
|
||||||
return;
|
return;
|
||||||
|
@ -55,8 +55,8 @@ public class ThemeService : IThemeService
|
|||||||
_directoryService.ExistOrCreate(_directoryService.SiteThemeDirectory);
|
_directoryService.ExistOrCreate(_directoryService.SiteThemeDirectory);
|
||||||
var reservedNames = Seed.DefaultThemes.Select(t => t.NormalizedName).ToList();
|
var reservedNames = Seed.DefaultThemes.Select(t => t.NormalizedName).ToList();
|
||||||
var themeFiles = _directoryService
|
var themeFiles = _directoryService
|
||||||
.GetFilesWithExtension(Parser.Parser.NormalizePath(_directoryService.SiteThemeDirectory), @"\.css")
|
.GetFilesWithExtension(Scanner.Parser.Parser.NormalizePath(_directoryService.SiteThemeDirectory), @"\.css")
|
||||||
.Where(name => !reservedNames.Contains(Parser.Parser.Normalize(name))).ToList();
|
.Where(name => !reservedNames.Contains(Scanner.Parser.Parser.Normalize(name))).ToList();
|
||||||
|
|
||||||
var allThemes = (await _unitOfWork.SiteThemeRepository.GetThemes()).ToList();
|
var allThemes = (await _unitOfWork.SiteThemeRepository.GetThemes()).ToList();
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ public class ThemeService : IThemeService
|
|||||||
var userThemes = allThemes.Where(t => t.Provider == ThemeProvider.User).ToList();
|
var userThemes = allThemes.Where(t => t.Provider == ThemeProvider.User).ToList();
|
||||||
foreach (var userTheme in userThemes)
|
foreach (var userTheme in userThemes)
|
||||||
{
|
{
|
||||||
var filepath = Parser.Parser.NormalizePath(
|
var filepath = Scanner.Parser.Parser.NormalizePath(
|
||||||
_directoryService.FileSystem.Path.Join(_directoryService.SiteThemeDirectory, userTheme.FileName));
|
_directoryService.FileSystem.Path.Join(_directoryService.SiteThemeDirectory, userTheme.FileName));
|
||||||
if (_directoryService.FileSystem.File.Exists(filepath)) continue;
|
if (_directoryService.FileSystem.File.Exists(filepath)) continue;
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ public class ThemeService : IThemeService
|
|||||||
foreach (var themeFile in themeFiles)
|
foreach (var themeFile in themeFiles)
|
||||||
{
|
{
|
||||||
var themeName =
|
var themeName =
|
||||||
Parser.Parser.Normalize(_directoryService.FileSystem.Path.GetFileNameWithoutExtension(themeFile));
|
Scanner.Parser.Parser.Normalize(_directoryService.FileSystem.Path.GetFileNameWithoutExtension(themeFile));
|
||||||
if (allThemeNames.Contains(themeName)) continue;
|
if (allThemeNames.Contains(themeName)) continue;
|
||||||
|
|
||||||
_unitOfWork.SiteThemeRepository.Add(new SiteTheme()
|
_unitOfWork.SiteThemeRepository.Add(new SiteTheme()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user