Merged develop in

This commit is contained in:
Joseph Milazzo 2024-02-10 09:53:14 -06:00
commit a443be7523
322 changed files with 31244 additions and 6350 deletions

View file

@ -31,7 +31,7 @@ public class AppUser : IdentityUser<int>, IHasConcurrencyToken
/// <summary>
/// A list of Series the user want's to read
/// </summary>
public ICollection<Series> WantToRead { get; set; } = null!;
public ICollection<AppUserWantToRead> WantToRead { get; set; } = null!;
/// <summary>
/// A list of Devices which allows the user to send files to
/// </summary>

View file

@ -0,0 +1,20 @@
namespace API.Entities;
public class AppUserWantToRead
{
public int Id { get; set; }
public required int SeriesId { get; set; }
public virtual Series Series { get; set; }
// Relationships
/// <summary>
/// Navigational Property for EF. Links to a unique AppUser
/// </summary>
public AppUser AppUser { get; set; } = null!;
/// <summary>
/// User this table of content belongs to
/// </summary>
public int AppUserId { get; set; }
}

View file

@ -25,8 +25,13 @@ public enum LibraryType
[Description("Image")]
Image = 3,
/// <summary>
/// Allows Books to Scrobble with AniList for Kavita+
/// </summary>
[Description("Light Novel")]
LightNovel = 4,
/// <summary>
/// Uses Magazine regex and is restricted to PDF and Archive by default
/// </summary>
[Description("Magazine")]
Magazine = 4
Magazine = 5
}

View file

@ -52,6 +52,7 @@ public enum ServerSettingKey
/// Is Authentication needed for non-admin accounts
/// </summary>
/// <remarks>Deprecated. This is no longer used v0.5.1+. Assume Authentication is always in effect</remarks>
[Obsolete("Not supported as of v0.5.1")]
[Description("EnableAuthentication")]
EnableAuthentication = 8,
/// <summary>
@ -79,6 +80,7 @@ public enum ServerSettingKey
/// If SMTP is enabled on the server
/// </summary>
[Description("CustomEmailService")]
[Obsolete("Use Email settings instead")]
EmailServiceUrl = 13,
/// <summary>
/// If Kavita should save bookmarks as WebP images
@ -147,6 +149,42 @@ public enum ServerSettingKey
/// The size of the cover image thumbnail. Defaults to <see cref="CoverImageSize"/>.Default
/// </summary>
[Description("CoverImageSize")]
CoverImageSize = 27
CoverImageSize = 27,
#region EmailSettings
/// <summary>
/// The address of the emailer host
/// </summary>
[Description("EmailSenderAddress")]
EmailSenderAddress = 28,
/// <summary>
/// What the email name should be
/// </summary>
[Description("EmailSenderDisplayName")]
EmailSenderDisplayName = 29,
[Description("EmailAuthUserName")]
EmailAuthUserName = 30,
[Description("EmailAuthPassword")]
EmailAuthPassword = 31,
[Description("EmailHost")]
EmailHost = 32,
[Description("EmailPort")]
EmailPort = 33,
[Description("EmailEnableSsl")]
EmailEnableSsl = 34,
/// <summary>
/// Number of bytes that the sender allows to be sent through
/// </summary>
[Description("EmailSizeLimit")]
EmailSizeLimit = 35,
/// <summary>
/// Should Kavita use config/templates for Email templates or the default ones
/// </summary>
[Description("EmailCustomizedTemplates")]
EmailCustomizedTemplates = 36,
#endregion
/// <summary>
/// When the cleanup task should run - Critical to keeping Kavita working
/// </summary>
[Description("TaskCleanup")]
TaskCleanup = 37
}

View file

@ -0,0 +1,14 @@
using System;
namespace API.Entities;
/// <summary>
/// This will track manual migrations so that I can use simple selects to check if a Manual Migration is needed
/// </summary>
public class ManualMigrationHistory
{
public int Id { get; set; }
public string ProductVersion { get; set; }
public required string Name { get; set; }
public DateTime RanAt { get; set; }
}

View file

@ -0,0 +1,17 @@
using System.Collections.Generic;
using API.Services.Plus;
namespace API.Entities.Metadata;
public class ExternalRating
{
public int Id { get; set; }
public int AverageScore { get; set; }
public int FavoriteCount { get; set; }
public ScrobbleProvider Provider { get; set; }
public string? ProviderUrl { get; set; }
public int SeriesId { get; set; }
public ICollection<ExternalSeriesMetadata> ExternalSeriesMetadatas { get; set; } = null!;
}

View file

@ -0,0 +1,29 @@
using System.Collections.Generic;
using API.Services.Plus;
using Microsoft.EntityFrameworkCore;
namespace API.Entities.Metadata;
[Index(nameof(SeriesId), IsUnique = false)]
public class ExternalRecommendation
{
public int Id { get; set; }
public required string Name { get; set; }
public required string CoverUrl { get; set; }
public required string Url { get; set; }
public string? Summary { get; set; }
public int? AniListId { get; set; }
public long? MalId { get; set; }
public ScrobbleProvider Provider { get; set; } = ScrobbleProvider.AniList;
/// <summary>
/// When null, represents an external series. When set, it is a Series
/// </summary>
public int? SeriesId { get; set; }
//public virtual Series? Series { get; set; }
// Relationships
public ICollection<ExternalSeriesMetadata> ExternalSeriesMetadatas { get; set; } = null!;
}

View file

@ -0,0 +1,43 @@
using System.Collections.Generic;
using API.Services.Plus;
namespace API.Entities.Metadata;
/// <summary>
/// Represents an Externally supplied Review for a given Series
/// </summary>
public class ExternalReview
{
public int Id { get; set; }
public string Tagline { get; set; }
public required string Body { get; set; }
/// <summary>
/// Pure text version of the body
/// </summary>
public required string BodyJustText { get; set; }
/// <summary>
/// Raw from the provider. Usually Markdown
/// </summary>
public string RawBody { get; set; }
public required ScrobbleProvider Provider { get; set; }
public string SiteUrl { get; set; }
/// <summary>
/// Reviewer's username
/// </summary>
public string Username { get; set; }
/// <summary>
/// An Optional Rating coming from the Review
/// </summary>
public int Rating { get; set; } = 0;
/// <summary>
/// The media's overall Score
/// </summary>
public int Score { get; set; }
public int TotalVotes { get; set; }
public int SeriesId { get; set; }
// Relationships
public ICollection<ExternalSeriesMetadata> ExternalSeriesMetadatas { get; set; } = null!;
}

View file

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
namespace API.Entities.Metadata;
/// <summary>
/// External Metadata from Kavita+ for a Series
/// </summary>
public class ExternalSeriesMetadata
{
public int Id { get; set; }
/// <summary>
/// External Reviews for the Series. Managed by Kavita for Kavita+ users
/// </summary>
public ICollection<ExternalReview> ExternalReviews { get; set; } = null!;
public ICollection<ExternalRating> ExternalRatings { get; set; } = null!;
/// <summary>
/// External recommendations will include all recommendations and will have a seriesId if it's on this Kavita instance.
/// </summary>
/// <remarks>Cleanup Service will perform matching to tie new series with recommendations</remarks>
public ICollection<ExternalRecommendation> ExternalRecommendations { get; set; } = null!;
/// <summary>
/// Average External Rating. -1 means not set
/// </summary>
public int AverageExternalRating { get; set; } = 0;
public int AniListId { get; set; }
public long MalId { get; set; }
public string GoogleBooksId { get; set; }
/// <summary>
/// Data is valid until this time
/// </summary>
public DateTime ValidUntilUtc { get; set; }
public Series Series { get; set; } = null!;
public int SeriesId { get; set; }
}

View file

@ -0,0 +1,14 @@
using System;
namespace API.Entities.Metadata;
/// <summary>
/// A blacklist of Series for Kavita+
/// </summary>
public class SeriesBlacklist
{
public int Id { get; set; }
public int SeriesId { get; set; }
public Series Series { get; set; }
public DateTime LastChecked { get; set; } = DateTime.UtcNow;
}

View file

@ -36,12 +36,20 @@ public class ScrobbleEvent : IEntityDate
/// <summary>
/// Depends on the ScrobbleEvent if filled in
/// </summary>
public int? VolumeNumber { get; set; }
public float? VolumeNumber { get; set; }
/// <summary>
/// Has this event been processed and pushed to Provider
/// </summary>
public bool IsProcessed { get; set; }
/// <summary>
/// Was there an error processing this event
/// </summary>
public bool IsErrored { get; set; }
/// <summary>
/// The error details
/// </summary>
public string? ErrorDetails { get; set; }
/// <summary>
/// The date this was processed
/// </summary>
public DateTime? ProcessDateUtc { get; set; }

View file

@ -15,4 +15,8 @@ public class ScrobbleEventFilter
/// A query to search against
/// </summary>
public string Query { get; set; }
/// <summary>
/// Include reviews in the result - Note: Review Scrobbling is disabled
/// </summary>
public bool IncludeReviews { get; set; } = false;
}

View file

@ -96,6 +96,7 @@ public class Series : IEntityDate, IHasReadTimeEstimate
public int AvgHoursToRead { get; set; }
public SeriesMetadata Metadata { get; set; } = null!;
public ExternalSeriesMetadata ExternalSeriesMetadata { get; set; } = null!;
public ICollection<AppUserRating> Ratings { get; set; } = null!;
public ICollection<AppUserProgress> Progress { get; set; } = null!;
@ -113,6 +114,7 @@ public class Series : IEntityDate, IHasReadTimeEstimate
public Library Library { get; set; } = null!;
public int LibraryId { get; set; }
public void UpdateLastFolderScanned()
{
LastFolderScanned = DateTime.Now;

View file

@ -8,14 +8,24 @@ public class Volume : IEntityDate, IHasReadTimeEstimate
{
public int Id { get; set; }
/// <summary>
/// A String representation of the volume number. Allows for floats.
/// A String representation of the volume number. Allows for floats. Can also include a range (1-2).
/// </summary>
/// <remarks>For Books with Series_index, this will map to the Series Index.</remarks>
public required string Name { get; set; }
/// <summary>
/// The minimum number in the Name field in Int form
/// </summary>
public required int Number { get; set; }
/// <remarks>Removed in v0.7.13.8, this was an int and we need the ability to have 0.5 volumes render on the UI</remarks>
[Obsolete("Use MinNumber and MaxNumber instead")]
public int Number { get; set; }
/// <summary>
/// The minimum number in the Name field
/// </summary>
public required float MinNumber { get; set; }
/// <summary>
/// The maximum number in the Name field (same as Minimum if Name isn't a range)
/// </summary>
public required float MaxNumber { get; set; }
public IList<Chapter> Chapters { get; set; } = null!;
public DateTime Created { get; set; }
public DateTime LastModified { get; set; }