Kavita+ Overhaul & New Changelog (#3507)

This commit is contained in:
Joe Milazzo 2025-01-20 08:14:57 -06:00 committed by GitHub
parent d880c1690c
commit a5707617f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
249 changed files with 14775 additions and 2300 deletions

View file

@ -8,8 +8,10 @@ using API.DTOs.Collection;
using API.DTOs.CollectionTags;
using API.DTOs.Dashboard;
using API.DTOs.Device;
using API.DTOs.Email;
using API.DTOs.Filtering;
using API.DTOs.Filtering.v2;
using API.DTOs.KavitaPlus.Manage;
using API.DTOs.MediaErrors;
using API.DTOs.Metadata;
using API.DTOs.Progress;
@ -32,6 +34,8 @@ using API.Helpers.Converters;
using API.Services;
using AutoMapper;
using CollectionTag = API.Entities.CollectionTag;
using EmailHistory = API.Entities.EmailHistory;
using ExternalSeriesMetadata = API.Entities.Metadata.ExternalSeriesMetadata;
using MediaError = API.Entities.MediaError;
using PublicationStatus = API.Entities.Enums.PublicationStatus;
using SiteTheme = API.Entities.SiteTheme;
@ -334,9 +338,21 @@ public class AutoMapperProfiles : Profile
opt.MapFrom(src => ReviewService.GetCharacters(src.Body)));
CreateMap<ExternalRecommendation, ExternalSeriesDto>();
CreateMap<Series, ManageMatchSeriesDto>()
.ForMember(dest => dest.Series,
opt =>
opt.MapFrom(src => src))
.ForMember(dest => dest.IsMatched,
opt =>
opt.MapFrom(src => src.ExternalSeriesMetadata != null && src.ExternalSeriesMetadata.AniListId != 0 && src.ExternalSeriesMetadata.ValidUntilUtc > DateTime.MinValue))
.ForMember(dest => dest.ValidUntilUtc,
opt =>
opt.MapFrom(src => src.ExternalSeriesMetadata.ValidUntilUtc));
CreateMap<MangaFile, FileExtensionExportDto>();
CreateMap<EmailHistory, EmailHistoryDto>()
.ForMember(dest => dest.ToUserName, opt => opt.MapFrom(src => src.AppUser.UserName));
CreateMap<Chapter, StandaloneChapterDto>()
.ForMember(dest => dest.SeriesId, opt => opt.MapFrom(src => src.Volume.SeriesId))

View file

@ -2,6 +2,7 @@
using API.DTOs;
using API.DTOs.Scrobbling;
using API.Entities;
using API.Extensions;
using API.Services.Plus;
namespace API.Helpers.Builders;
@ -19,7 +20,7 @@ public class PlusSeriesDtoBuilder : IEntityBuilder<PlusSeriesDto>
{
_seriesDto = new PlusSeriesDto()
{
MediaFormat = LibraryTypeHelper.GetFormat(series.Library.Type),
MediaFormat = series.Library.Type.ConvertToPlusMediaFormat(series.Format),
SeriesName = series.Name,
AltSeriesName = series.LocalizedName,
AniListId = ScrobblingService.ExtractId<int?>(series.Metadata.WebLinks,

View file

@ -0,0 +1,18 @@
using System;
namespace API.Extensions;
public static class DayOfWeekHelper
{
private static readonly Random Rnd = new();
/// <summary>
/// Returns a random DayOfWeek value.
/// </summary>
/// <returns>A randomly selected DayOfWeek.</returns>
public static DayOfWeek Random()
{
var values = Enum.GetValues<DayOfWeek>();
return (DayOfWeek)values.GetValue(Rnd.Next(values.Length))!;
}
}

View file

@ -12,8 +12,10 @@ using Microsoft.EntityFrameworkCore;
namespace API.Helpers;
#nullable enable
public static class GenreHelper
{
public static async Task UpdateChapterGenres(Chapter chapter, IEnumerable<string> genreNames, IUnitOfWork unitOfWork)
{
// Normalize genre names once and store them in a hash set for quick lookups

40
API/Helpers/JwtHelper.cs Normal file
View file

@ -0,0 +1,40 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
namespace API.Helpers;
public static class JwtHelper
{
/// <summary>
/// Extracts the expiration date from a JWT token.
/// </summary>
public static DateTime GetTokenExpiry(string jwtToken)
{
if (string.IsNullOrEmpty(jwtToken))
return DateTime.MinValue;
// Parse the JWT and extract the expiry claim
var jwtHandler = new JwtSecurityTokenHandler();
var token = jwtHandler.ReadJwtToken(jwtToken);
var exp = token.Claims.FirstOrDefault(c => c.Type == "exp")?.Value;
if (long.TryParse(exp, out var expSeconds))
{
return DateTimeOffset.FromUnixTimeSeconds(expSeconds).UtcDateTime;
}
return DateTime.MinValue;
}
/// <summary>
/// Checks if a JWT token is valid based on its expiry date.
/// </summary>
public static bool IsTokenValid(string jwtToken)
{
if (string.IsNullOrEmpty(jwtToken)) return false;
var expiry = GetTokenExpiry(jwtToken);
return expiry > DateTime.UtcNow;
}
}

View file

@ -1,24 +0,0 @@
using System;
using API.DTOs.Scrobbling;
using API.Entities.Enums;
namespace API.Helpers;
#nullable enable
public static class LibraryTypeHelper
{
public static MediaFormat GetFormat(LibraryType libraryType)
{
// TODO: Refactor this to an extension on LibraryType
return libraryType switch
{
LibraryType.Manga => MediaFormat.Manga,
LibraryType.Comic => MediaFormat.Comic,
LibraryType.LightNovel => MediaFormat.LightNovel,
LibraryType.Book => MediaFormat.LightNovel,
LibraryType.Image => MediaFormat.Manga,
LibraryType.ComicVine => MediaFormat.Comic,
_ => throw new ArgumentOutOfRangeException(nameof(libraryType), libraryType, null)
};
}
}