using Microsoft.AspNetCore.Mvc; using Nexus.Api.Helpers; using System.Text.RegularExpressions; namespace Nexus.Api.Controllers; [ApiController] [Route("api/v1/incidents")] public class IncidentsController : ControllerBase { [HttpGet] public async Task GetAll() { var basePath = "/mnt/workspace-iris/memory/incidents"; if (!Directory.Exists(basePath)) return Results.Ok(Array.Empty()); var incidents = new List(); foreach (var file in Directory.GetFiles(basePath, "*.md").OrderByDescending(f => f).Take(50)) { var fi = new FileInfo(file); if (fi.Length > 1_000_000) continue; var name = Path.GetFileNameWithoutExtension(file); var content = await System.IO.File.ReadAllTextAsync(file); var title = name; var titleMatch = Regex.Match(content, @"^#\s+(.+)$", RegexOptions.Multiline); if (titleMatch.Success) title = titleMatch.Groups[1].Value.Trim(); var date = (string?)null; var dateMatch = Regex.Match(name, @"^(\d{4}-\d{2}-\d{2})"); if (dateMatch.Success) date = dateMatch.Groups[1].Value; var severity = "unknown"; var severityMatch = Regex.Match(content, @"\*\*Severity:\*\*\s*(.+)$", RegexOptions.Multiline); if (severityMatch.Success) severity = severityMatch.Groups[1].Value.Trim(); var excerptEnd = content.IndexOf("\n## ", StringComparison.Ordinal); var excerpt = excerptEnd > 0 ? content[..excerptEnd].Trim() : content[..Math.Min(300, content.Length)].Trim(); if (excerpt.Length > 200) excerpt = excerpt[..200] + "\u2026"; incidents.Add(new { name = Path.GetFileName(file), title, date, severity, excerpt, size = fi.Length }); } return Results.Ok(incidents); } [HttpGet("{name}")] public async Task GetOne(string name) { var basePath = "/mnt/workspace-iris/memory/incidents"; if (!PathSecurityHelper.TryResolveSafePath(basePath, name, out var filePath)) return Results.BadRequest("Invalid filename."); if (!System.IO.File.Exists(filePath!)) { if (!name.EndsWith(".md", StringComparison.OrdinalIgnoreCase)) filePath = Path.Combine(basePath, name + ".md"); if (!System.IO.File.Exists(filePath!)) return Results.NotFound(); } var content = await System.IO.File.ReadAllTextAsync(filePath!); var fi = new FileInfo(filePath!); var fileName = Path.GetFileName(filePath!); var title = fileName; var titleMatch = Regex.Match(content, @"^#\s+(.+)$", RegexOptions.Multiline); if (titleMatch.Success) title = titleMatch.Groups[1].Value.Trim(); var date = (string?)null; var dateMatch = Regex.Match(fileName, @"^(\d{4}-\d{2}-\d{2})"); if (dateMatch.Success) date = dateMatch.Groups[1].Value; return Results.Ok(new { name = fileName, title, date, content, size = fi.Length }); } }