using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Gott.Models; using Gott.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; namespace Gott.Endpoints; public static class HistoryEndpoint { public static void MapHistoryEndpoint(this IEndpointRouteBuilder app) { app.MapGet("/api/history", HandleHistory); app.MapGet("/api/history/poll", HandlePoll); app.MapPost("/api/archive", HandleArchive); app.MapGet("/api/archives", HandleListArchives); app.MapGet("/api/archive/{archiveId}", HandleGetArchive); app.MapGet("/api/attachments/{messageId}", HandleGetAttachments); app.MapGet("/api/chains/{chainId}", HandleGetChain); } private static async Task HandleHistory(HttpContext ctx, DatabaseService db) { var sessionId = ctx.Request.Query["sessionId"].FirstOrDefault(); if (string.IsNullOrEmpty(sessionId)) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsJsonAsync(new { error = "sessionId required" }); return; } var chains = await db.GetActiveChains(sessionId); var result = new List(); foreach (var chain in chains) { var messages = await db.GetChainMessages(chain.ChainId); result.Add(new { chain, messages }); } await ctx.Response.WriteAsJsonAsync(result); } private static async Task HandlePoll(HttpContext ctx, DatabaseService db) { var sessionId = ctx.Request.Query["sessionId"].FirstOrDefault(); var afterStr = ctx.Request.Query["afterId"].FirstOrDefault(); var afterId = long.TryParse(afterStr, out var a) ? a : 0; if (string.IsNullOrEmpty(sessionId)) { ctx.Response.StatusCode = 400; return; } var messages = await db.GetActiveMessagesAfterId(sessionId, afterId); await ctx.Response.WriteAsJsonAsync(messages); } private static async Task HandleArchive(HttpContext ctx, DatabaseService db) { var sessionId = ctx.Request.Query["sessionId"].FirstOrDefault(); if (string.IsNullOrEmpty(sessionId)) { ctx.Response.StatusCode = 400; return; } var archive = await db.CreateArchive(sessionId); if (archive == null) { ctx.Response.StatusCode = 204; return; } await ctx.Response.WriteAsJsonAsync(archive); } private static async Task HandleListArchives(HttpContext ctx, DatabaseService db) { var sessionId = ctx.Request.Query["sessionId"].FirstOrDefault(); if (string.IsNullOrEmpty(sessionId)) { ctx.Response.StatusCode = 400; return; } var archives = await db.GetArchives(sessionId); await ctx.Response.WriteAsJsonAsync(archives); } private static async Task HandleGetAttachments(HttpContext ctx, DatabaseService db) { var messageIdStr = ctx.Request.RouteValues["messageId"]?.ToString(); if (!long.TryParse(messageIdStr, out var messageId)) { ctx.Response.StatusCode = 400; return; } var attachments = await db.GetAttachments(messageId); // Ohne Base64-Data zurückgeben (zu groß), stattdessen als separater Download var result = new List(); foreach (var att in attachments) { result.Add(new { att.Id, att.MessageId, att.Type, att.MediaType, att.FileName, att.Data, att.CreatedAt }); } await ctx.Response.WriteAsJsonAsync(result); } private static async Task HandleGetChain(HttpContext ctx, DatabaseService db) { var chainId = ctx.Request.RouteValues["chainId"]?.ToString(); if (string.IsNullOrEmpty(chainId)) { ctx.Response.StatusCode = 400; return; } var chain = await db.GetChain(chainId); if (chain == null) { ctx.Response.StatusCode = 404; return; } await ctx.Response.WriteAsJsonAsync(chain); } private static async Task HandleGetArchive(HttpContext ctx, DatabaseService db) { var archiveId = ctx.Request.RouteValues["archiveId"]?.ToString(); if (string.IsNullOrEmpty(archiveId)) { ctx.Response.StatusCode = 400; return; } var chains = await db.GetArchiveChains(archiveId); var result = new List(); foreach (var chain in chains) { var messages = await db.GetChainMessages(chain.ChainId); result.Add(new { chain, messages }); } await ctx.Response.WriteAsJsonAsync(result); } }