Logging Enhancements (#1521)
* Recreated Kavita Logging with Serilog instead of Default. This needs to be move out of the appsettings now, to allow auto updater to patch. * Refactored the code to be completely configured via Code rather than appsettings.json. This is a required step for Auto Updating. * Added in the ability to send logs directly to the UI only for users on the log route. Stopping implementation as Alerts page will handle the rest of the implementation. * Fixed up the backup service to not rely on Config from appsettings.json * Tweaked the Logging levels available * Moved everything over to File-scoped namespaces * Moved everything over to File-scoped namespaces * Code cleanup, removed an old migration and changed so debug logging doesn't print sensitive db data * Removed dead code
This commit is contained in:
parent
9f715cc35f
commit
d1a14f7e68
212 changed files with 16599 additions and 16834 deletions
|
@ -1,10 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
public class AppRole : IdentityRole<int>
|
||||
{
|
||||
public class AppRole : IdentityRole<int>
|
||||
{
|
||||
public ICollection<AppUserRole> UserRoles { get; set; }
|
||||
}
|
||||
}
|
||||
public ICollection<AppUserRole> UserRoles { get; set; }
|
||||
}
|
||||
|
|
|
@ -5,45 +5,44 @@ using API.Entities.Interfaces;
|
|||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
public class AppUser : IdentityUser<int>, IHasConcurrencyToken
|
||||
{
|
||||
public class AppUser : IdentityUser<int>, IHasConcurrencyToken
|
||||
public DateTime Created { get; set; } = DateTime.Now;
|
||||
public DateTime LastActive { get; set; }
|
||||
public ICollection<Library> Libraries { get; set; }
|
||||
public ICollection<AppUserRole> UserRoles { get; set; }
|
||||
public ICollection<AppUserProgress> Progresses { get; set; }
|
||||
public ICollection<AppUserRating> Ratings { get; set; }
|
||||
public AppUserPreferences UserPreferences { get; set; }
|
||||
public ICollection<AppUserBookmark> Bookmarks { get; set; }
|
||||
/// <summary>
|
||||
/// Reading lists associated with this user
|
||||
/// </summary>
|
||||
public ICollection<ReadingList> ReadingLists { get; set; }
|
||||
/// <summary>
|
||||
/// A list of Series the user want's to read
|
||||
/// </summary>
|
||||
public ICollection<Series> WantToRead { get; set; }
|
||||
/// <summary>
|
||||
/// An API Key to interact with external services, like OPDS
|
||||
/// </summary>
|
||||
public string ApiKey { get; set; }
|
||||
/// <summary>
|
||||
/// The confirmation token for the user (invite). This will be set to null after the user confirms.
|
||||
/// </summary>
|
||||
public string ConfirmationToken { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
[ConcurrencyCheck]
|
||||
public uint RowVersion { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnSavingChanges()
|
||||
{
|
||||
public DateTime Created { get; set; } = DateTime.Now;
|
||||
public DateTime LastActive { get; set; }
|
||||
public ICollection<Library> Libraries { get; set; }
|
||||
public ICollection<AppUserRole> UserRoles { get; set; }
|
||||
public ICollection<AppUserProgress> Progresses { get; set; }
|
||||
public ICollection<AppUserRating> Ratings { get; set; }
|
||||
public AppUserPreferences UserPreferences { get; set; }
|
||||
public ICollection<AppUserBookmark> Bookmarks { get; set; }
|
||||
/// <summary>
|
||||
/// Reading lists associated with this user
|
||||
/// </summary>
|
||||
public ICollection<ReadingList> ReadingLists { get; set; }
|
||||
/// <summary>
|
||||
/// A list of Series the user want's to read
|
||||
/// </summary>
|
||||
public ICollection<Series> WantToRead { get; set; }
|
||||
/// <summary>
|
||||
/// An API Key to interact with external services, like OPDS
|
||||
/// </summary>
|
||||
public string ApiKey { get; set; }
|
||||
/// <summary>
|
||||
/// The confirmation token for the user (invite). This will be set to null after the user confirms.
|
||||
/// </summary>
|
||||
public string ConfirmationToken { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
[ConcurrencyCheck]
|
||||
public uint RowVersion { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnSavingChanges()
|
||||
{
|
||||
RowVersion++;
|
||||
}
|
||||
|
||||
RowVersion++;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,30 +2,29 @@
|
|||
using System.Text.Json.Serialization;
|
||||
using API.Entities.Interfaces;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a saved page in a Chapter entity for a given user.
|
||||
/// </summary>
|
||||
public class AppUserBookmark : IEntityDate
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int Page { get; set; }
|
||||
public int VolumeId { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
public int ChapterId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents a saved page in a Chapter entity for a given user.
|
||||
/// Filename in the Bookmark Directory
|
||||
/// </summary>
|
||||
public class AppUserBookmark : IEntityDate
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int Page { get; set; }
|
||||
public int VolumeId { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
public int ChapterId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Filename in the Bookmark Directory
|
||||
/// </summary>
|
||||
public string FileName { get; set; } = string.Empty;
|
||||
public string FileName { get; set; } = string.Empty;
|
||||
|
||||
|
||||
// Relationships
|
||||
[JsonIgnore]
|
||||
public AppUser AppUser { get; set; }
|
||||
public int AppUserId { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
}
|
||||
// Relationships
|
||||
[JsonIgnore]
|
||||
public AppUser AppUser { get; set; }
|
||||
public int AppUserId { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,109 +1,108 @@
|
|||
using API.Entities.Enums;
|
||||
using API.Entities.Enums.UserPreferences;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
public class AppUserPreferences
|
||||
{
|
||||
public class AppUserPreferences
|
||||
{
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// Manga Reader Option: What direction should the next/prev page buttons go
|
||||
/// </summary>
|
||||
public ReadingDirection ReadingDirection { get; set; } = ReadingDirection.LeftToRight;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: How should the image be scaled to screen
|
||||
/// </summary>
|
||||
public ScalingOption ScalingOption { get; set; } = ScalingOption.Automatic;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: Which side of a split image should we show first
|
||||
/// </summary>
|
||||
public PageSplitOption PageSplitOption { get; set; } = PageSplitOption.FitSplit;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: How the manga reader should perform paging or reading of the file
|
||||
/// <example>
|
||||
/// Webtoon uses scrolling to page, MANGA_LR uses paging by clicking left/right side of reader, MANGA_UD uses paging
|
||||
/// by clicking top/bottom sides of reader.
|
||||
/// </example>
|
||||
/// </summary>
|
||||
public ReaderMode ReaderMode { get; set; }
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// Manga Reader Option: What direction should the next/prev page buttons go
|
||||
/// </summary>
|
||||
public ReadingDirection ReadingDirection { get; set; } = ReadingDirection.LeftToRight;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: How should the image be scaled to screen
|
||||
/// </summary>
|
||||
public ScalingOption ScalingOption { get; set; } = ScalingOption.Automatic;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: Which side of a split image should we show first
|
||||
/// </summary>
|
||||
public PageSplitOption PageSplitOption { get; set; } = PageSplitOption.FitSplit;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: How the manga reader should perform paging or reading of the file
|
||||
/// <example>
|
||||
/// Webtoon uses scrolling to page, MANGA_LR uses paging by clicking left/right side of reader, MANGA_UD uses paging
|
||||
/// by clicking top/bottom sides of reader.
|
||||
/// </example>
|
||||
/// </summary>
|
||||
public ReaderMode ReaderMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Manga Reader Option: Allow the menu to close after 6 seconds without interaction
|
||||
/// </summary>
|
||||
public bool AutoCloseMenu { get; set; } = true;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: Show screen hints to the user on some actions, ie) pagination direction change
|
||||
/// </summary>
|
||||
public bool ShowScreenHints { get; set; } = true;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: How many pages to display in the reader at once
|
||||
/// </summary>
|
||||
public LayoutMode LayoutMode { get; set; } = LayoutMode.Single;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: Background color of the reader
|
||||
/// </summary>
|
||||
public string BackgroundColor { get; set; } = "#000000";
|
||||
/// <summary>
|
||||
/// Book Reader Option: Override extra Margin
|
||||
/// </summary>
|
||||
public int BookReaderMargin { get; set; } = 15;
|
||||
/// <summary>
|
||||
/// Book Reader Option: Override line-height
|
||||
/// </summary>
|
||||
public int BookReaderLineSpacing { get; set; } = 100;
|
||||
/// <summary>
|
||||
/// Book Reader Option: Override font size
|
||||
/// </summary>
|
||||
public int BookReaderFontSize { get; set; } = 100;
|
||||
/// <summary>
|
||||
/// Book Reader Option: Maps to the default Kavita font-family (inherit) or an override
|
||||
/// </summary>
|
||||
public string BookReaderFontFamily { get; set; } = "default";
|
||||
/// <summary>
|
||||
/// Book Reader Option: Allows tapping on side of screens to paginate
|
||||
/// </summary>
|
||||
public bool BookReaderTapToPaginate { get; set; } = false;
|
||||
/// <summary>
|
||||
/// Book Reader Option: What direction should the next/prev page buttons go
|
||||
/// </summary>
|
||||
public ReadingDirection BookReaderReadingDirection { get; set; } = ReadingDirection.LeftToRight;
|
||||
/// <summary>
|
||||
/// UI Site Global Setting: The UI theme the user should use.
|
||||
/// </summary>
|
||||
/// <remarks>Should default to Dark</remarks>
|
||||
public SiteTheme Theme { get; set; }
|
||||
/// <summary>
|
||||
/// Book Reader Option: The color theme to decorate the book contents
|
||||
/// </summary>
|
||||
/// <remarks>Should default to Dark</remarks>
|
||||
public string BookThemeName { get; set; } = "Dark";
|
||||
/// <summary>
|
||||
/// Book Reader Option: The way a page from a book is rendered. Default is as book dictates, 1 column is fit to height,
|
||||
/// 2 column is fit to height, 2 columns
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to Default</remarks>
|
||||
public BookPageLayoutMode BookReaderLayoutMode { get; set; } = BookPageLayoutMode.Default;
|
||||
/// <summary>
|
||||
/// Book Reader Option: A flag that hides the menu-ing system behind a click on the screen. This should be used with tap to paginate, but the app doesn't enforce this.
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to false</remarks>
|
||||
public bool BookReaderImmersiveMode { get; set; } = false;
|
||||
/// <summary>
|
||||
/// Global Site Option: If the UI should layout items as Cards or List items
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to Cards</remarks>
|
||||
public PageLayoutMode GlobalPageLayoutMode { get; set; } = PageLayoutMode.Cards;
|
||||
/// <summary>
|
||||
/// UI Site Global Setting: If unread summaries should be blurred until expanded or unless user has read it already
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to false</remarks>
|
||||
public bool BlurUnreadSummaries { get; set; } = false;
|
||||
/// <summary>
|
||||
/// UI Site Global Setting: Should Kavita prompt user to confirm downloads that are greater than 100 MB.
|
||||
/// </summary>
|
||||
public bool PromptForDownloadSize { get; set; } = true;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: Allow the menu to close after 6 seconds without interaction
|
||||
/// </summary>
|
||||
public bool AutoCloseMenu { get; set; } = true;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: Show screen hints to the user on some actions, ie) pagination direction change
|
||||
/// </summary>
|
||||
public bool ShowScreenHints { get; set; } = true;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: How many pages to display in the reader at once
|
||||
/// </summary>
|
||||
public LayoutMode LayoutMode { get; set; } = LayoutMode.Single;
|
||||
/// <summary>
|
||||
/// Manga Reader Option: Background color of the reader
|
||||
/// </summary>
|
||||
public string BackgroundColor { get; set; } = "#000000";
|
||||
/// <summary>
|
||||
/// Book Reader Option: Override extra Margin
|
||||
/// </summary>
|
||||
public int BookReaderMargin { get; set; } = 15;
|
||||
/// <summary>
|
||||
/// Book Reader Option: Override line-height
|
||||
/// </summary>
|
||||
public int BookReaderLineSpacing { get; set; } = 100;
|
||||
/// <summary>
|
||||
/// Book Reader Option: Override font size
|
||||
/// </summary>
|
||||
public int BookReaderFontSize { get; set; } = 100;
|
||||
/// <summary>
|
||||
/// Book Reader Option: Maps to the default Kavita font-family (inherit) or an override
|
||||
/// </summary>
|
||||
public string BookReaderFontFamily { get; set; } = "default";
|
||||
/// <summary>
|
||||
/// Book Reader Option: Allows tapping on side of screens to paginate
|
||||
/// </summary>
|
||||
public bool BookReaderTapToPaginate { get; set; } = false;
|
||||
/// <summary>
|
||||
/// Book Reader Option: What direction should the next/prev page buttons go
|
||||
/// </summary>
|
||||
public ReadingDirection BookReaderReadingDirection { get; set; } = ReadingDirection.LeftToRight;
|
||||
/// <summary>
|
||||
/// UI Site Global Setting: The UI theme the user should use.
|
||||
/// </summary>
|
||||
/// <remarks>Should default to Dark</remarks>
|
||||
public SiteTheme Theme { get; set; }
|
||||
/// <summary>
|
||||
/// Book Reader Option: The color theme to decorate the book contents
|
||||
/// </summary>
|
||||
/// <remarks>Should default to Dark</remarks>
|
||||
public string BookThemeName { get; set; } = "Dark";
|
||||
/// <summary>
|
||||
/// Book Reader Option: The way a page from a book is rendered. Default is as book dictates, 1 column is fit to height,
|
||||
/// 2 column is fit to height, 2 columns
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to Default</remarks>
|
||||
public BookPageLayoutMode BookReaderLayoutMode { get; set; } = BookPageLayoutMode.Default;
|
||||
/// <summary>
|
||||
/// Book Reader Option: A flag that hides the menu-ing system behind a click on the screen. This should be used with tap to paginate, but the app doesn't enforce this.
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to false</remarks>
|
||||
public bool BookReaderImmersiveMode { get; set; } = false;
|
||||
/// <summary>
|
||||
/// Global Site Option: If the UI should layout items as Cards or List items
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to Cards</remarks>
|
||||
public PageLayoutMode GlobalPageLayoutMode { get; set; } = PageLayoutMode.Cards;
|
||||
/// <summary>
|
||||
/// UI Site Global Setting: If unread summaries should be blurred until expanded or unless user has read it already
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to false</remarks>
|
||||
public bool BlurUnreadSummaries { get; set; } = false;
|
||||
/// <summary>
|
||||
/// UI Site Global Setting: Should Kavita prompt user to confirm downloads that are greater than 100 MB.
|
||||
/// </summary>
|
||||
public bool PromptForDownloadSize { get; set; } = true;
|
||||
|
||||
public AppUser AppUser { get; set; }
|
||||
public int AppUserId { get; set; }
|
||||
}
|
||||
public AppUser AppUser { get; set; }
|
||||
public int AppUserId { get; set; }
|
||||
}
|
||||
|
|
|
@ -2,56 +2,55 @@
|
|||
using System;
|
||||
using API.Entities.Interfaces;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the progress a single user has on a given Chapter.
|
||||
/// </summary>
|
||||
//[Index(nameof(SeriesId), nameof(VolumeId), nameof(ChapterId), nameof(AppUserId), IsUnique = true)]
|
||||
public class AppUserProgress : IEntityDate
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the progress a single user has on a given Chapter.
|
||||
/// Id of Entity
|
||||
/// </summary>
|
||||
//[Index(nameof(SeriesId), nameof(VolumeId), nameof(ChapterId), nameof(AppUserId), IsUnique = true)]
|
||||
public class AppUserProgress : IEntityDate
|
||||
{
|
||||
/// <summary>
|
||||
/// Id of Entity
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// Pages Read for given Chapter
|
||||
/// </summary>
|
||||
public int PagesRead { get; set; }
|
||||
/// <summary>
|
||||
/// Volume belonging to Chapter
|
||||
/// </summary>
|
||||
public int VolumeId { get; set; }
|
||||
/// <summary>
|
||||
/// Series belonging to Chapter
|
||||
/// </summary>
|
||||
public int SeriesId { get; set; }
|
||||
/// <summary>
|
||||
/// Chapter
|
||||
/// </summary>
|
||||
public int ChapterId { get; set; }
|
||||
/// <summary>
|
||||
/// For Book Reader, represents the nearest passed anchor on the screen that can be used to resume scroll point
|
||||
/// on next load
|
||||
/// </summary>
|
||||
public string BookScrollId { get; set; }
|
||||
/// <summary>
|
||||
/// When this was first created
|
||||
/// </summary>
|
||||
public DateTime Created { get; set; }
|
||||
/// <summary>
|
||||
/// Last date this was updated
|
||||
/// </summary>
|
||||
public DateTime LastModified { get; set; }
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// Pages Read for given Chapter
|
||||
/// </summary>
|
||||
public int PagesRead { get; set; }
|
||||
/// <summary>
|
||||
/// Volume belonging to Chapter
|
||||
/// </summary>
|
||||
public int VolumeId { get; set; }
|
||||
/// <summary>
|
||||
/// Series belonging to Chapter
|
||||
/// </summary>
|
||||
public int SeriesId { get; set; }
|
||||
/// <summary>
|
||||
/// Chapter
|
||||
/// </summary>
|
||||
public int ChapterId { get; set; }
|
||||
/// <summary>
|
||||
/// For Book Reader, represents the nearest passed anchor on the screen that can be used to resume scroll point
|
||||
/// on next load
|
||||
/// </summary>
|
||||
public string BookScrollId { get; set; }
|
||||
/// <summary>
|
||||
/// When this was first created
|
||||
/// </summary>
|
||||
public DateTime Created { get; set; }
|
||||
/// <summary>
|
||||
/// Last date this was updated
|
||||
/// </summary>
|
||||
public DateTime LastModified { get; set; }
|
||||
|
||||
// Relationships
|
||||
/// <summary>
|
||||
/// Navigational Property for EF. Links to a unique AppUser
|
||||
/// </summary>
|
||||
public AppUser AppUser { get; set; }
|
||||
/// <summary>
|
||||
/// User this progress belongs to
|
||||
/// </summary>
|
||||
public int AppUserId { get; set; }
|
||||
}
|
||||
// Relationships
|
||||
/// <summary>
|
||||
/// Navigational Property for EF. Links to a unique AppUser
|
||||
/// </summary>
|
||||
public AppUser AppUser { get; set; }
|
||||
/// <summary>
|
||||
/// User this progress belongs to
|
||||
/// </summary>
|
||||
public int AppUserId { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
public class AppUserRating
|
||||
{
|
||||
public class AppUserRating
|
||||
{
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// A number between 0-5 that represents how good a series is.
|
||||
/// </summary>
|
||||
public int Rating { get; set; }
|
||||
/// <summary>
|
||||
/// A short summary the user can write when giving their review.
|
||||
/// </summary>
|
||||
public string Review { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
|
||||
|
||||
// Relationships
|
||||
public int AppUserId { get; set; }
|
||||
public AppUser AppUser { get; set; }
|
||||
}
|
||||
}
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// A number between 0-5 that represents how good a series is.
|
||||
/// </summary>
|
||||
public int Rating { get; set; }
|
||||
/// <summary>
|
||||
/// A short summary the user can write when giving their review.
|
||||
/// </summary>
|
||||
public string Review { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
|
||||
|
||||
// Relationships
|
||||
public int AppUserId { get; set; }
|
||||
public AppUser AppUser { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
public class AppUserRole : IdentityUserRole<int>
|
||||
{
|
||||
public class AppUserRole : IdentityUserRole<int>
|
||||
{
|
||||
public AppUser User { get; set; }
|
||||
public AppRole Role { get; set; }
|
||||
}
|
||||
}
|
||||
public AppUser User { get; set; }
|
||||
public AppRole Role { get; set; }
|
||||
}
|
||||
|
|
|
@ -5,116 +5,115 @@ using API.Entities.Interfaces;
|
|||
using API.Parser;
|
||||
using API.Services;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
public class Chapter : IEntityDate, IHasReadTimeEstimate
|
||||
{
|
||||
public class Chapter : IEntityDate, IHasReadTimeEstimate
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// Range of numbers. Chapter 2-4 -> "2-4". Chapter 2 -> "2".
|
||||
/// </summary>
|
||||
public string Range { get; set; }
|
||||
/// <summary>
|
||||
/// Smallest number of the Range. Can be a partial like Chapter 4.5
|
||||
/// </summary>
|
||||
public string Number { get; set; }
|
||||
/// <summary>
|
||||
/// The files that represent this Chapter
|
||||
/// </summary>
|
||||
public ICollection<MangaFile> Files { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
/// <summary>
|
||||
/// Relative path to the (managed) image file representing the cover image
|
||||
/// </summary>
|
||||
/// <remarks>The file is managed internally to Kavita's APPDIR</remarks>
|
||||
public string CoverImage { get; set; }
|
||||
public bool CoverImageLocked { get; set; }
|
||||
/// <summary>
|
||||
/// Total number of pages in all MangaFiles
|
||||
/// </summary>
|
||||
public int Pages { get; set; }
|
||||
/// <summary>
|
||||
/// If this Chapter contains files that could only be identified as Series or has Special Identifier from filename
|
||||
/// </summary>
|
||||
public bool IsSpecial { get; set; }
|
||||
/// <summary>
|
||||
/// Used for books/specials to display custom title. For non-specials/books, will be set to <see cref="Range"/>
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
/// <summary>
|
||||
/// Age Rating for the issue/chapter
|
||||
/// </summary>
|
||||
public AgeRating AgeRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Chapter title
|
||||
/// </summary>
|
||||
/// <remarks>This should not be confused with Title which is used for special filenames.</remarks>
|
||||
public string TitleName { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Date which chapter was released
|
||||
/// </summary>
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
/// <summary>
|
||||
/// Summary for the Chapter/Issue
|
||||
/// </summary>
|
||||
public string Summary { get; set; }
|
||||
/// <summary>
|
||||
/// Language for the Chapter/Issue
|
||||
/// </summary>
|
||||
public string Language { get; set; }
|
||||
/// <summary>
|
||||
/// Total number of issues in the series
|
||||
/// </summary>
|
||||
public int TotalCount { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// Number in the Total Count
|
||||
/// </summary>
|
||||
public int Count { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Total Word count of all chapters in this chapter.
|
||||
/// </summary>
|
||||
/// <remarks>Word Count is only available from EPUB files</remarks>
|
||||
public long WordCount { get; set; }
|
||||
/// <inheritdoc cref="IHasReadTimeEstimate"/>
|
||||
public int MinHoursToRead { get; set; }
|
||||
/// <inheritdoc cref="IHasReadTimeEstimate"/>
|
||||
public int MaxHoursToRead { get; set; }
|
||||
/// <inheritdoc cref="IHasReadTimeEstimate"/>
|
||||
public int AvgHoursToRead { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// All people attached at a Chapter level. Usually Comics will have different people per issue.
|
||||
/// </summary>
|
||||
public ICollection<Person> People { get; set; } = new List<Person>();
|
||||
/// <summary>
|
||||
/// Genres for the Chapter
|
||||
/// </summary>
|
||||
public ICollection<Genre> Genres { get; set; } = new List<Genre>();
|
||||
public ICollection<Tag> Tags { get; set; } = new List<Tag>();
|
||||
|
||||
|
||||
|
||||
|
||||
// Relationships
|
||||
public Volume Volume { get; set; }
|
||||
public int VolumeId { get; set; }
|
||||
|
||||
public void UpdateFrom(ParserInfo info)
|
||||
{
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// Range of numbers. Chapter 2-4 -> "2-4". Chapter 2 -> "2".
|
||||
/// </summary>
|
||||
public string Range { get; set; }
|
||||
/// <summary>
|
||||
/// Smallest number of the Range. Can be a partial like Chapter 4.5
|
||||
/// </summary>
|
||||
public string Number { get; set; }
|
||||
/// <summary>
|
||||
/// The files that represent this Chapter
|
||||
/// </summary>
|
||||
public ICollection<MangaFile> Files { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
/// <summary>
|
||||
/// Relative path to the (managed) image file representing the cover image
|
||||
/// </summary>
|
||||
/// <remarks>The file is managed internally to Kavita's APPDIR</remarks>
|
||||
public string CoverImage { get; set; }
|
||||
public bool CoverImageLocked { get; set; }
|
||||
/// <summary>
|
||||
/// Total number of pages in all MangaFiles
|
||||
/// </summary>
|
||||
public int Pages { get; set; }
|
||||
/// <summary>
|
||||
/// If this Chapter contains files that could only be identified as Series or has Special Identifier from filename
|
||||
/// </summary>
|
||||
public bool IsSpecial { get; set; }
|
||||
/// <summary>
|
||||
/// Used for books/specials to display custom title. For non-specials/books, will be set to <see cref="Range"/>
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
/// <summary>
|
||||
/// Age Rating for the issue/chapter
|
||||
/// </summary>
|
||||
public AgeRating AgeRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Chapter title
|
||||
/// </summary>
|
||||
/// <remarks>This should not be confused with Title which is used for special filenames.</remarks>
|
||||
public string TitleName { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Date which chapter was released
|
||||
/// </summary>
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
/// <summary>
|
||||
/// Summary for the Chapter/Issue
|
||||
/// </summary>
|
||||
public string Summary { get; set; }
|
||||
/// <summary>
|
||||
/// Language for the Chapter/Issue
|
||||
/// </summary>
|
||||
public string Language { get; set; }
|
||||
/// <summary>
|
||||
/// Total number of issues in the series
|
||||
/// </summary>
|
||||
public int TotalCount { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// Number in the Total Count
|
||||
/// </summary>
|
||||
public int Count { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Total Word count of all chapters in this chapter.
|
||||
/// </summary>
|
||||
/// <remarks>Word Count is only available from EPUB files</remarks>
|
||||
public long WordCount { get; set; }
|
||||
/// <inheritdoc cref="IHasReadTimeEstimate"/>
|
||||
public int MinHoursToRead { get; set; }
|
||||
/// <inheritdoc cref="IHasReadTimeEstimate"/>
|
||||
public int MaxHoursToRead { get; set; }
|
||||
/// <inheritdoc cref="IHasReadTimeEstimate"/>
|
||||
public int AvgHoursToRead { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// All people attached at a Chapter level. Usually Comics will have different people per issue.
|
||||
/// </summary>
|
||||
public ICollection<Person> People { get; set; } = new List<Person>();
|
||||
/// <summary>
|
||||
/// Genres for the Chapter
|
||||
/// </summary>
|
||||
public ICollection<Genre> Genres { get; set; } = new List<Genre>();
|
||||
public ICollection<Tag> Tags { get; set; } = new List<Tag>();
|
||||
|
||||
|
||||
|
||||
|
||||
// Relationships
|
||||
public Volume Volume { get; set; }
|
||||
public int VolumeId { get; set; }
|
||||
|
||||
public void UpdateFrom(ParserInfo info)
|
||||
Files ??= new List<MangaFile>();
|
||||
IsSpecial = info.IsSpecialInfo();
|
||||
if (IsSpecial)
|
||||
{
|
||||
Files ??= new List<MangaFile>();
|
||||
IsSpecial = info.IsSpecialInfo();
|
||||
if (IsSpecial)
|
||||
{
|
||||
Number = "0";
|
||||
}
|
||||
Title = (IsSpecial && info.Format == MangaFormat.Epub)
|
||||
? info.Title
|
||||
: Range;
|
||||
|
||||
Number = "0";
|
||||
}
|
||||
Title = (IsSpecial && info.Format == MangaFormat.Epub)
|
||||
? info.Title
|
||||
: Range;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,56 +2,55 @@
|
|||
using API.Entities.Metadata;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a user entered field that is used as a tagging and grouping mechanism
|
||||
/// </summary>
|
||||
[Index(nameof(Id), nameof(Promoted), IsUnique = true)]
|
||||
public class CollectionTag
|
||||
{
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// Represents a user entered field that is used as a tagging and grouping mechanism
|
||||
/// Visible title of the Tag
|
||||
/// </summary>
|
||||
[Index(nameof(Id), nameof(Promoted), IsUnique = true)]
|
||||
public class CollectionTag
|
||||
public string Title { get; set; }
|
||||
/// <summary>
|
||||
/// Absolute path to the (managed) image file
|
||||
/// </summary>
|
||||
/// <remarks>The file is managed internally to Kavita's APPDIR</remarks>
|
||||
public string CoverImage { get; set; }
|
||||
/// <summary>
|
||||
/// Denotes if the CoverImage has been overridden by the user. If so, it will not be updated during normal scan operations.
|
||||
/// </summary>
|
||||
public bool CoverImageLocked { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A description of the tag
|
||||
/// </summary>
|
||||
public string Summary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A normalized string used to check if the tag already exists in the DB
|
||||
/// </summary>
|
||||
public string NormalizedTitle { get; set; }
|
||||
/// <summary>
|
||||
/// A promoted collection tag will allow all linked seriesMetadata's Series to show for all users.
|
||||
/// </summary>
|
||||
public bool Promoted { get; set; }
|
||||
|
||||
public ICollection<SeriesMetadata> SeriesMetadatas { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Not Used due to not using concurrency update
|
||||
/// </summary>
|
||||
public uint RowVersion { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Not Used due to not using concurrency update
|
||||
/// </summary>
|
||||
public void OnSavingChanges()
|
||||
{
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// Visible title of the Tag
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
/// <summary>
|
||||
/// Absolute path to the (managed) image file
|
||||
/// </summary>
|
||||
/// <remarks>The file is managed internally to Kavita's APPDIR</remarks>
|
||||
public string CoverImage { get; set; }
|
||||
/// <summary>
|
||||
/// Denotes if the CoverImage has been overridden by the user. If so, it will not be updated during normal scan operations.
|
||||
/// </summary>
|
||||
public bool CoverImageLocked { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A description of the tag
|
||||
/// </summary>
|
||||
public string Summary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A normalized string used to check if the tag already exists in the DB
|
||||
/// </summary>
|
||||
public string NormalizedTitle { get; set; }
|
||||
/// <summary>
|
||||
/// A promoted collection tag will allow all linked seriesMetadata's Series to show for all users.
|
||||
/// </summary>
|
||||
public bool Promoted { get; set; }
|
||||
|
||||
public ICollection<SeriesMetadata> SeriesMetadatas { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Not Used due to not using concurrency update
|
||||
/// </summary>
|
||||
public uint RowVersion { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Not Used due to not using concurrency update
|
||||
/// </summary>
|
||||
public void OnSavingChanges()
|
||||
{
|
||||
RowVersion++;
|
||||
}
|
||||
RowVersion++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
using System.ComponentModel;
|
||||
|
||||
namespace API.Entities.Enums
|
||||
namespace API.Entities.Enums;
|
||||
|
||||
public enum LibraryType
|
||||
{
|
||||
public enum LibraryType
|
||||
{
|
||||
/// <summary>
|
||||
/// Uses Manga regex for filename parsing
|
||||
/// </summary>
|
||||
[Description("Manga")]
|
||||
Manga = 0,
|
||||
/// <summary>
|
||||
/// Uses Comic regex for filename parsing
|
||||
/// </summary>
|
||||
[Description("Comic")]
|
||||
Comic = 1,
|
||||
/// <summary>
|
||||
/// Uses Manga regex for filename parsing also uses epub metadata
|
||||
/// </summary>
|
||||
[Description("Book")]
|
||||
Book = 2,
|
||||
}
|
||||
/// <summary>
|
||||
/// Uses Manga regex for filename parsing
|
||||
/// </summary>
|
||||
[Description("Manga")]
|
||||
Manga = 0,
|
||||
/// <summary>
|
||||
/// Uses Comic regex for filename parsing
|
||||
/// </summary>
|
||||
[Description("Comic")]
|
||||
Comic = 1,
|
||||
/// <summary>
|
||||
/// Uses Manga regex for filename parsing also uses epub metadata
|
||||
/// </summary>
|
||||
[Description("Book")]
|
||||
Book = 2,
|
||||
}
|
||||
|
|
|
@ -1,38 +1,37 @@
|
|||
using System.ComponentModel;
|
||||
|
||||
namespace API.Entities.Enums
|
||||
namespace API.Entities.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the format of the file
|
||||
/// </summary>
|
||||
public enum MangaFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the format of the file
|
||||
/// Image file
|
||||
/// See <see cref="Services.Tasks.Scanner.Parser.Parser.ImageFileExtensions"/> for supported extensions
|
||||
/// </summary>
|
||||
public enum MangaFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Image file
|
||||
/// See <see cref="Services.Tasks.Scanner.Parser.Parser.ImageFileExtensions"/> for supported extensions
|
||||
/// </summary>
|
||||
[Description("Image")]
|
||||
Image = 0,
|
||||
/// <summary>
|
||||
/// Archive based file
|
||||
/// See <see cref="Services.Tasks.Scanner.Parser.Parser.ArchiveFileExtensions"/> for supported extensions
|
||||
/// </summary>
|
||||
[Description("Archive")]
|
||||
Archive = 1,
|
||||
/// <summary>
|
||||
/// Unknown. Not used.
|
||||
/// </summary>
|
||||
[Description("Unknown")]
|
||||
Unknown = 2,
|
||||
/// <summary>
|
||||
/// EPUB File
|
||||
/// </summary>
|
||||
[Description("EPUB")]
|
||||
Epub = 3,
|
||||
/// <summary>
|
||||
/// PDF File
|
||||
/// </summary>
|
||||
[Description("PDF")]
|
||||
Pdf = 4
|
||||
}
|
||||
[Description("Image")]
|
||||
Image = 0,
|
||||
/// <summary>
|
||||
/// Archive based file
|
||||
/// See <see cref="Services.Tasks.Scanner.Parser.Parser.ArchiveFileExtensions"/> for supported extensions
|
||||
/// </summary>
|
||||
[Description("Archive")]
|
||||
Archive = 1,
|
||||
/// <summary>
|
||||
/// Unknown. Not used.
|
||||
/// </summary>
|
||||
[Description("Unknown")]
|
||||
Unknown = 2,
|
||||
/// <summary>
|
||||
/// EPUB File
|
||||
/// </summary>
|
||||
[Description("EPUB")]
|
||||
Epub = 3,
|
||||
/// <summary>
|
||||
/// PDF File
|
||||
/// </summary>
|
||||
[Description("PDF")]
|
||||
Pdf = 4
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
namespace API.Entities.Enums
|
||||
namespace API.Entities.Enums;
|
||||
|
||||
public enum PageSplitOption
|
||||
{
|
||||
public enum PageSplitOption
|
||||
{
|
||||
SplitLeftToRight = 0,
|
||||
SplitRightToLeft = 1,
|
||||
NoSplit = 2,
|
||||
FitSplit = 3
|
||||
}
|
||||
SplitLeftToRight = 0,
|
||||
SplitRightToLeft = 1,
|
||||
NoSplit = 2,
|
||||
FitSplit = 3
|
||||
}
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
namespace API.Entities.Enums
|
||||
namespace API.Entities.Enums;
|
||||
|
||||
public enum PersonRole
|
||||
{
|
||||
public enum PersonRole
|
||||
{
|
||||
/// <summary>
|
||||
/// Another role, not covered by other types
|
||||
/// </summary>
|
||||
Other = 1,
|
||||
/// <summary>
|
||||
/// Author or Writer
|
||||
/// </summary>
|
||||
Writer = 3,
|
||||
Penciller = 4,
|
||||
Inker = 5,
|
||||
Colorist = 6,
|
||||
Letterer = 7,
|
||||
CoverArtist = 8,
|
||||
Editor = 9,
|
||||
Publisher = 10,
|
||||
/// <summary>
|
||||
/// Represents a character/person within the story
|
||||
/// </summary>
|
||||
Character = 11,
|
||||
/// <summary>
|
||||
/// The Translator
|
||||
/// </summary>
|
||||
Translator = 12
|
||||
/// <summary>
|
||||
/// Another role, not covered by other types
|
||||
/// </summary>
|
||||
Other = 1,
|
||||
/// <summary>
|
||||
/// Author or Writer
|
||||
/// </summary>
|
||||
Writer = 3,
|
||||
Penciller = 4,
|
||||
Inker = 5,
|
||||
Colorist = 6,
|
||||
Letterer = 7,
|
||||
CoverArtist = 8,
|
||||
Editor = 9,
|
||||
Publisher = 10,
|
||||
/// <summary>
|
||||
/// Represents a character/person within the story
|
||||
/// </summary>
|
||||
Character = 11,
|
||||
/// <summary>
|
||||
/// The Translator
|
||||
/// </summary>
|
||||
Translator = 12
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
using System.ComponentModel;
|
||||
|
||||
namespace API.Entities.Enums
|
||||
namespace API.Entities.Enums;
|
||||
|
||||
public enum ReaderMode
|
||||
{
|
||||
public enum ReaderMode
|
||||
{
|
||||
[Description("Left and Right")]
|
||||
LeftRight = 0,
|
||||
[Description("Up and Down")]
|
||||
UpDown = 1,
|
||||
[Description("Webtoon")]
|
||||
Webtoon = 2
|
||||
}
|
||||
[Description("Left and Right")]
|
||||
LeftRight = 0,
|
||||
[Description("Up and Down")]
|
||||
UpDown = 1,
|
||||
[Description("Webtoon")]
|
||||
Webtoon = 2
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
namespace API.Entities.Enums
|
||||
namespace API.Entities.Enums;
|
||||
|
||||
public enum ReadingDirection
|
||||
{
|
||||
public enum ReadingDirection
|
||||
{
|
||||
LeftToRight = 0,
|
||||
RightToLeft = 1
|
||||
}
|
||||
}
|
||||
LeftToRight = 0,
|
||||
RightToLeft = 1
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
namespace API.Entities.Enums
|
||||
namespace API.Entities.Enums;
|
||||
|
||||
public enum ScalingOption
|
||||
{
|
||||
public enum ScalingOption
|
||||
{
|
||||
FitToHeight = 0,
|
||||
FitToWidth = 1,
|
||||
Original = 2,
|
||||
Automatic = 3
|
||||
}
|
||||
}
|
||||
FitToHeight = 0,
|
||||
FitToWidth = 1,
|
||||
Original = 2,
|
||||
Automatic = 3
|
||||
}
|
||||
|
|
|
@ -1,100 +1,99 @@
|
|||
using System.ComponentModel;
|
||||
|
||||
namespace API.Entities.Enums
|
||||
namespace API.Entities.Enums;
|
||||
|
||||
public enum ServerSettingKey
|
||||
{
|
||||
public enum ServerSettingKey
|
||||
{
|
||||
/// <summary>
|
||||
/// Cron format for how often full library scans are performed.
|
||||
/// </summary>
|
||||
[Description("TaskScan")]
|
||||
TaskScan = 0,
|
||||
/// <summary>
|
||||
/// Where files are cached. Not currently used.
|
||||
/// </summary>
|
||||
[Description("CacheDirectory")]
|
||||
CacheDirectory = 1,
|
||||
/// <summary>
|
||||
/// Cron format for how often backups are taken.
|
||||
/// </summary>
|
||||
[Description("TaskBackup")]
|
||||
TaskBackup = 2,
|
||||
/// <summary>
|
||||
/// Logging level for Server. Not managed in DB. Managed in appsettings.json and synced to DB.
|
||||
/// </summary>
|
||||
[Description("LoggingLevel")]
|
||||
LoggingLevel = 3,
|
||||
/// <summary>
|
||||
/// Port server listens on. Not managed in DB. Managed in appsettings.json and synced to DB.
|
||||
/// </summary>
|
||||
[Description("Port")]
|
||||
Port = 4,
|
||||
/// <summary>
|
||||
/// Where the backups are stored.
|
||||
/// </summary>
|
||||
[Description("BackupDirectory")]
|
||||
BackupDirectory = 5,
|
||||
/// <summary>
|
||||
/// Allow anonymous data to be reported to KavitaStats
|
||||
/// </summary>
|
||||
[Description("AllowStatCollection")]
|
||||
AllowStatCollection = 6,
|
||||
/// <summary>
|
||||
/// Is OPDS enabled for the server
|
||||
/// </summary>
|
||||
[Description("EnableOpds")]
|
||||
EnableOpds = 7,
|
||||
/// <summary>
|
||||
/// 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>
|
||||
[Description("EnableAuthentication")]
|
||||
EnableAuthentication = 8,
|
||||
/// <summary>
|
||||
/// Base Url for the server. Not Implemented.
|
||||
/// </summary>
|
||||
[Description("BaseUrl")]
|
||||
BaseUrl = 9,
|
||||
/// <summary>
|
||||
/// Represents this installation of Kavita. Is tied to Stat reporting but has no information about user or files.
|
||||
/// </summary>
|
||||
[Description("InstallId")]
|
||||
InstallId = 10,
|
||||
/// <summary>
|
||||
/// Represents the version the software is running.
|
||||
/// </summary>
|
||||
/// <remarks>This will be updated on Startup to the latest release. Provides ability to detect if certain migrations need to be run.</remarks>
|
||||
[Description("InstallVersion")]
|
||||
InstallVersion = 11,
|
||||
/// <summary>
|
||||
/// Location of where bookmarks are stored
|
||||
/// </summary>
|
||||
[Description("BookmarkDirectory")]
|
||||
BookmarkDirectory = 12,
|
||||
/// <summary>
|
||||
/// If SMTP is enabled on the server
|
||||
/// </summary>
|
||||
[Description("CustomEmailService")]
|
||||
EmailServiceUrl = 13,
|
||||
/// <summary>
|
||||
/// If Kavita should save bookmarks as WebP images
|
||||
/// </summary>
|
||||
[Description("ConvertBookmarkToWebP")]
|
||||
ConvertBookmarkToWebP = 14,
|
||||
/// <summary>
|
||||
/// If the Swagger UI Should be exposed. Does not require authentication, but does require a JWT.
|
||||
/// </summary>
|
||||
[Description("EnableSwaggerUi")]
|
||||
EnableSwaggerUi = 15,
|
||||
/// <summary>
|
||||
/// Total Number of Backups to maintain before cleaning. Default 30, min 1.
|
||||
/// </summary>
|
||||
[Description("TotalBackups")]
|
||||
TotalBackups = 16,
|
||||
/// <summary>
|
||||
/// If Kavita should watch the library folders and process changes
|
||||
/// </summary>
|
||||
[Description("EnableFolderWatching")]
|
||||
EnableFolderWatching = 17,
|
||||
}
|
||||
/// <summary>
|
||||
/// Cron format for how often full library scans are performed.
|
||||
/// </summary>
|
||||
[Description("TaskScan")]
|
||||
TaskScan = 0,
|
||||
/// <summary>
|
||||
/// Where files are cached. Not currently used.
|
||||
/// </summary>
|
||||
[Description("CacheDirectory")]
|
||||
CacheDirectory = 1,
|
||||
/// <summary>
|
||||
/// Cron format for how often backups are taken.
|
||||
/// </summary>
|
||||
[Description("TaskBackup")]
|
||||
TaskBackup = 2,
|
||||
/// <summary>
|
||||
/// Logging level for Server. Not managed in DB. Managed in appsettings.json and synced to DB.
|
||||
/// </summary>
|
||||
[Description("LoggingLevel")]
|
||||
LoggingLevel = 3,
|
||||
/// <summary>
|
||||
/// Port server listens on. Not managed in DB. Managed in appsettings.json and synced to DB.
|
||||
/// </summary>
|
||||
[Description("Port")]
|
||||
Port = 4,
|
||||
/// <summary>
|
||||
/// Where the backups are stored.
|
||||
/// </summary>
|
||||
[Description("BackupDirectory")]
|
||||
BackupDirectory = 5,
|
||||
/// <summary>
|
||||
/// Allow anonymous data to be reported to KavitaStats
|
||||
/// </summary>
|
||||
[Description("AllowStatCollection")]
|
||||
AllowStatCollection = 6,
|
||||
/// <summary>
|
||||
/// Is OPDS enabled for the server
|
||||
/// </summary>
|
||||
[Description("EnableOpds")]
|
||||
EnableOpds = 7,
|
||||
/// <summary>
|
||||
/// 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>
|
||||
[Description("EnableAuthentication")]
|
||||
EnableAuthentication = 8,
|
||||
/// <summary>
|
||||
/// Base Url for the server. Not Implemented.
|
||||
/// </summary>
|
||||
[Description("BaseUrl")]
|
||||
BaseUrl = 9,
|
||||
/// <summary>
|
||||
/// Represents this installation of Kavita. Is tied to Stat reporting but has no information about user or files.
|
||||
/// </summary>
|
||||
[Description("InstallId")]
|
||||
InstallId = 10,
|
||||
/// <summary>
|
||||
/// Represents the version the software is running.
|
||||
/// </summary>
|
||||
/// <remarks>This will be updated on Startup to the latest release. Provides ability to detect if certain migrations need to be run.</remarks>
|
||||
[Description("InstallVersion")]
|
||||
InstallVersion = 11,
|
||||
/// <summary>
|
||||
/// Location of where bookmarks are stored
|
||||
/// </summary>
|
||||
[Description("BookmarkDirectory")]
|
||||
BookmarkDirectory = 12,
|
||||
/// <summary>
|
||||
/// If SMTP is enabled on the server
|
||||
/// </summary>
|
||||
[Description("CustomEmailService")]
|
||||
EmailServiceUrl = 13,
|
||||
/// <summary>
|
||||
/// If Kavita should save bookmarks as WebP images
|
||||
/// </summary>
|
||||
[Description("ConvertBookmarkToWebP")]
|
||||
ConvertBookmarkToWebP = 14,
|
||||
/// <summary>
|
||||
/// If the Swagger UI Should be exposed. Does not require authentication, but does require a JWT.
|
||||
/// </summary>
|
||||
[Description("EnableSwaggerUi")]
|
||||
EnableSwaggerUi = 15,
|
||||
/// <summary>
|
||||
/// Total Number of Backups to maintain before cleaning. Default 30, min 1.
|
||||
/// </summary>
|
||||
[Description("TotalBackups")]
|
||||
TotalBackups = 16,
|
||||
/// <summary>
|
||||
/// If Kavita should watch the library folders and process changes
|
||||
/// </summary>
|
||||
[Description("EnableFolderWatching")]
|
||||
EnableFolderWatching = 17,
|
||||
}
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace API.Entities
|
||||
{
|
||||
public class FolderPath
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Path { get; set; }
|
||||
/// <summary>
|
||||
/// Used when scanning to see if we can skip if nothing has changed
|
||||
/// </summary>
|
||||
/// <remarks>Time stored in UTC</remarks>
|
||||
public DateTime LastScanned { get; set; }
|
||||
namespace API.Entities;
|
||||
|
||||
// Relationship
|
||||
public Library Library { get; set; }
|
||||
public int LibraryId { get; set; }
|
||||
}
|
||||
public class FolderPath
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Path { get; set; }
|
||||
/// <summary>
|
||||
/// Used when scanning to see if we can skip if nothing has changed
|
||||
/// </summary>
|
||||
/// <remarks>Time stored in UTC</remarks>
|
||||
public DateTime LastScanned { get; set; }
|
||||
|
||||
// Relationship
|
||||
public Library Library { get; set; }
|
||||
public int LibraryId { get; set; }
|
||||
}
|
||||
|
|
|
@ -2,17 +2,16 @@
|
|||
using API.Entities.Metadata;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace API.Entities
|
||||
{
|
||||
[Index(nameof(NormalizedTitle), nameof(ExternalTag), IsUnique = true)]
|
||||
public class Genre
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string NormalizedTitle { get; set; }
|
||||
public bool ExternalTag { get; set; }
|
||||
namespace API.Entities;
|
||||
|
||||
public ICollection<SeriesMetadata> SeriesMetadatas { get; set; }
|
||||
public ICollection<Chapter> Chapters { get; set; }
|
||||
}
|
||||
[Index(nameof(NormalizedTitle), nameof(ExternalTag), IsUnique = true)]
|
||||
public class Genre
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string NormalizedTitle { get; set; }
|
||||
public bool ExternalTag { get; set; }
|
||||
|
||||
public ICollection<SeriesMetadata> SeriesMetadatas { get; set; }
|
||||
public ICollection<Chapter> Chapters { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace API.Entities.Interfaces
|
||||
namespace API.Entities.Interfaces;
|
||||
|
||||
public interface IEntityDate
|
||||
{
|
||||
public interface IEntityDate
|
||||
{
|
||||
DateTime Created { get; set; }
|
||||
DateTime LastModified { get; set; }
|
||||
}
|
||||
}
|
||||
DateTime Created { get; set; }
|
||||
DateTime LastModified { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
namespace API.Entities.Interfaces
|
||||
namespace API.Entities.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// An interface abstracting an entity that has a concurrency token.
|
||||
/// </summary>
|
||||
public interface IHasConcurrencyToken
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface abstracting an entity that has a concurrency token.
|
||||
/// Gets the version of this row. Acts as a concurrency token.
|
||||
/// </summary>
|
||||
public interface IHasConcurrencyToken
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the version of this row. Acts as a concurrency token.
|
||||
/// </summary>
|
||||
uint RowVersion { get; }
|
||||
uint RowVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when saving changes to this entity.
|
||||
/// </summary>
|
||||
void OnSavingChanges();
|
||||
/// <summary>
|
||||
/// Called when saving changes to this entity.
|
||||
/// </summary>
|
||||
void OnSavingChanges();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,39 +5,38 @@ using System.Linq;
|
|||
using API.Entities.Enums;
|
||||
using API.Entities.Interfaces;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
public class Library : IEntityDate
|
||||
{
|
||||
public class Library : IEntityDate
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// Update this summary with a way it's used, else let's remove it.
|
||||
/// </summary>
|
||||
[Obsolete("This has never been coded for. Likely we can remove it.")]
|
||||
public string CoverImage { get; set; }
|
||||
public LibraryType Type { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
/// <summary>
|
||||
/// Last time Library was scanned
|
||||
/// </summary>
|
||||
/// <remarks>Time stored in UTC</remarks>
|
||||
public DateTime LastScanned { get; set; }
|
||||
public ICollection<FolderPath> Folders { get; set; }
|
||||
public ICollection<AppUser> AppUsers { get; set; }
|
||||
public ICollection<Series> Series { get; set; }
|
||||
|
||||
// Methods
|
||||
/// <summary>
|
||||
/// Has there been any modifications to the FolderPath's directory since the <see cref="FolderPath.LastScanned"/> date
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool AnyModificationsSinceLastScan()
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// Update this summary with a way it's used, else let's remove it.
|
||||
/// </summary>
|
||||
[Obsolete("This has never been coded for. Likely we can remove it.")]
|
||||
public string CoverImage { get; set; }
|
||||
public LibraryType Type { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
/// <summary>
|
||||
/// Last time Library was scanned
|
||||
/// </summary>
|
||||
/// <remarks>Time stored in UTC</remarks>
|
||||
public DateTime LastScanned { get; set; }
|
||||
public ICollection<FolderPath> Folders { get; set; }
|
||||
public ICollection<AppUser> AppUsers { get; set; }
|
||||
public ICollection<Series> Series { get; set; }
|
||||
|
||||
// Methods
|
||||
/// <summary>
|
||||
/// Has there been any modifications to the FolderPath's directory since the <see cref="FolderPath.LastScanned"/> date
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool AnyModificationsSinceLastScan()
|
||||
{
|
||||
// NOTE: I don't think we can do this due to NTFS
|
||||
return Folders.All(folder => File.GetLastWriteTimeUtc(folder.Path) > folder.LastScanned);
|
||||
}
|
||||
|
||||
// NOTE: I don't think we can do this due to NTFS
|
||||
return Folders.All(folder => File.GetLastWriteTimeUtc(folder.Path) > folder.LastScanned);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,48 +4,47 @@ using System.IO;
|
|||
using API.Entities.Enums;
|
||||
using API.Entities.Interfaces;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a wrapper to the underlying file. This provides information around file, like number of pages, format, etc.
|
||||
/// </summary>
|
||||
public class MangaFile : IEntityDate
|
||||
{
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// Represents a wrapper to the underlying file. This provides information around file, like number of pages, format, etc.
|
||||
/// Absolute path to the archive file
|
||||
/// </summary>
|
||||
public class MangaFile : IEntityDate
|
||||
public string FilePath { get; set; }
|
||||
/// <summary>
|
||||
/// Number of pages for the given file
|
||||
/// </summary>
|
||||
public int Pages { get; set; }
|
||||
public MangaFormat Format { get; set; }
|
||||
/// <inheritdoc cref="IEntityDate.Created"/>
|
||||
public DateTime Created { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Last time underlying file was modified
|
||||
/// </summary>
|
||||
/// <remarks>This gets updated anytime the file is scanned</remarks>
|
||||
public DateTime LastModified { get; set; }
|
||||
/// <summary>
|
||||
/// Last time file analysis ran on this file
|
||||
/// </summary>
|
||||
public DateTime LastFileAnalysis { get; set; }
|
||||
|
||||
|
||||
// Relationship Mapping
|
||||
public Chapter Chapter { get; set; }
|
||||
public int ChapterId { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Updates the Last Modified time of the underlying file to the LastWriteTime
|
||||
/// </summary>
|
||||
public void UpdateLastModified()
|
||||
{
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// Absolute path to the archive file
|
||||
/// </summary>
|
||||
public string FilePath { get; set; }
|
||||
/// <summary>
|
||||
/// Number of pages for the given file
|
||||
/// </summary>
|
||||
public int Pages { get; set; }
|
||||
public MangaFormat Format { get; set; }
|
||||
/// <inheritdoc cref="IEntityDate.Created"/>
|
||||
public DateTime Created { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Last time underlying file was modified
|
||||
/// </summary>
|
||||
/// <remarks>This gets updated anytime the file is scanned</remarks>
|
||||
public DateTime LastModified { get; set; }
|
||||
/// <summary>
|
||||
/// Last time file analysis ran on this file
|
||||
/// </summary>
|
||||
public DateTime LastFileAnalysis { get; set; }
|
||||
|
||||
|
||||
// Relationship Mapping
|
||||
public Chapter Chapter { get; set; }
|
||||
public int ChapterId { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Updates the Last Modified time of the underlying file to the LastWriteTime
|
||||
/// </summary>
|
||||
public void UpdateLastModified()
|
||||
{
|
||||
LastModified = File.GetLastWriteTime(FilePath);
|
||||
}
|
||||
LastModified = File.GetLastWriteTime(FilePath);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,84 +4,83 @@ using API.Entities.Enums;
|
|||
using API.Entities.Interfaces;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace API.Entities.Metadata
|
||||
namespace API.Entities.Metadata;
|
||||
|
||||
[Index(nameof(Id), nameof(SeriesId), IsUnique = true)]
|
||||
public class SeriesMetadata : IHasConcurrencyToken
|
||||
{
|
||||
[Index(nameof(Id), nameof(SeriesId), IsUnique = true)]
|
||||
public class SeriesMetadata : IHasConcurrencyToken
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Summary { get; set; } = string.Empty;
|
||||
|
||||
public ICollection<CollectionTag> CollectionTags { get; set; }
|
||||
|
||||
public ICollection<Genre> Genres { get; set; } = new List<Genre>();
|
||||
public ICollection<Tag> Tags { get; set; } = new List<Tag>();
|
||||
/// <summary>
|
||||
/// All people attached at a Series level.
|
||||
/// </summary>
|
||||
public ICollection<Person> People { get; set; } = new List<Person>();
|
||||
|
||||
/// <summary>
|
||||
/// Highest Age Rating from all Chapters
|
||||
/// </summary>
|
||||
public AgeRating AgeRating { get; set; }
|
||||
/// <summary>
|
||||
/// Earliest Year from all chapters
|
||||
/// </summary>
|
||||
public int ReleaseYear { get; set; }
|
||||
/// <summary>
|
||||
/// Language of the content (BCP-47 code)
|
||||
/// </summary>
|
||||
public string Language { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Total number of issues/volumes in the series
|
||||
/// </summary>
|
||||
public int TotalCount { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// Max number of issues/volumes in the series (Max of Volume/Issue field in ComicInfo)
|
||||
/// </summary>
|
||||
public int MaxCount { get; set; } = 0;
|
||||
public PublicationStatus PublicationStatus { get; set; }
|
||||
|
||||
// Locks
|
||||
public bool LanguageLocked { get; set; }
|
||||
public bool SummaryLocked { get; set; }
|
||||
/// <summary>
|
||||
/// Locked by user so metadata updates from scan loop will not override AgeRating
|
||||
/// </summary>
|
||||
public bool AgeRatingLocked { get; set; }
|
||||
/// <summary>
|
||||
/// Locked by user so metadata updates from scan loop will not override PublicationStatus
|
||||
/// </summary>
|
||||
public bool PublicationStatusLocked { get; set; }
|
||||
public bool GenresLocked { get; set; }
|
||||
public bool TagsLocked { get; set; }
|
||||
public bool WriterLocked { get; set; }
|
||||
public bool CharacterLocked { get; set; }
|
||||
public bool ColoristLocked { get; set; }
|
||||
public bool EditorLocked { get; set; }
|
||||
public bool InkerLocked { get; set; }
|
||||
public bool LettererLocked { get; set; }
|
||||
public bool PencillerLocked { get; set; }
|
||||
public bool PublisherLocked { get; set; }
|
||||
public bool TranslatorLocked { get; set; }
|
||||
public bool CoverArtistLocked { get; set; }
|
||||
|
||||
|
||||
// Relationship
|
||||
public Series Series { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[ConcurrencyCheck]
|
||||
public uint RowVersion { get; private set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnSavingChanges()
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Summary { get; set; } = string.Empty;
|
||||
|
||||
public ICollection<CollectionTag> CollectionTags { get; set; }
|
||||
|
||||
public ICollection<Genre> Genres { get; set; } = new List<Genre>();
|
||||
public ICollection<Tag> Tags { get; set; } = new List<Tag>();
|
||||
/// <summary>
|
||||
/// All people attached at a Series level.
|
||||
/// </summary>
|
||||
public ICollection<Person> People { get; set; } = new List<Person>();
|
||||
|
||||
/// <summary>
|
||||
/// Highest Age Rating from all Chapters
|
||||
/// </summary>
|
||||
public AgeRating AgeRating { get; set; }
|
||||
/// <summary>
|
||||
/// Earliest Year from all chapters
|
||||
/// </summary>
|
||||
public int ReleaseYear { get; set; }
|
||||
/// <summary>
|
||||
/// Language of the content (BCP-47 code)
|
||||
/// </summary>
|
||||
public string Language { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Total number of issues/volumes in the series
|
||||
/// </summary>
|
||||
public int TotalCount { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// Max number of issues/volumes in the series (Max of Volume/Issue field in ComicInfo)
|
||||
/// </summary>
|
||||
public int MaxCount { get; set; } = 0;
|
||||
public PublicationStatus PublicationStatus { get; set; }
|
||||
|
||||
// Locks
|
||||
public bool LanguageLocked { get; set; }
|
||||
public bool SummaryLocked { get; set; }
|
||||
/// <summary>
|
||||
/// Locked by user so metadata updates from scan loop will not override AgeRating
|
||||
/// </summary>
|
||||
public bool AgeRatingLocked { get; set; }
|
||||
/// <summary>
|
||||
/// Locked by user so metadata updates from scan loop will not override PublicationStatus
|
||||
/// </summary>
|
||||
public bool PublicationStatusLocked { get; set; }
|
||||
public bool GenresLocked { get; set; }
|
||||
public bool TagsLocked { get; set; }
|
||||
public bool WriterLocked { get; set; }
|
||||
public bool CharacterLocked { get; set; }
|
||||
public bool ColoristLocked { get; set; }
|
||||
public bool EditorLocked { get; set; }
|
||||
public bool InkerLocked { get; set; }
|
||||
public bool LettererLocked { get; set; }
|
||||
public bool PencillerLocked { get; set; }
|
||||
public bool PublisherLocked { get; set; }
|
||||
public bool TranslatorLocked { get; set; }
|
||||
public bool CoverArtistLocked { get; set; }
|
||||
|
||||
|
||||
// Relationship
|
||||
public Series Series { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[ConcurrencyCheck]
|
||||
public uint RowVersion { get; private set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnSavingChanges()
|
||||
{
|
||||
RowVersion++;
|
||||
}
|
||||
RowVersion++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,23 +2,22 @@
|
|||
using API.Entities.Enums;
|
||||
using API.Entities.Metadata;
|
||||
|
||||
namespace API.Entities
|
||||
{
|
||||
public enum ProviderSource
|
||||
{
|
||||
Local = 1,
|
||||
External = 2
|
||||
}
|
||||
public class Person
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string NormalizedName { get; set; }
|
||||
public PersonRole Role { get; set; }
|
||||
//public ProviderSource Source { get; set; }
|
||||
namespace API.Entities;
|
||||
|
||||
// Relationships
|
||||
public ICollection<SeriesMetadata> SeriesMetadatas { get; set; }
|
||||
public ICollection<Chapter> ChapterMetadatas { get; set; }
|
||||
}
|
||||
public enum ProviderSource
|
||||
{
|
||||
Local = 1,
|
||||
External = 2
|
||||
}
|
||||
public class Person
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string NormalizedName { get; set; }
|
||||
public PersonRole Role { get; set; }
|
||||
//public ProviderSource Source { get; set; }
|
||||
|
||||
// Relationships
|
||||
public ICollection<SeriesMetadata> SeriesMetadatas { get; set; }
|
||||
public ICollection<Chapter> ChapterMetadatas { get; set; }
|
||||
}
|
||||
|
|
|
@ -2,38 +2,37 @@
|
|||
using System.Collections.Generic;
|
||||
using API.Entities.Interfaces;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// This is a collection of <see cref="ReadingListItem"/> which represent individual chapters and an order.
|
||||
/// </summary>
|
||||
public class ReadingList : IEntityDate
|
||||
{
|
||||
public int Id { get; init; }
|
||||
public string Title { get; set; }
|
||||
/// <summary>
|
||||
/// This is a collection of <see cref="ReadingListItem"/> which represent individual chapters and an order.
|
||||
/// A normalized string used to check if the reading list already exists in the DB
|
||||
/// </summary>
|
||||
public class ReadingList : IEntityDate
|
||||
{
|
||||
public int Id { get; init; }
|
||||
public string Title { get; set; }
|
||||
/// <summary>
|
||||
/// A normalized string used to check if the reading list already exists in the DB
|
||||
/// </summary>
|
||||
public string NormalizedTitle { get; set; }
|
||||
public string Summary { get; set; }
|
||||
/// <summary>
|
||||
/// Reading lists that are promoted are only done by admins
|
||||
/// </summary>
|
||||
public bool Promoted { get; set; }
|
||||
/// <summary>
|
||||
/// Absolute path to the (managed) image file
|
||||
/// </summary>
|
||||
/// <remarks>The file is managed internally to Kavita's APPDIR</remarks>
|
||||
public string CoverImage { get; set; }
|
||||
public bool CoverImageLocked { get; set; }
|
||||
public string NormalizedTitle { get; set; }
|
||||
public string Summary { get; set; }
|
||||
/// <summary>
|
||||
/// Reading lists that are promoted are only done by admins
|
||||
/// </summary>
|
||||
public bool Promoted { get; set; }
|
||||
/// <summary>
|
||||
/// Absolute path to the (managed) image file
|
||||
/// </summary>
|
||||
/// <remarks>The file is managed internally to Kavita's APPDIR</remarks>
|
||||
public string CoverImage { get; set; }
|
||||
public bool CoverImageLocked { get; set; }
|
||||
|
||||
public ICollection<ReadingListItem> Items { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
public ICollection<ReadingListItem> Items { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
|
||||
// Relationships
|
||||
public int AppUserId { get; set; }
|
||||
public AppUser AppUser { get; set; }
|
||||
// Relationships
|
||||
public int AppUserId { get; set; }
|
||||
public AppUser AppUser { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
public class ReadingListItem
|
||||
{
|
||||
public class ReadingListItem
|
||||
{
|
||||
public int Id { get; init; }
|
||||
public int SeriesId { get; set; }
|
||||
public int VolumeId { get; set; }
|
||||
public int ChapterId { get; set; }
|
||||
/// <summary>
|
||||
/// Order of the chapter within a Reading List
|
||||
/// </summary>
|
||||
public int Order { get; set; }
|
||||
public int Id { get; init; }
|
||||
public int SeriesId { get; set; }
|
||||
public int VolumeId { get; set; }
|
||||
public int ChapterId { get; set; }
|
||||
/// <summary>
|
||||
/// Order of the chapter within a Reading List
|
||||
/// </summary>
|
||||
public int Order { get; set; }
|
||||
|
||||
// Relationship
|
||||
public ReadingList ReadingList { get; set; }
|
||||
public int ReadingListId { get; set; }
|
||||
// Relationship
|
||||
public ReadingList ReadingList { get; set; }
|
||||
public int ReadingListId { get; set; }
|
||||
|
||||
// Keep these for easy join statements
|
||||
public Series Series { get; set; }
|
||||
public Volume Volume { get; set; }
|
||||
public Chapter Chapter { get; set; }
|
||||
// Keep these for easy join statements
|
||||
public Series Series { get; set; }
|
||||
public Volume Volume { get; set; }
|
||||
public Chapter Chapter { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,25 +2,24 @@
|
|||
using API.Entities.Enums;
|
||||
using API.Entities.Interfaces;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
public class ServerSetting : IHasConcurrencyToken
|
||||
{
|
||||
public class ServerSetting : IHasConcurrencyToken
|
||||
[Key]
|
||||
public ServerSettingKey Key { get; set; }
|
||||
/// <summary>
|
||||
/// The value of the Setting. Converter knows how to convert to the correct type
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[ConcurrencyCheck]
|
||||
public uint RowVersion { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnSavingChanges()
|
||||
{
|
||||
[Key]
|
||||
public ServerSettingKey Key { get; set; }
|
||||
/// <summary>
|
||||
/// The value of the Setting. Converter knows how to convert to the correct type
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[ConcurrencyCheck]
|
||||
public uint RowVersion { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnSavingChanges()
|
||||
{
|
||||
RowVersion++;
|
||||
}
|
||||
RowVersion++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,45 +2,44 @@
|
|||
using System.Collections.Generic;
|
||||
using API.Entities.Interfaces;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities;
|
||||
|
||||
public class Volume : IEntityDate, IHasReadTimeEstimate
|
||||
{
|
||||
public class Volume : IEntityDate, IHasReadTimeEstimate
|
||||
{
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// A String representation of the volume number. Allows for floats.
|
||||
/// </summary>
|
||||
/// <remarks>For Books with Series_index, this will map to the Series Index.</remarks>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// The minimum number in the Name field in Int form
|
||||
/// </summary>
|
||||
public int Number { get; set; }
|
||||
public IList<Chapter> Chapters { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
/// <summary>
|
||||
/// Absolute path to the (managed) image file
|
||||
/// </summary>
|
||||
/// <remarks>The file is managed internally to Kavita's APPDIR</remarks>
|
||||
public string CoverImage { get; set; }
|
||||
/// <summary>
|
||||
/// Total pages of all chapters in this volume
|
||||
/// </summary>
|
||||
public int Pages { get; set; }
|
||||
/// <summary>
|
||||
/// Total Word count of all chapters in this volume.
|
||||
/// </summary>
|
||||
/// <remarks>Word Count is only available from EPUB files</remarks>
|
||||
public long WordCount { get; set; }
|
||||
public int MinHoursToRead { get; set; }
|
||||
public int MaxHoursToRead { get; set; }
|
||||
public int AvgHoursToRead { get; set; }
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// A String representation of the volume number. Allows for floats.
|
||||
/// </summary>
|
||||
/// <remarks>For Books with Series_index, this will map to the Series Index.</remarks>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// The minimum number in the Name field in Int form
|
||||
/// </summary>
|
||||
public int Number { get; set; }
|
||||
public IList<Chapter> Chapters { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
/// <summary>
|
||||
/// Absolute path to the (managed) image file
|
||||
/// </summary>
|
||||
/// <remarks>The file is managed internally to Kavita's APPDIR</remarks>
|
||||
public string CoverImage { get; set; }
|
||||
/// <summary>
|
||||
/// Total pages of all chapters in this volume
|
||||
/// </summary>
|
||||
public int Pages { get; set; }
|
||||
/// <summary>
|
||||
/// Total Word count of all chapters in this volume.
|
||||
/// </summary>
|
||||
/// <remarks>Word Count is only available from EPUB files</remarks>
|
||||
public long WordCount { get; set; }
|
||||
public int MinHoursToRead { get; set; }
|
||||
public int MaxHoursToRead { get; set; }
|
||||
public int AvgHoursToRead { get; set; }
|
||||
|
||||
|
||||
// Relationships
|
||||
public Series Series { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
// Relationships
|
||||
public Series Series { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue