mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-06-23 15:30:34 -04:00
* Cleanup some messaging in the scan loop to be more context bearing * Added Response Caching to Series Detail for 1 min, due to the heavy nature of the call. * Refactored code to make it so that processing of series runs sync correctly. Added a log to inform the user of corrupted volume from buggy code in v0.5.6. * Moved folder watching out of experimental * Fixed an issue where empty folders could break the scan loop * Another fix for when dates aren't valid, the scanner wouldn't get the proper min and would throw an exception (develop) * Implemented the ability to edit release year from the UI for a series. * Added a unit test for some new logic * Code smells * Rewrote the handler for suspending watching to be more resilient and ensure no two threads have a race condition. * More error handling for when a ScanFolder is invoked but multiple series belong to that folder, log it to the user and default to a library scan. * ScanSeries now will check for kavitaignores higher than it's own folder and respect library level. * Fixed an issue where image series with a folder name containing the word "folder" could get ignored as it thought the image was a cover image. When a series folder is moved or deleted, skip parent ignore finding. * Removed some old files, added in scanFolder a check if the series found for a folder is in a book library and if so to always do a library scan (as books are often nested into one folder with multiple series). Added some unit tests * Refactored some scan loop logic into ComicInfo, wrote tests and updated some documentation to make the fields more clear. * Added a test for GetLastWriteTime based on recent bug * Cleaned up some redundant code * Fixed a bad merge * Code smells * Removed a package that's no longer used. * Ensure we check against ScanQueue on ScanFolder enqueuing * Documentation and more bullet proofing to ensure Hangfire checks work more as expected
147 lines
6.0 KiB
C#
147 lines
6.0 KiB
C#
using System;
|
|
using System.Linq;
|
|
using API.Entities.Enums;
|
|
using Kavita.Common.Extensions;
|
|
|
|
namespace API.Data.Metadata;
|
|
|
|
/// <summary>
|
|
/// A representation of a ComicInfo.xml file
|
|
/// </summary>
|
|
/// <remarks>See reference of the loose spec here: https://anansi-project.github.io/docs/comicinfo/documentation</remarks>
|
|
public class ComicInfo
|
|
{
|
|
public string Summary { get; set; } = string.Empty;
|
|
public string Title { get; set; } = string.Empty;
|
|
public string Series { get; set; } = string.Empty;
|
|
/// <summary>
|
|
/// Localized Series name. Not standard.
|
|
/// </summary>
|
|
public string LocalizedSeries { get; set; } = string.Empty;
|
|
public string SeriesSort { get; set; } = string.Empty;
|
|
public string Number { get; set; } = string.Empty;
|
|
/// <summary>
|
|
/// The total number of items in the series.
|
|
/// </summary>
|
|
[System.ComponentModel.DefaultValueAttribute(0)]
|
|
public int Count { get; set; } = 0;
|
|
public string Volume { get; set; } = string.Empty;
|
|
public string Notes { get; set; } = string.Empty;
|
|
public string Genre { get; set; } = string.Empty;
|
|
public int PageCount { get; set; }
|
|
// ReSharper disable once InconsistentNaming
|
|
/// <summary>
|
|
/// IETF BCP 47 Code to represent the language of the content
|
|
/// </summary>
|
|
public string LanguageISO { get; set; } = string.Empty;
|
|
/// <summary>
|
|
/// This is the link to where the data was scraped from
|
|
/// </summary>
|
|
public string Web { get; set; } = string.Empty;
|
|
[System.ComponentModel.DefaultValueAttribute(0)]
|
|
public int Day { get; set; } = 0;
|
|
[System.ComponentModel.DefaultValueAttribute(0)]
|
|
public int Month { get; set; } = 0;
|
|
[System.ComponentModel.DefaultValueAttribute(0)]
|
|
public int Year { get; set; } = 0;
|
|
|
|
|
|
/// <summary>
|
|
/// Rating based on the content. Think PG-13, R for movies. See <see cref="AgeRating"/> for valid types
|
|
/// </summary>
|
|
public string AgeRating { get; set; } = string.Empty;
|
|
/// <summary>
|
|
/// User's rating of the content
|
|
/// </summary>
|
|
public float UserRating { get; set; }
|
|
|
|
public string StoryArc { get; set; } = string.Empty;
|
|
public string SeriesGroup { get; set; } = string.Empty;
|
|
public string AlternateNumber { get; set; } = string.Empty;
|
|
[System.ComponentModel.DefaultValueAttribute(0)]
|
|
public int AlternateCount { get; set; } = 0;
|
|
public string AlternateSeries { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// This is Epub only: calibre:title_sort
|
|
/// Represents the sort order for the title
|
|
/// </summary>
|
|
public string TitleSort { get; set; } = string.Empty;
|
|
/// <summary>
|
|
/// This comes from ComicInfo and is free form text. We use this to validate against a set of tags and mark a file as
|
|
/// special.
|
|
/// </summary>
|
|
public string Format { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// The translator, can be comma separated. This is part of ComicInfo.xml draft v2.1
|
|
/// </summary>
|
|
/// See https://github.com/anansi-project/comicinfo/issues/2 for information about this tag
|
|
public string Translator { get; set; } = string.Empty;
|
|
/// <summary>
|
|
/// Misc tags. This is part of ComicInfo.xml draft v2.1
|
|
/// </summary>
|
|
/// See https://github.com/anansi-project/comicinfo/issues/1 for information about this tag
|
|
public string Tags { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// This is the Author. For Books, we map creator tag in OPF to this field. Comma separated if multiple.
|
|
/// </summary>
|
|
public string Writer { get; set; } = string.Empty;
|
|
public string Penciller { get; set; } = string.Empty;
|
|
public string Inker { get; set; } = string.Empty;
|
|
public string Colorist { get; set; } = string.Empty;
|
|
public string Letterer { get; set; } = string.Empty;
|
|
public string CoverArtist { get; set; } = string.Empty;
|
|
public string Editor { get; set; } = string.Empty;
|
|
public string Publisher { get; set; } = string.Empty;
|
|
public string Characters { get; set; } = string.Empty;
|
|
|
|
public static AgeRating ConvertAgeRatingToEnum(string value)
|
|
{
|
|
if (string.IsNullOrEmpty(value)) return Entities.Enums.AgeRating.Unknown;
|
|
return Enum.GetValues<AgeRating>()
|
|
.SingleOrDefault(t => t.ToDescription().ToUpperInvariant().Equals(value.ToUpperInvariant()), Entities.Enums.AgeRating.Unknown);
|
|
}
|
|
|
|
public static void CleanComicInfo(ComicInfo info)
|
|
{
|
|
if (info == null) return;
|
|
|
|
info.Series = info.Series.Trim();
|
|
info.SeriesSort = info.SeriesSort.Trim();
|
|
info.LocalizedSeries = info.LocalizedSeries.Trim();
|
|
|
|
info.Writer = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Writer);
|
|
info.Colorist = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Colorist);
|
|
info.Editor = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Editor);
|
|
info.Inker = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Inker);
|
|
info.Letterer = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Letterer);
|
|
info.Penciller = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Penciller);
|
|
info.Publisher = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Publisher);
|
|
info.Characters = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Characters);
|
|
info.Translator = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.Translator);
|
|
info.CoverArtist = Services.Tasks.Scanner.Parser.Parser.CleanAuthor(info.CoverArtist);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Uses both Volume and Number to make an educated guess as to what count refers to and it's highest number.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public int CalculatedCount()
|
|
{
|
|
if (!string.IsNullOrEmpty(Number) && float.Parse(Number) > 0)
|
|
{
|
|
return (int) Math.Floor(float.Parse(Number));
|
|
}
|
|
if (!string.IsNullOrEmpty(Volume) && float.Parse(Volume) > 0)
|
|
{
|
|
return Math.Max(Count, (int) Math.Floor(float.Parse(Volume)));
|
|
}
|
|
|
|
return Count;
|
|
}
|
|
|
|
|
|
}
|