Actions initial commit
Some checks failed
Docker Image CI / build (push) Has been cancelled

This commit is contained in:
2025-10-16 02:52:04 +02:00
parent 13fb917c5d
commit 53276e858b
36 changed files with 1013 additions and 169 deletions

View File

@@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.EntityFrameworkCore;
namespace API.Schema.ActionsContext;
[PrimaryKey("Key")]
public abstract class ActionRecord(string action, DateTime performedAt) : Identifiable
{
/// <summary>
/// Constant string that describes the performed Action
/// </summary>
[StringLength(128)]
public string Action { get; init; } = action;
/// <summary>
/// UTC Time when Action was performed
/// </summary>
public DateTime PerformedAt { get; init; } = performedAt;
}

View File

@@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
using API.Schema.MangaContext;
namespace API.Schema.ActionsContext.Actions;
public sealed class ChapterDownloadedActionRecord(string action, DateTime performedAt, string chapterId) : ActionRecord(action, performedAt)
{
public ChapterDownloadedActionRecord(Chapter chapter) : this(ChapterDownloadedAction, DateTime.UtcNow, chapter.Key) { }
/// <summary>
/// Chapter that was downloaded
/// </summary>
[StringLength(64)]
public string ChapterId { get; init; } = chapterId;
public const string ChapterDownloadedAction = "Chapter.Downloaded";
}

View File

@@ -0,0 +1,12 @@
using API.Schema.ActionsContext.Actions.Generic;
using API.Schema.MangaContext;
namespace API.Schema.ActionsContext.Actions;
public sealed class ChaptersRetrievedActionRecord(string action, DateTime performedAt, string mangaId)
: ActionWithMangaRecord(action, performedAt, mangaId)
{
public ChaptersRetrievedActionRecord(Manga manga) : this(ChaptersRetrievedAction, DateTime.UtcNow, manga.Key) { }
public const string ChaptersRetrievedAction = "Manga.ChaptersRetrieved";
}

View File

@@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
using API.Schema.ActionsContext.Actions.Generic;
using API.Schema.MangaContext;
namespace API.Schema.ActionsContext.Actions;
public sealed class CoverDownloadedActionRecord(string action, DateTime performedAt, string mangaId, string filename)
: ActionWithMangaRecord(action, performedAt, mangaId)
{
public CoverDownloadedActionRecord(Manga manga, string filename) : this(CoverDownloadedAction, DateTime.UtcNow, manga.Key, filename) { }
/// <summary>
/// Filename on disk
/// </summary>
[StringLength(1024)]
public string Filename { get; init; } = filename;
public const string CoverDownloadedAction = "Manga.CoverDownloaded";
}

View File

@@ -0,0 +1,22 @@
using System.ComponentModel.DataAnnotations;
namespace API.Schema.ActionsContext.Actions;
public sealed class DataMovedActionRecord(string action, DateTime performedAt, string from, string to) : ActionRecord(action, performedAt)
{
public DataMovedActionRecord(string from, string to) : this(DataMovedAction, DateTime.UtcNow, from, to) { }
/// <summary>
/// From path
/// </summary>
[StringLength(2048)]
public string From { get; init; } = from;
/// <summary>
/// To path
/// </summary>
[StringLength(2048)]
public string To { get; init; } = to;
public const string DataMovedAction = "Tranga.DataMoved";
}

View File

@@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
using API.Schema.MangaContext;
namespace API.Schema.ActionsContext.Actions.Generic;
public abstract class ActionWithMangaRecord(string action, DateTime performedAt, string mangaId) : ActionRecord(action, performedAt)
{
protected ActionWithMangaRecord(string action, DateTime performedAt, Manga manga) : this(action, performedAt, manga.Key) { }
/// <summary>
/// <see cref="Schema.MangaContext.Manga"/> for which the cover was downloaded
/// </summary>
[StringLength(64)]
public string MangaId { get; init; } = mangaId;
}

View File

@@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
using API.Schema.ActionsContext.Actions.Generic;
using API.Schema.MangaContext;
namespace API.Schema.ActionsContext.Actions;
public sealed class LibraryMovedActionRecord(string action, DateTime performedAt, string mangaId, string fileLibraryId) : ActionWithMangaRecord(action, performedAt, mangaId)
{
public LibraryMovedActionRecord(Manga manga, FileLibrary library) : this(LibraryMovedAction, DateTime.UtcNow, manga.Key, library.Key) { }
/// <summary>
/// <see cref="Schema.MangaContext.FileLibrary"/> for which the cover was downloaded
/// </summary>
[StringLength(64)]
public string FileLibraryId { get; init; } = fileLibraryId;
public const string LibraryMovedAction = "Manga.LibraryMoved";
}

View File

@@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
using API.Schema.ActionsContext.Actions.Generic;
using API.Schema.MangaContext;
using API.Schema.MangaContext.MetadataFetchers;
namespace API.Schema.ActionsContext.Actions;
public sealed class MetadataUpdatedActionRecord(string action, DateTime performedAt, string mangaId, string metadataFetcher)
: ActionWithMangaRecord(action, performedAt, mangaId)
{
public MetadataUpdatedActionRecord(Manga manga, MetadataFetcher fetcher) : this(MetadataUpdatedAction, DateTime.UtcNow, manga.Key, fetcher.Name) { }
/// <summary>
/// Filename on disk
/// </summary>
[StringLength(1024)]
public string MetadataFetcher { get; init; } = metadataFetcher;
public const string MetadataUpdatedAction = "Manga.MetadataUpdated";
}

View File

@@ -0,0 +1,8 @@
namespace API.Schema.ActionsContext.Actions;
public sealed class StartupActionRecord(string action, DateTime performedAt) : ActionRecord(action, performedAt)
{
public StartupActionRecord() : this(StartupAction, DateTime.UtcNow) { }
public const string StartupAction = "Tranga.Started";
}

View File

@@ -0,0 +1,22 @@
using API.Schema.ActionsContext.Actions;
using Microsoft.EntityFrameworkCore;
namespace API.Schema.ActionsContext;
public class ActionsContext(DbContextOptions<ActionsContext> options) : TrangaBaseContext<ActionsContext>(options)
{
public DbSet<ActionRecord> Actions { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ActionRecord>()
.HasDiscriminator(a => a.Action)
.HasValue<ChapterDownloadedActionRecord>(ChapterDownloadedActionRecord.ChapterDownloadedAction)
.HasValue<CoverDownloadedActionRecord>(CoverDownloadedActionRecord.CoverDownloadedAction)
.HasValue<ChaptersRetrievedActionRecord>(ChaptersRetrievedActionRecord.ChaptersRetrievedAction)
.HasValue<MetadataUpdatedActionRecord>(MetadataUpdatedActionRecord.MetadataUpdatedAction)
.HasValue<DataMovedActionRecord>(DataMovedActionRecord.DataMovedAction)
.HasValue<LibraryMovedActionRecord>(LibraryMovedActionRecord.LibraryMovedAction)
.HasValue<StartupActionRecord>(StartupActionRecord.StartupAction);
}
}