From bc110e2274ae89cd9083c30bba74771676de2dc3 Mon Sep 17 00:00:00 2001 From: gamer147 Date: Sat, 13 Jun 2026 08:15:29 -0400 Subject: [PATCH] feat(emblem): /emblem/favorite accept-only (persistence deferred) --- .../Controllers/EmblemController.cs | 11 ++++++ .../Requests/Emblem/EmblemFavoriteRequest.cs | 17 +++++++++ .../EmblemControllerFavoriteTests.cs | 37 +++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 SVSim.EmulatedEntrypoint/Models/Dtos/Requests/Emblem/EmblemFavoriteRequest.cs create mode 100644 SVSim.UnitTests/Controllers/EmblemControllerFavoriteTests.cs diff --git a/SVSim.EmulatedEntrypoint/Controllers/EmblemController.cs b/SVSim.EmulatedEntrypoint/Controllers/EmblemController.cs index e0fc4c50..3b5f8abd 100644 --- a/SVSim.EmulatedEntrypoint/Controllers/EmblemController.cs +++ b/SVSim.EmulatedEntrypoint/Controllers/EmblemController.cs @@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore; using SVSim.Database; using SVSim.EmulatedEntrypoint.Models.Dtos.Common; using SVSim.EmulatedEntrypoint.Models.Dtos.Requests; +using SVSim.EmulatedEntrypoint.Models.Dtos.Requests.Emblem; using SVSim.EmulatedEntrypoint.Models.Dtos.Responses.Emblem; namespace SVSim.EmulatedEntrypoint.Controllers; @@ -36,4 +37,14 @@ public class EmblemController : SVSimController .ToList(), }; } + + [HttpPost("favorite")] + public ActionResult Favorite([FromBody] EmblemFavoriteRequest _) + { + if (!TryGetViewerId(out long __)) return Unauthorized(); + // Accept-and-ack. Persisting per-viewer cosmetic favorites is deferred until + // a viewer-favorites schema lands (would also serve /sleeve/favorite + /degree/favorite + // via the shared Wizard/FavoriteTask.cs Kind enum). + return new EmptyResponse(); + } } diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/Emblem/EmblemFavoriteRequest.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/Emblem/EmblemFavoriteRequest.cs new file mode 100644 index 00000000..b24570c1 --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/Emblem/EmblemFavoriteRequest.cs @@ -0,0 +1,17 @@ +using MessagePack; +using System.Text.Json.Serialization; + +namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.Emblem; + +[MessagePackObject] +public class EmblemFavoriteRequest : BaseRequest +{ + // Spec note: ids are STRINGS on the wire, not ints. Same gotcha as /sleeve/favorite and /degree/favorite. + [JsonPropertyName("favorite_add")] + [Key("favorite_add")] + public List FavoriteAdd { get; set; } = new(); + + [JsonPropertyName("favorite_remove")] + [Key("favorite_remove")] + public List FavoriteRemove { get; set; } = new(); +} diff --git a/SVSim.UnitTests/Controllers/EmblemControllerFavoriteTests.cs b/SVSim.UnitTests/Controllers/EmblemControllerFavoriteTests.cs new file mode 100644 index 00000000..4294a434 --- /dev/null +++ b/SVSim.UnitTests/Controllers/EmblemControllerFavoriteTests.cs @@ -0,0 +1,37 @@ +using System.Net; +using System.Text; +using NUnit.Framework; +using SVSim.UnitTests.Infrastructure; + +namespace SVSim.UnitTests.Controllers; + +public class EmblemControllerFavoriteTests +{ + [Test] + public async Task Favorite_accepts_add_and_remove_lists() + { + using var factory = new SVSimTestFactory(); + long viewerId = await factory.SeedViewerAsync(tutorialState: 0); + using var client = factory.CreateAuthenticatedClient(viewerId); + + var requestJson = """{"favorite_add":["100","101"],"favorite_remove":["200"],"viewer_id":"0","steam_id":0,"steam_session_ticket":""}"""; + var response = await client.PostAsync("/emblem/favorite", + new StringContent(requestJson, Encoding.UTF8, "application/json")); + + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [Test] + public async Task Favorite_accepts_empty_lists() + { + using var factory = new SVSimTestFactory(); + long viewerId = await factory.SeedViewerAsync(tutorialState: 0); + using var client = factory.CreateAuthenticatedClient(viewerId); + + var requestJson = """{"favorite_add":[],"favorite_remove":[],"viewer_id":"0","steam_id":0,"steam_session_ticket":""}"""; + var response = await client.PostAsync("/emblem/favorite", + new StringContent(requestJson, Encoding.UTF8, "application/json")); + + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } +}