Implemented a Generic Library that uses Regex from the admin to parse the files. Still a bit of a WIP on how it's actually going to work or if it will be usable.

This commit is contained in:
Joseph Milazzo 2024-03-15 12:26:19 -05:00
parent 9d31262448
commit 6f4162d793
22 changed files with 224 additions and 60 deletions

View file

@ -1,4 +1,5 @@
using System.IO;
using System.Collections.Generic;
using System.IO;
using API.Data.Metadata;
using API.Entities.Enums;
@ -11,7 +12,8 @@ namespace API.Services.Tasks.Scanner.Parser;
/// </summary>
public class BasicParser(IDirectoryService directoryService, IDefaultParser imageParser) : DefaultParser(directoryService)
{
public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null)
public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type,
ComicInfo? comicInfo = null, IEnumerable<string>? extraRegex = null)
{
var fileName = directoryService.FileSystem.Path.GetFileNameWithoutExtension(filePath);
// TODO: Potential Bug: This will return null, but on Image libraries, if all images, we would want to include this.

View file

@ -1,11 +1,13 @@
using API.Data.Metadata;
using System.Collections.Generic;
using API.Data.Metadata;
using API.Entities.Enums;
namespace API.Services.Tasks.Scanner.Parser;
public class BookParser(IDirectoryService directoryService, IBookService bookService, IDefaultParser basicParser) : DefaultParser(directoryService)
{
public override ParserInfo Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo comicInfo = null)
public override ParserInfo Parse(string filePath, string rootPath, string libraryRoot, LibraryType type,
ComicInfo? comicInfo = null, IEnumerable<string>? extraRegex = null)
{
var info = bookService.ParseInfo(filePath);
if (info == null) return null;

View file

@ -1,4 +1,5 @@
using System.IO;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using API.Data.Metadata;
using API.Entities.Enums;
@ -15,11 +16,8 @@ public class ComicVineParser(IDirectoryService directoryService) : DefaultParser
/// <summary>
/// This Parser generates Series name to be defined as Series + first Issue Volume, so "Batman (2020)".
/// </summary>
/// <param name="filePath"></param>
/// <param name="rootPath"></param>
/// <param name="type"></param>
/// <returns></returns>
public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null)
public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type,
ComicInfo? comicInfo = null, IEnumerable<string>? extraRegex = null)
{
if (type != LibraryType.ComicVine) return null;

View file

@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using API.Data.Metadata;
@ -8,7 +9,7 @@ namespace API.Services.Tasks.Scanner.Parser;
public interface IDefaultParser
{
ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null);
ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null, IEnumerable<string>? extraRegex = null);
void ParseFromFallbackFolders(string filePath, string rootPath, LibraryType type, ref ParserInfo ret);
bool IsApplicable(string filePath, LibraryType type);
}
@ -26,8 +27,11 @@ public abstract class DefaultParser(IDirectoryService directoryService) : IDefau
/// <param name="filePath"></param>
/// <param name="rootPath">Root folder</param>
/// <param name="type">Allows different Regex to be used for parsing.</param>
/// <param name="comicInfo">ComicInfo if present (for epub it si always present)</param>
/// <param name="extraRegex">The regex for the Generic Parser</param>
/// <returns><see cref="ParserInfo"/> or null if Series was empty</returns>
public abstract ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null);
public abstract ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type,
ComicInfo? comicInfo = null, IEnumerable<string>? extraRegex = null);
/// <summary>
/// Fills out <see cref="ParserInfo"/> by trying to parse volume, chapters, and series from folders

View file

@ -0,0 +1,90 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using API.Data.Metadata;
using API.Entities.Enums;
namespace API.Services.Tasks.Scanner.Parser;
#nullable enable
/// <summary>
/// Uses an at-runtime array of Regex to parse out information
/// </summary>
/// <param name="directoryService"></param>
public class GenericLibraryParser(IDirectoryService directoryService) : DefaultParser(directoryService)
{
public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type,
ComicInfo? comicInfo = null, IEnumerable<string>? extraRegex = null)
{
if (extraRegex == null) return null;
// The idea is this is passed in as a default param. Only Generic will use it
var fileName = directoryService.FileSystem.Path.GetFileNameWithoutExtension(filePath);
var info = new ParserInfo()
{
Filename = Path.GetFileName(filePath),
Format = Parser.ParseFormat(filePath),
Title = Parser.RemoveExtensionIfSupported(fileName)!,
FullFilePath = filePath,
Series = string.Empty,
ComicInfo = comicInfo,
Chapters = Parser.ParseComicChapter(fileName),
Volumes = Parser.ParseComicVolume(fileName)
};
foreach (var regex in extraRegex)
{
var matches = new Regex(regex, RegexOptions.IgnoreCase).Matches(fileName);
foreach (var group in matches.Select(match => match.Groups))
{
foreach (var matchKey in group.Keys)
{
var matchValue = group[matchKey].Value;
switch (matchKey)
{
case "Series":
info.Series = SetIfNotDefault(matchValue, info.Series);
break;
case "Chapter":
info.Chapters = SetIfNotDefault(matchValue, info.Chapters);
break;
}
}
}
}
// Process the final info here: (cleaning values, setting internal encoding overrides)
if (info.IsSpecial)
{
info.Volumes = Parser.SpecialVolume;
}
if (string.IsNullOrEmpty(info.Chapters))
{
info.Chapters = Parser.DefaultChapter;
}
if (!info.IsSpecial && string.IsNullOrEmpty(info.Volumes))
{
info.Chapters = Parser.LooseLeafVolume;
}
return string.IsNullOrEmpty(info.Series) ? null : info;
}
private static string SetIfNotDefault(string value, string originalValue)
{
if (string.IsNullOrEmpty(value)) return originalValue;
if (string.IsNullOrEmpty(originalValue)) return value;
return originalValue;
}
public override bool IsApplicable(string filePath, LibraryType type)
{
return type == LibraryType.Generic;
}
}

View file

@ -1,4 +1,5 @@
using System.IO;
using System.Collections.Generic;
using System.IO;
using API.Data.Metadata;
using API.Entities.Enums;
@ -7,7 +8,8 @@ namespace API.Services.Tasks.Scanner.Parser;
public class ImageParser(IDirectoryService directoryService) : DefaultParser(directoryService)
{
public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null)
public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type,
ComicInfo? comicInfo = null, IEnumerable<string>? extraRegex = null)
{
if (type != LibraryType.Image || !Parser.IsImage(filePath)) return null;

View file

@ -1,4 +1,5 @@
using System.IO;
using System.Collections.Generic;
using System.IO;
using API.Data.Metadata;
using API.Entities.Enums;
@ -6,7 +7,8 @@ namespace API.Services.Tasks.Scanner.Parser;
public class PdfParser(IDirectoryService directoryService) : DefaultParser(directoryService)
{
public override ParserInfo Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo comicInfo = null)
public override ParserInfo Parse(string filePath, string rootPath, string libraryRoot, LibraryType type,
ComicInfo? comicInfo = null, IEnumerable<string>? extraRegex = null)
{
var fileName = directoryService.FileSystem.Path.GetFileNameWithoutExtension(filePath);
var ret = new ParserInfo