Files
SVSimServer/SVSim.EmulatedEntrypoint/Controllers/DownloadTimeController.cs
gamer147 ad5c9e91ae feat(download_time): stub start/end endpoints
Spec at docs/api-spec/endpoints/post-login/download_time-{start,end}.md
already documented both endpoints fully against the decompiled
Wizard/DownloadStartTask.cs and Wizard/DownloadFinishTask.cs — the
controller side was the gap.

The client fires /download_time/start before kicking off an Akamai
asset bundle download and /download_time/end on completion. Both are
pure telemetry from our perspective. When NukeIdentityOnStartup wipes
PlayerPrefs broadly (the pre-narrow loader behaviour), the client
decides it needs to download tutorial assets, calls /download_time/start,
and a 404 there surfaces as an HTTP error popup before the download
proceeds. Stubbing with empty data:{} bodies plus result_code:1 is the
documented minimum-viable response.

Acts as belt-and-suspenders against the narrow IdentityWipe (which
preserves the cache index so downloads shouldn't trigger) ever being
bypassed by a different code path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 18:04:28 -04:00

37 lines
1.8 KiB
C#

using Microsoft.AspNetCore.Mvc;
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests;
namespace SVSim.EmulatedEntrypoint.Controllers;
/// <summary>
/// /download_time/* — asset-download timing telemetry. The client fires
/// <c>POST /download_time/start</c> right before kicking off an Akamai asset bundle
/// download (<c>Wizard/DownloadStartTask.cs</c>) and <c>POST /download_time/end</c> when
/// it completes (<c>Wizard/DownloadFinishTask.cs</c>). Both are pure telemetry from our
/// perspective — we don't track download timings — but the client surfaces an HTTP error
/// dialog if either 404s, so we ack with empty <c>data: {}</c> bodies.
///
/// <para>Explicit <see cref="RouteAttribute"/> because the base controller token would
/// resolve to <c>/downloadtime</c>, missing the underscore.</para>
/// </summary>
[Route("download_time")]
public class DownloadTimeController : SVSimController
{
/// <summary>
/// Spec: <c>docs/api-spec/endpoints/post-login/download_time-start.md</c>. The client's
/// <c>DownloadStartTask.Parse</c> reads an optional <c>image_type</c> string
/// (<c>"card"</c> → CardDetail loading-screen art, <c>"still"</c> → StoryDetail, anything
/// else → default). We omit it; the client falls through to the default art.
/// </summary>
[HttpPost("start")]
public IActionResult Start([FromBody] BaseRequest request) => Ok(new { });
/// <summary>
/// Spec: <c>docs/api-spec/endpoints/post-login/download_time-end.md</c>. The client's
/// <c>DownloadFinishTask</c> doesn't override <c>Parse</c> at all — only <c>result_code</c>
/// matters. Empty data is the documented minimum-viable response.
/// </summary>
[HttpPost("end")]
public IActionResult End([FromBody] BaseRequest request) => Ok(new { });
}