From 6b5c5d0d3bae333d0d0f3407e0800c3d829be265 Mon Sep 17 00:00:00 2001 From: Kleidukos Date: Sat, 23 May 2026 16:26:25 +0200 Subject: [PATCH] Some changes and missing classes on last commit - Program.cs updated to services and init database --- OakArchive/OakArchive.csproj | 9 +---- OakArchive/Program.cs | 52 +++++++++++++++++++++++-- OakArchive/Util/PerceptualHashHelper.cs | 47 ++++++++++++++++++++++ compose.yaml | 7 ++-- 4 files changed, 101 insertions(+), 14 deletions(-) create mode 100644 OakArchive/Util/PerceptualHashHelper.cs diff --git a/OakArchive/OakArchive.csproj b/OakArchive/OakArchive.csproj index 7c977dc..9f0707a 100644 --- a/OakArchive/OakArchive.csproj +++ b/OakArchive/OakArchive.csproj @@ -14,6 +14,7 @@ + @@ -28,13 +29,7 @@ - - - - - - - + diff --git a/OakArchive/Program.cs b/OakArchive/Program.cs index 0ece349..e76c8b1 100644 --- a/OakArchive/Program.cs +++ b/OakArchive/Program.cs @@ -1,21 +1,67 @@ +using Microsoft.EntityFrameworkCore; +using OakArchive.Database; +using OakArchive.Services; + namespace OakArchive; public class Program { - public static void Main(string[] args) + public static async Task Main(string[] args) { var builder = WebApplication.CreateBuilder(args); - // Add services to the container. builder.Services.AddControllers(); + builder.Services.AddDbContext(options => + options.UseNpgsql(builder.Configuration["DefaultConnection"])); + + + builder.Services.AddMemoryCache(); // Registriert das native IMemoryCache von Microsoft + builder.Services.AddSingleton(); + + builder.Services.AddHttpClient(client => + { + client.BaseAddress = new Uri("https://api.tcgdex.net/v2/"); + client.DefaultRequestHeaders.Add("Accept", "application/json"); + }); + + builder.Services.AddScoped(); + var app = builder.Build(); - // Configure the HTTP request pipeline. + app.Lifetime.ApplicationStarted.Register(async () => + { + // Da ApplicationStarted synchron registriert, machen wir hier einen neuen asynchronen Scope auf + using var scope = app.Services.CreateScope(); + try + { + var context = scope.ServiceProvider.GetRequiredService(); + + Console.WriteLine("[INFO] Prüfe auf ausstehende Datenbank-Migrationen..."); + + // Führt alle ausstehenden Migrationen auf der PostgreSQL-Datenbank aus. + // Falls die Datenbank noch gar nicht existiert, wird sie hier automatisch erstellt! + await context.Database.MigrateAsync(); + + var updater = scope.ServiceProvider.GetRequiredService(); + + Console.WriteLine("[INFO] === Starte TCGdex Test-Sync im Hintergrund ==="); + + var result = await updater.SyncBaseDataFromTcgDex(); + + Console.WriteLine($"[INFO] === Test-Sync beendet! Neue Daten geladen: {result} ==="); + } + catch (Exception ex) + { + Console.WriteLine($"[FEHLER] !!! Fehler beim Test-Sync: {ex.Message} !!!"); + Console.WriteLine(ex.StackTrace); + } + }); app.UseAuthorization(); + app.UseStaticFiles(); app.MapControllers(); diff --git a/OakArchive/Util/PerceptualHashHelper.cs b/OakArchive/Util/PerceptualHashHelper.cs new file mode 100644 index 0000000..604ce8c --- /dev/null +++ b/OakArchive/Util/PerceptualHashHelper.cs @@ -0,0 +1,47 @@ +using CoenM.ImageHash.HashAlgorithms; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; + +namespace OakArchive.Util; + +public class PerceptualHashHelper +{ + private static readonly PerceptualHash _perceptualHash = new(); + + private const int TargetWidth = 600; + private const int TargetHeight = 840; + private const int Margin = 15; + + public static ulong GenerateHash(byte[] rawImage) + { + using var image = Image.Load(rawImage); + + image.Mutate(x => x.Resize(TargetWidth, TargetHeight)); + + return _perceptualHash.Hash(image); + } + + public static ulong GenerateHashWithMargin(byte[] rawImage) + { + using var image = Image.Load(rawImage); + + const int maxContentWidth = TargetWidth - (2 * Margin); + const int maxContentHeight = TargetHeight - (2 * Margin); + + image.Mutate(x => x.Resize(new ResizeOptions + { + Size = new Size(maxContentWidth, maxContentHeight), + Mode = ResizeMode.Max + })); + + using var canvas = new Image(TargetWidth, TargetHeight, Color.Black); + + var posX = (TargetWidth - image.Width) / 2; + var posY = (TargetHeight - image.Height) / 2; + + canvas.Mutate(x => x.DrawImage(image, new Point(posX, posY), 1f)); + + return _perceptualHash.Hash(canvas); + } +} \ No newline at end of file diff --git a/compose.yaml b/compose.yaml index d4c7bd8..7cdb608 100644 --- a/compose.yaml +++ b/compose.yaml @@ -4,13 +4,12 @@ build: context: . dockerfile: OakArchive/Dockerfile - # Falls die DB in einer anderen Datei ist, nimm depends_on raus, - # da Compose nur Services innerhalb derselben Datei überwachen kann. networks: - postgres-network environment: - # WICHTIG: Host muss der 'container_name' oder 'service_name' der DB sein - - CONNECTION_STRING=Host=OmniDB;Database=oak_db;Username=admin;Password=${DB_PASSWORD} + - DefaultConnection=Host=OmniDB;Database=oak_db;Username=admin;Password=${DB_PASSWORD} + volumes: + - C:\Users\larsh\Documents\docker\oakarchive\Cards:/app/Cards networks: postgres-network: