From ef907ee09dd15edd234cace57fee66843cbfbebf Mon Sep 17 00:00:00 2001 From: glax Date: Thu, 16 Oct 2025 20:28:43 +0200 Subject: [PATCH] Fix Actions that can have related chapters and manga --- API/Controllers/ActionsController.cs | 4 +-- API/Controllers/DTOs/ActionRecord.cs | 8 +++--- ....cs => 20251016182526_Actions.Designer.cs} | 28 +++++++++++-------- ...4_Actions.cs => 20251016182526_Actions.cs} | 4 +-- .../Actions/ActionsContextModelSnapshot.cs | 26 ++++++++++------- .../Actions/ChapterDownloadedActionRecord.cs | 6 ++-- .../Actions/ChaptersRetrievedActionRecord.cs | 4 +-- .../Actions/CoverDownloadedActionRecord.cs | 4 ++- .../Generic/ActionWithChapterRecord.cs | 7 ++--- .../Actions/Generic/ActionWithMangaRecord.cs | 7 ++--- .../Actions/LibraryMovedActionRecord.cs | 5 +++- .../Actions/MetadataUpdatedActionRecord.cs | 4 ++- API/Schema/ActionsContext/ActionsContext.cs | 11 ++++++++ ...DownloadChapterFromMangaconnectorWorker.cs | 2 +- API/openapi/API_v2.json | 4 +-- 15 files changed, 75 insertions(+), 49 deletions(-) rename API/Migrations/Actions/{20251016170924_Actions.Designer.cs => 20251016182526_Actions.Designer.cs} (86%) rename API/Migrations/Actions/{20251016170924_Actions.cs => 20251016182526_Actions.cs} (88%) diff --git a/API/Controllers/ActionsController.cs b/API/Controllers/ActionsController.cs index f0408df..75294cb 100644 --- a/API/Controllers/ActionsController.cs +++ b/API/Controllers/ActionsController.cs @@ -69,7 +69,7 @@ public class ActionsController(ActionsContext context) : Controller [ProducesResponseType(Status500InternalServerError)] public async Task>, InternalServerError>> GetActionsRelatedToManga(string MangaId) { - if(await context.Actions.FromSqlInterpolated($"""SELECT * FROM public."Actions" WHERE "MangaId" = {MangaId}""").ToListAsync() is not { } actions) + if(await context.Actions.FromSqlInterpolated($"""SELECT * FROM public."Actions" WHERE "MangaId" = {MangaId}""").ToListAsync(HttpContext.RequestAborted) is not { } actions) return TypedResults.InternalServerError(); return TypedResults.Ok(actions.Select(a => new ActionRecord(a))); @@ -85,7 +85,7 @@ public class ActionsController(ActionsContext context) : Controller [ProducesResponseType(Status500InternalServerError)] public async Task>, InternalServerError>> GetActionsRelatedToChapter(string ChapterId) { - if(await context.Actions.FromSqlInterpolated($"""SELECT * FROM public."Actions" WHERE "ChapterId" = {ChapterId}""").ToListAsync() is not { } actions) + if(await context.Actions.FromSqlInterpolated($"""SELECT * FROM public."Actions" WHERE "ChapterId" = {ChapterId}""").ToListAsync(HttpContext.RequestAborted) is not { } actions) return TypedResults.InternalServerError(); return TypedResults.Ok(actions.Select(a => new ActionRecord(a))); diff --git a/API/Controllers/DTOs/ActionRecord.cs b/API/Controllers/DTOs/ActionRecord.cs index 961e93b..2b0d910 100644 --- a/API/Controllers/DTOs/ActionRecord.cs +++ b/API/Controllers/DTOs/ActionRecord.cs @@ -11,8 +11,8 @@ public sealed record ActionRecord : Identifiable { Action = actionRecord.Action; PerformedAt = actionRecord.PerformedAt; - MangaId = actionRecord is ActionWithMangaRecord m ? m.MangaId : null; - ChapterId = actionRecord is ActionWithChapterRecord c ? c.ChapterId : null; + MangaId = actionRecord is IActionWithMangaRecord m ? m.MangaId : null; + ChapterId = actionRecord is IActionWithChapterRecord c ? c.ChapterId : null; } /// @@ -28,13 +28,13 @@ public sealed record ActionRecord : Identifiable public DateTime PerformedAt { get; init; } /// - /// MangaId if Record is + /// MangaId if Record is /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? MangaId { get; init; } /// - /// ChapterId if Record is + /// ChapterId if Record is /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? ChapterId { get; init; } diff --git a/API/Migrations/Actions/20251016170924_Actions.Designer.cs b/API/Migrations/Actions/20251016182526_Actions.Designer.cs similarity index 86% rename from API/Migrations/Actions/20251016170924_Actions.Designer.cs rename to API/Migrations/Actions/20251016182526_Actions.Designer.cs index 0499a95..482cf08 100644 --- a/API/Migrations/Actions/20251016170924_Actions.Designer.cs +++ b/API/Migrations/Actions/20251016182526_Actions.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace API.Migrations.Actions { [DbContext(typeof(ActionsContext))] - [Migration("20251016170924_Actions")] + [Migration("20251016182526_Actions")] partial class Actions { /// @@ -53,8 +53,14 @@ namespace API.Migrations.Actions b.Property("ChapterId") .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasColumnType("text") + .HasColumnName("ChapterId"); + + b.Property("MangaId") + .IsRequired() + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("text") + .HasColumnName("MangaId"); b.HasDiscriminator().HasValue(1); }); @@ -66,8 +72,8 @@ namespace API.Migrations.Actions b.Property("MangaId") .IsRequired() .ValueGeneratedOnUpdateSometimes() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasColumnType("text") + .HasColumnName("MangaId"); b.HasDiscriminator().HasValue(2); }); @@ -84,8 +90,8 @@ namespace API.Migrations.Actions b.Property("MangaId") .IsRequired() .ValueGeneratedOnUpdateSometimes() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasColumnType("text") + .HasColumnName("MangaId"); b.HasDiscriminator().HasValue(3); }); @@ -119,8 +125,8 @@ namespace API.Migrations.Actions b.Property("MangaId") .IsRequired() .ValueGeneratedOnUpdateSometimes() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasColumnType("text") + .HasColumnName("MangaId"); b.HasDiscriminator().HasValue(5); }); @@ -132,8 +138,8 @@ namespace API.Migrations.Actions b.Property("MangaId") .IsRequired() .ValueGeneratedOnUpdateSometimes() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasColumnType("text") + .HasColumnName("MangaId"); b.Property("MetadataFetcher") .IsRequired() diff --git a/API/Migrations/Actions/20251016170924_Actions.cs b/API/Migrations/Actions/20251016182526_Actions.cs similarity index 88% rename from API/Migrations/Actions/20251016170924_Actions.cs rename to API/Migrations/Actions/20251016182526_Actions.cs index 53ad8b9..53c9651 100644 --- a/API/Migrations/Actions/20251016170924_Actions.cs +++ b/API/Migrations/Actions/20251016182526_Actions.cs @@ -18,8 +18,8 @@ namespace API.Migrations.Actions Key = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), Action = table.Column(type: "integer", maxLength: 128, nullable: false), PerformedAt = table.Column(type: "timestamp with time zone", nullable: false), - ChapterId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), - MangaId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ChapterId = table.Column(type: "text", nullable: true), + MangaId = table.Column(type: "text", nullable: true), Filename = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), From = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), To = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), diff --git a/API/Migrations/Actions/ActionsContextModelSnapshot.cs b/API/Migrations/Actions/ActionsContextModelSnapshot.cs index 4997c96..eaf026a 100644 --- a/API/Migrations/Actions/ActionsContextModelSnapshot.cs +++ b/API/Migrations/Actions/ActionsContextModelSnapshot.cs @@ -50,8 +50,14 @@ namespace API.Migrations.Actions b.Property("ChapterId") .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasColumnType("text") + .HasColumnName("ChapterId"); + + b.Property("MangaId") + .IsRequired() + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("text") + .HasColumnName("MangaId"); b.HasDiscriminator().HasValue(1); }); @@ -63,8 +69,8 @@ namespace API.Migrations.Actions b.Property("MangaId") .IsRequired() .ValueGeneratedOnUpdateSometimes() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasColumnType("text") + .HasColumnName("MangaId"); b.HasDiscriminator().HasValue(2); }); @@ -81,8 +87,8 @@ namespace API.Migrations.Actions b.Property("MangaId") .IsRequired() .ValueGeneratedOnUpdateSometimes() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasColumnType("text") + .HasColumnName("MangaId"); b.HasDiscriminator().HasValue(3); }); @@ -116,8 +122,8 @@ namespace API.Migrations.Actions b.Property("MangaId") .IsRequired() .ValueGeneratedOnUpdateSometimes() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasColumnType("text") + .HasColumnName("MangaId"); b.HasDiscriminator().HasValue(5); }); @@ -129,8 +135,8 @@ namespace API.Migrations.Actions b.Property("MangaId") .IsRequired() .ValueGeneratedOnUpdateSometimes() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasColumnType("text") + .HasColumnName("MangaId"); b.Property("MetadataFetcher") .IsRequired() diff --git a/API/Schema/ActionsContext/Actions/ChapterDownloadedActionRecord.cs b/API/Schema/ActionsContext/Actions/ChapterDownloadedActionRecord.cs index eeef8f3..25dc5ff 100644 --- a/API/Schema/ActionsContext/Actions/ChapterDownloadedActionRecord.cs +++ b/API/Schema/ActionsContext/Actions/ChapterDownloadedActionRecord.cs @@ -3,7 +3,9 @@ using API.Schema.MangaContext; namespace API.Schema.ActionsContext.Actions; -public sealed class ChapterDownloadedActionRecord(ActionsEnum action, DateTime performedAt, string chapterId) : ActionWithChapterRecord(action, performedAt, chapterId) +public sealed class ChapterDownloadedActionRecord(ActionsEnum action, DateTime performedAt, string mangaId, string chapterId) : ActionRecord(action, performedAt), IActionWithChapterRecord, IActionWithMangaRecord { - public ChapterDownloadedActionRecord(Chapter chapter) : this(ActionsEnum.ChapterDownloaded, DateTime.UtcNow, chapter.Key) { } + public ChapterDownloadedActionRecord(Manga manga, Chapter chapter) : this(ActionsEnum.ChapterDownloaded, DateTime.UtcNow, manga.Key, chapter.Key) { } + public string ChapterId { get; init; } = chapterId; + public string MangaId { get; init; } = mangaId; } \ No newline at end of file diff --git a/API/Schema/ActionsContext/Actions/ChaptersRetrievedActionRecord.cs b/API/Schema/ActionsContext/Actions/ChaptersRetrievedActionRecord.cs index 8b70fde..8e594a8 100644 --- a/API/Schema/ActionsContext/Actions/ChaptersRetrievedActionRecord.cs +++ b/API/Schema/ActionsContext/Actions/ChaptersRetrievedActionRecord.cs @@ -4,9 +4,9 @@ using API.Schema.MangaContext; namespace API.Schema.ActionsContext.Actions; public sealed class ChaptersRetrievedActionRecord(ActionsEnum action, DateTime performedAt, string mangaId) - : ActionWithMangaRecord(action, performedAt, mangaId) + : ActionRecord(action, performedAt), IActionWithMangaRecord { public ChaptersRetrievedActionRecord(Manga manga) : this(ActionsEnum.ChaptersRetrieved, DateTime.UtcNow, manga.Key) { } - public const string ChaptersRetrievedAction = "Manga.ChaptersRetrieved"; + public string MangaId { get; init; } = mangaId; } \ No newline at end of file diff --git a/API/Schema/ActionsContext/Actions/CoverDownloadedActionRecord.cs b/API/Schema/ActionsContext/Actions/CoverDownloadedActionRecord.cs index 61c4c9c..c1a1c80 100644 --- a/API/Schema/ActionsContext/Actions/CoverDownloadedActionRecord.cs +++ b/API/Schema/ActionsContext/Actions/CoverDownloadedActionRecord.cs @@ -5,7 +5,7 @@ using API.Schema.MangaContext; namespace API.Schema.ActionsContext.Actions; public sealed class CoverDownloadedActionRecord(ActionsEnum action, DateTime performedAt, string mangaId, string filename) - : ActionWithMangaRecord(action, performedAt, mangaId) + : ActionRecord(action, performedAt), IActionWithMangaRecord { public CoverDownloadedActionRecord(Manga manga, string filename) : this(ActionsEnum.CoverDownloaded, DateTime.UtcNow, manga.Key, filename) { } @@ -14,4 +14,6 @@ public sealed class CoverDownloadedActionRecord(ActionsEnum action, DateTime per /// [StringLength(1024)] public string Filename { get; init; } = filename; + + public string MangaId { get; init; } = mangaId; } \ No newline at end of file diff --git a/API/Schema/ActionsContext/Actions/Generic/ActionWithChapterRecord.cs b/API/Schema/ActionsContext/Actions/Generic/ActionWithChapterRecord.cs index 41d84bf..b3afb92 100644 --- a/API/Schema/ActionsContext/Actions/Generic/ActionWithChapterRecord.cs +++ b/API/Schema/ActionsContext/Actions/Generic/ActionWithChapterRecord.cs @@ -1,15 +1,12 @@ using System.ComponentModel.DataAnnotations; -using API.Schema.MangaContext; namespace API.Schema.ActionsContext.Actions.Generic; -public abstract class ActionWithChapterRecord(ActionsEnum action, DateTime performedAt, string chapterId) : ActionRecord(action, performedAt) +public interface IActionWithChapterRecord { - protected ActionWithChapterRecord(ActionsEnum action, DateTime performedAt, Chapter chapter) : this(action, performedAt, chapter.Key) { } - /// /// for which the cover was downloaded /// [StringLength(64)] - public string ChapterId { get; init; } = chapterId; + public string ChapterId { get; init; } } \ No newline at end of file diff --git a/API/Schema/ActionsContext/Actions/Generic/ActionWithMangaRecord.cs b/API/Schema/ActionsContext/Actions/Generic/ActionWithMangaRecord.cs index 05a8355..e7d597e 100644 --- a/API/Schema/ActionsContext/Actions/Generic/ActionWithMangaRecord.cs +++ b/API/Schema/ActionsContext/Actions/Generic/ActionWithMangaRecord.cs @@ -1,15 +1,12 @@ using System.ComponentModel.DataAnnotations; -using API.Schema.MangaContext; namespace API.Schema.ActionsContext.Actions.Generic; -public abstract class ActionWithMangaRecord(ActionsEnum action, DateTime performedAt, string mangaId) : ActionRecord(action, performedAt) +public interface IActionWithMangaRecord { - protected ActionWithMangaRecord(ActionsEnum action, DateTime performedAt, Manga manga) : this(action, performedAt, manga.Key) { } - /// /// for which the cover was downloaded /// [StringLength(64)] - public string MangaId { get; init; } = mangaId; + public string MangaId { get; init; } } \ No newline at end of file diff --git a/API/Schema/ActionsContext/Actions/LibraryMovedActionRecord.cs b/API/Schema/ActionsContext/Actions/LibraryMovedActionRecord.cs index 6499385..c40707e 100644 --- a/API/Schema/ActionsContext/Actions/LibraryMovedActionRecord.cs +++ b/API/Schema/ActionsContext/Actions/LibraryMovedActionRecord.cs @@ -4,7 +4,8 @@ using API.Schema.MangaContext; namespace API.Schema.ActionsContext.Actions; -public sealed class LibraryMovedActionRecord(ActionsEnum action, DateTime performedAt, string mangaId, string fileLibraryId) : ActionWithMangaRecord(action, performedAt, mangaId) +public sealed class LibraryMovedActionRecord(ActionsEnum action, DateTime performedAt, string mangaId, string fileLibraryId) + : ActionRecord(action, performedAt), IActionWithMangaRecord { public LibraryMovedActionRecord(Manga manga, FileLibrary library) : this(ActionsEnum.LibraryMoved, DateTime.UtcNow, manga.Key, library.Key) { } @@ -13,4 +14,6 @@ public sealed class LibraryMovedActionRecord(ActionsEnum action, DateTime perfor /// [StringLength(64)] public string FileLibraryId { get; init; } = fileLibraryId; + + public string MangaId { get; init; } = mangaId; } \ No newline at end of file diff --git a/API/Schema/ActionsContext/Actions/MetadataUpdatedActionRecord.cs b/API/Schema/ActionsContext/Actions/MetadataUpdatedActionRecord.cs index 6b687d9..3851a7b 100644 --- a/API/Schema/ActionsContext/Actions/MetadataUpdatedActionRecord.cs +++ b/API/Schema/ActionsContext/Actions/MetadataUpdatedActionRecord.cs @@ -6,7 +6,7 @@ using API.Schema.MangaContext.MetadataFetchers; namespace API.Schema.ActionsContext.Actions; public sealed class MetadataUpdatedActionRecord(ActionsEnum action, DateTime performedAt, string mangaId, string metadataFetcher) - : ActionWithMangaRecord(action, performedAt, mangaId) + : ActionRecord(action, performedAt), IActionWithMangaRecord { public MetadataUpdatedActionRecord(Manga manga, MetadataFetcher fetcher) : this(ActionsEnum.MetadataUpdated, DateTime.UtcNow, manga.Key, fetcher.Name) { } @@ -15,4 +15,6 @@ public sealed class MetadataUpdatedActionRecord(ActionsEnum action, DateTime per /// [StringLength(1024)] public string MetadataFetcher { get; init; } = metadataFetcher; + + public string MangaId { get; init; } = mangaId; } \ No newline at end of file diff --git a/API/Schema/ActionsContext/ActionsContext.cs b/API/Schema/ActionsContext/ActionsContext.cs index 908e7a7..fde8ab4 100644 --- a/API/Schema/ActionsContext/ActionsContext.cs +++ b/API/Schema/ActionsContext/ActionsContext.cs @@ -19,5 +19,16 @@ public class ActionsContext(DbContextOptions options) : TrangaBa .HasValue(ActionsEnum.DataMoved) .HasValue(ActionsEnum.LibraryMoved) .HasValue(ActionsEnum.Startup); + + modelBuilder.Entity().Property(a => a.MangaId).HasColumnName("MangaId"); + modelBuilder.Entity().Property(a => a.ChapterId).HasColumnName("ChapterId"); + + modelBuilder.Entity().Property(a => a.MangaId).HasColumnName("MangaId"); + + modelBuilder.Entity().Property(a => a.MangaId).HasColumnName("MangaId"); + + modelBuilder.Entity().Property(a => a.MangaId).HasColumnName("MangaId"); + + modelBuilder.Entity().Property(a => a.MangaId).HasColumnName("MangaId"); } } \ No newline at end of file diff --git a/API/Workers/MangaDownloadWorkers/DownloadChapterFromMangaconnectorWorker.cs b/API/Workers/MangaDownloadWorkers/DownloadChapterFromMangaconnectorWorker.cs index ad98dcf..a8e3020 100644 --- a/API/Workers/MangaDownloadWorkers/DownloadChapterFromMangaconnectorWorker.cs +++ b/API/Workers/MangaDownloadWorkers/DownloadChapterFromMangaconnectorWorker.cs @@ -192,7 +192,7 @@ public class DownloadChapterFromMangaconnectorWorker(MangaConnectorId c Log.Debug($"Downloaded chapter {chapter}."); - ActionsContext.Actions.Add(new ChapterDownloadedActionRecord(chapter)); + ActionsContext.Actions.Add(new ChapterDownloadedActionRecord(chapter.ParentManga, chapter)); if(await ActionsContext.Sync(CancellationToken, GetType(), "Download complete") is { success: false } actionsContextException) Log.Error($"Failed to save database changes: {actionsContextException.exceptionMessage}"); diff --git a/API/openapi/API_v2.json b/API/openapi/API_v2.json index aea45a2..fc90b12 100644 --- a/API/openapi/API_v2.json +++ b/API/openapi/API_v2.json @@ -3277,12 +3277,12 @@ }, "mangaId": { "type": "string", - "description": "MangaId if Record is API.Schema.ActionsContext.Actions.Generic.ActionWithMangaRecord", + "description": "MangaId if Record is API.Schema.ActionsContext.Actions.Generic.IActionWithMangaRecord", "nullable": true }, "chapterId": { "type": "string", - "description": "ChapterId if Record is API.Schema.ActionsContext.Actions.Generic.ActionWithMangaRecord", + "description": "ChapterId if Record is API.Schema.ActionsContext.Actions.Generic.IActionWithMangaRecord", "nullable": true }, "key": {