Files
Radicade/Server/Analytics/GameLogsAPI.cs
T
2026-10-16 23:33:13 -07:00

102 lines
2.7 KiB
C#

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<IActionResult> 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<IActionResult> 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<IActionResult> CreateReport()
{
var body = await ReadAsync();
var id = Guid.NewGuid().ToString();
return Ok(new { ReportId = id, Success = true });
}
private async Task<string> ReadAsync()
{
using var reader = new StreamReader(Request.Body);
return await reader.ReadToEndAsync();
}
private async Task<byte[]> 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<string?> 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] + "...";
}
}
}