using Microsoft.AspNetCore.Mvc; using RadicadeServer.DB; namespace RadicadeServer.API.Logs { [Route("gamelogs")] public class GameLogsAPI : Controller { private const int HeadChars = 400; private const long MaxAttachmentBytes = 20 * 1024 * 1024; [HttpPut("reports/{id}")] [HttpPost("reports/{id}")] public async Task UploadReport(string id) { var body = await ReadAsync(); return Ok(new { ReportId = id, Success = true }); } [HttpPut("reports/{id}/attachments/{name}")] [HttpPost("reports/{id}/attachments/{name}")] public async Task UploadAttachment(string id, string name) { var body = await ReadBytesAsync(); var path = await StoreAsync(id, name, body); return Ok(new { ReportId = id, AttachmentName = name, Size = body.Length, Success = true }); } [HttpPost("reports")] public async Task CreateReport() { var body = await ReadAsync(); var id = Guid.NewGuid().ToString(); return Ok(new { ReportId = id, Success = true }); } private async Task ReadAsync() { using var reader = new StreamReader(Request.Body); return await reader.ReadToEndAsync(); } private async Task ReadBytesAsync() { using var buffer = new MemoryStream(); var chunk = new byte[81920]; int read; while ((read = await Request.Body.ReadAsync(chunk)) > 0) { buffer.Write(chunk, 0, read); if (buffer.Length >= MaxAttachmentBytes) break; } return buffer.ToArray(); } private static async Task StoreAsync(string reportId, string name, byte[] body) { if (body.Length == 0 || body.Length > MaxAttachmentBytes) return null; try { Directory.CreateDirectory(AttachmentFolder); var path = Path.Combine(AttachmentFolder, $"{Sanitize(reportId)}-{Sanitize(name)}"); await System.IO.File.WriteAllBytesAsync(path, body); return path; } catch (Exception) { return null; } } private static string AttachmentFolder => Path.Combine(DBConfig.PrivateData, "BugReports"); private static string Sanitize(string value) { var clean = new string((value ?? string.Empty).Where(c => !Path.GetInvalidFileNameChars().Contains(c)).ToArray()); return clean.Length == 0 ? "upload" : clean; } private static string Summarize(byte[] body) { foreach (var b in body) { if (b == 0) return "(binary)"; } return Head(System.Text.Encoding.UTF8.GetString(body, 0, Math.Min(body.Length, 4096))); } private static string Head(string body) { var flat = body.Replace('\r', ' ').Replace('\n', ' ').Trim(); if (flat.Length == 0) return string.Empty; return flat.Length <= HeadChars ? flat : flat[..HeadChars] + "..."; } } }