Added basic parsing and unit tests. Setting up an intermediate object to hold information from parser. Removed hangfire db from git.
This commit is contained in:
parent
4fd9943b91
commit
8c80ed090d
13 changed files with 347 additions and 8 deletions
|
|
@ -32,4 +32,8 @@
|
|||
<Folder Include="Tasks" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Hangfire-log.db" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -8,12 +8,10 @@ namespace API.Controllers
|
|||
{
|
||||
public class AdminController : BaseApiController
|
||||
{
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly UserManager<AppUser> _userManager;
|
||||
|
||||
public AdminController(IUserRepository userRepository, UserManager<AppUser> userManager)
|
||||
public AdminController(UserManager<AppUser> userManager)
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ namespace API.Controllers
|
|||
return BadRequest("Library name already exists. Please choose a unique name to the server.");
|
||||
}
|
||||
|
||||
// TODO: We probably need to clean the folders before we insert
|
||||
// TODO: We probably need to normalize the folders before we insert
|
||||
var library = new Library
|
||||
{
|
||||
Name = createLibraryDto.Name.ToLower(),
|
||||
|
|
|
|||
Binary file not shown.
BIN
API/Hangfire.db
BIN
API/Hangfire.db
Binary file not shown.
200
API/Parser/Parser.cs
Normal file
200
API/Parser/Parser.cs
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace API.Parser
|
||||
{
|
||||
public static class Parser
|
||||
{
|
||||
//?: is a non-capturing group in C#, else anything in () will be a group
|
||||
private static readonly Regex[] MangaVolumeRegex = new[]
|
||||
{
|
||||
// Historys Strongest Disciple Kenichi_v11_c90-98.zip
|
||||
new Regex(
|
||||
|
||||
@"(?<Series>.*)(\b|_)v(?<Volume>\d+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
// Killing Bites Vol. 0001 Ch. 0001 - Galactica Scanlations (gb)
|
||||
new Regex(
|
||||
@"(vol. ?)(?<Volume>0*[1-9]+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
// Dance in the Vampire Bund v16-17
|
||||
new Regex(
|
||||
|
||||
@"(?<Series>.*)(\b|_)v(?<Volume>\d+-?\d+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
new Regex(
|
||||
@"(?:v)(?<Volume>0*[1-9]+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
};
|
||||
|
||||
private static readonly Regex[] MangaSeriesRegex = new[]
|
||||
{
|
||||
// Gokukoku no Brynhildr - c001-008 (v01) [TrinityBAKumA], Black Bullet - v4 c17 [batoto]
|
||||
new Regex(
|
||||
|
||||
@"(?<Series>.*)( - )(?:v|vo|c)\d",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
// Historys Strongest Disciple Kenichi_v11_c90-98.zip, Killing Bites Vol. 0001 Ch. 0001 - Galactica Scanlations (gb)
|
||||
new Regex(
|
||||
|
||||
@"(?<Series>.*)(\b|_)v",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
// Black Bullet
|
||||
new Regex(
|
||||
|
||||
@"(?<Series>.*)(\b|_)(v|vo|c)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
// [BAA]_Darker_than_Black_c1 (This is very greedy, make sure it's always last)
|
||||
new Regex(
|
||||
@"(?<Series>.*)(\b|_)(c)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
|
||||
};
|
||||
|
||||
private static readonly Regex[] ReleaseGroupRegex = new[]
|
||||
{
|
||||
// [TrinityBAKumA Finella&anon], [BAA]_, [SlowManga&OverloadScans], [batoto]
|
||||
new Regex(@"(?:\[(?<subgroup>(?!\s).+?(?<!\s))\](?:_|-|\s|\.)?)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
// (Shadowcat-Empire),
|
||||
// new Regex(@"(?:\[(?<subgroup>(?!\s).+?(?<!\s))\](?:_|-|\s|\.)?)",
|
||||
// RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
};
|
||||
|
||||
private static readonly Regex[] MangaChapterRegex = new[]
|
||||
{
|
||||
new Regex(
|
||||
|
||||
@"(c|ch)(\.? ?)(?<Chapter>\d+-?\d*)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
};
|
||||
|
||||
public static string ParseSeries(string filename)
|
||||
{
|
||||
foreach (var regex in MangaSeriesRegex)
|
||||
{
|
||||
var matches = regex.Matches(filename);
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
if (match.Groups["Volume"] != Match.Empty)
|
||||
{
|
||||
return CleanTitle(match.Groups["Series"].Value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Unable to parse {0}", filename);
|
||||
return "";
|
||||
}
|
||||
|
||||
public static string ParseVolume(string filename)
|
||||
{
|
||||
foreach (var regex in MangaVolumeRegex)
|
||||
{
|
||||
var matches = regex.Matches(filename);
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
if (match.Groups["Volume"] != Match.Empty)
|
||||
{
|
||||
return RemoveLeadingZeroes(match.Groups["Volume"].Value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Unable to parse {0}", filename);
|
||||
return "";
|
||||
}
|
||||
|
||||
public static string ParseChapter(string filename)
|
||||
{
|
||||
foreach (var regex in MangaChapterRegex)
|
||||
{
|
||||
var matches = regex.Matches(filename);
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
if (match.Groups["Chapter"] != Match.Empty)
|
||||
{
|
||||
var value = match.Groups["Chapter"].Value;
|
||||
|
||||
|
||||
if (value.Contains("-"))
|
||||
{
|
||||
var tokens = value.Split("-");
|
||||
var from = RemoveLeadingZeroes(tokens[0]);
|
||||
var to = RemoveLeadingZeroes(tokens[1]);
|
||||
return $"{from}-{to}";
|
||||
}
|
||||
|
||||
return RemoveLeadingZeroes(match.Groups["Chapter"].Value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translates _ -> spaces, trims front and back of string, removes release groups
|
||||
/// </summary>
|
||||
/// <param name="title"></param>
|
||||
/// <returns></returns>
|
||||
public static string CleanTitle(string title)
|
||||
{
|
||||
foreach (var regex in ReleaseGroupRegex)
|
||||
{
|
||||
var matches = regex.Matches(title);
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
if (match.Success)
|
||||
{
|
||||
title = title.Replace(match.Value, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
title = title.Replace("_", " ");
|
||||
return title.Trim();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Pads the start of a number string with 0's so ordering works fine if there are over 100 items.
|
||||
/// Handles ranges (ie 4-8) -> (004-008).
|
||||
/// </summary>
|
||||
/// <param name="number"></param>
|
||||
/// <returns>A zero padded number</returns>
|
||||
public static string PadZeros(string number)
|
||||
{
|
||||
if (number.Contains("-"))
|
||||
{
|
||||
var tokens = number.Split("-");
|
||||
return $"{PerformPadding(tokens[0])}-{PerformPadding(tokens[1])}";
|
||||
}
|
||||
|
||||
return PerformPadding(number);
|
||||
}
|
||||
|
||||
private static string PerformPadding(string number)
|
||||
{
|
||||
var num = Int32.Parse(number);
|
||||
return num switch
|
||||
{
|
||||
< 10 => "00" + num,
|
||||
< 100 => "0" + num,
|
||||
_ => number
|
||||
};
|
||||
}
|
||||
|
||||
public static string RemoveLeadingZeroes(string title)
|
||||
{
|
||||
return title.TrimStart(new Char[] { '0' });
|
||||
}
|
||||
}
|
||||
}
|
||||
14
API/Parser/ParserInfo.cs
Normal file
14
API/Parser/ParserInfo.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace API.Parser
|
||||
{
|
||||
public class ParserInfo
|
||||
{
|
||||
// This can be multiple
|
||||
public string Chapters { get; set; }
|
||||
public string Series { get; set; }
|
||||
// This can be multiple
|
||||
public string Volume { get; set; }
|
||||
public IEnumerable<string> Files { get; init; }
|
||||
}
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ namespace API.Services
|
|||
});
|
||||
}
|
||||
catch (ArgumentException) {
|
||||
Console.WriteLine(@"The directory 'C:\Program Files' does not exist.");
|
||||
_logger.LogError($"The directory '{folderPath}' does not exist");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +79,7 @@ namespace API.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
|
||||
// Determine whether to parallelize file processing on each folder based on processor count.
|
||||
int procCount = System.Environment.ProcessorCount;
|
||||
int procCount = Environment.ProcessorCount;
|
||||
|
||||
// Data structure to hold names of subfolders to be examined for files.
|
||||
Stack<string> dirs = new Stack<string>();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Data source=kavita.db",
|
||||
"HangfireConnection": "Data source=hangfire.db"
|
||||
},
|
||||
"TokenKey": "super secret unguessable key",
|
||||
"Logging": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue