feat(guild): controller scaffolding + /guild/info baseline
- 5 common DTOs under Models/Dtos/Common/Guild/ (GuildDetailDto, GuildUserBaseDto, GuildMemberInfoDto, ChatUserDto, ChatMessageDto) - 28 per-endpoint request/response DTOs under Models/Dtos/Guild/ and Models/Dtos/GuildChat/ with full [MessagePackObject]/[Key]/ [JsonPropertyName] attribute mirrors on every property - GuildController (22 actions): /guild/info returns prod-shape with config-backed max_member_num/max_sub_leader_num/usable_stamp_list; 21 stubs return empty/default DTOs - GuildChatController (7 stubs), /guild_chat/messages stub returns wait_interval=10 per config - 29 new routing smoke test cases (100 total, all pass) - GuildWireShape literal-JSON test for GuildInfoResponse (1/1 pass) - GameConfigurationJsonbTests updated for 17th GuildConfig section - Total: 1422 tests pass, 0 errors Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
129
SVSim.EmulatedEntrypoint/Controllers/GuildController.cs
Normal file
129
SVSim.EmulatedEntrypoint/Controllers/GuildController.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SVSim.Database.Models.Config;
|
||||
using SVSim.Database.Services;
|
||||
using SVSim.Database.Services.Guild;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Common;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Guild;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Controllers;
|
||||
|
||||
/// <summary>/guild/* — 22 endpoints. See docs/api-spec/endpoints/post-login/guild-*.md.</summary>
|
||||
[Route("guild")]
|
||||
public sealed class GuildController : SVSimController
|
||||
{
|
||||
private readonly IGuildService _guild;
|
||||
private readonly IGameConfigService _configs;
|
||||
|
||||
public GuildController(IGuildService guild, IGameConfigService configs)
|
||||
{
|
||||
_guild = guild;
|
||||
_configs = configs;
|
||||
}
|
||||
|
||||
[HttpPost("info")]
|
||||
public async Task<ActionResult<GuildInfoResponse>> Info([FromBody] BaseRequest _, CancellationToken ct)
|
||||
{
|
||||
if (!TryGetViewerId(out var viewerId)) return Unauthorized();
|
||||
var cfg = _configs.Get<GuildConfig>();
|
||||
var view = await _guild.GetMyGuildAsync(viewerId, ct);
|
||||
var resp = new GuildInfoResponse
|
||||
{
|
||||
MaxMemberNum = cfg.MaxMemberNum,
|
||||
MaxSubLeaderNum = cfg.MaxSubLeaderNum,
|
||||
UsableStampList = cfg.UsableStampList.ConvertAll(i => i.ToString()),
|
||||
};
|
||||
if (view is null)
|
||||
{
|
||||
resp.GuildStatus = 0; // NOT_JOINING
|
||||
}
|
||||
else
|
||||
{
|
||||
resp.GuildStatus = 2; // JOINING — fully populated path lands in Task 7
|
||||
// Task 7 populates `Guild`, JoinRequestCount, InviteCount.
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
// ===== 21 remaining stubs — each returns the response DTO with defaults =====
|
||||
|
||||
[HttpPost("create")]
|
||||
public Task<ActionResult<EmptyResponse>> Create([FromBody] GuildCreateRequest req, CancellationToken ct) => Stub();
|
||||
|
||||
[HttpPost("breakup")]
|
||||
public Task<ActionResult<EmptyResponse>> Breakup([FromBody] BaseRequest _, CancellationToken ct) => Stub();
|
||||
|
||||
[HttpPost("update")]
|
||||
public Task<ActionResult<GuildUpdateResponse>> Update([FromBody] GuildUpdateRequest req, CancellationToken ct)
|
||||
=> Task.FromResult<ActionResult<GuildUpdateResponse>>(new GuildUpdateResponse());
|
||||
|
||||
[HttpPost("update_description")]
|
||||
public Task<ActionResult<EmptyResponse>> UpdateDescription([FromBody] GuildUpdateDescriptionRequest req, CancellationToken ct) => Stub();
|
||||
|
||||
[HttpPost("update_emblem")]
|
||||
public Task<ActionResult<GuildUpdateResponse>> UpdateEmblem([FromBody] GuildUpdateEmblemRequest req, CancellationToken ct)
|
||||
=> Task.FromResult<ActionResult<GuildUpdateResponse>>(new GuildUpdateResponse());
|
||||
|
||||
[HttpPost("search_guild")]
|
||||
public Task<ActionResult<GuildSearchGuildResponse>> SearchGuild([FromBody] GuildSearchGuildRequest req, CancellationToken ct)
|
||||
=> Task.FromResult<ActionResult<GuildSearchGuildResponse>>(new GuildSearchGuildResponse { List = new() });
|
||||
|
||||
[HttpPost("emblem_list")]
|
||||
public Task<ActionResult<GuildEmblemListResponse>> EmblemList([FromBody] BaseRequest _, CancellationToken ct)
|
||||
=> Task.FromResult<ActionResult<GuildEmblemListResponse>>(new GuildEmblemListResponse { EmblemList = new() });
|
||||
|
||||
[HttpPost("others_info")]
|
||||
public Task<ActionResult<GuildOthersInfoResponse>> OthersInfo([FromBody] GuildOthersInfoRequest req, CancellationToken ct)
|
||||
=> Task.FromResult<ActionResult<GuildOthersInfoResponse>>(new GuildOthersInfoResponse());
|
||||
|
||||
[HttpPost("friend_list")]
|
||||
public Task<ActionResult<GuildFriendListResponse>> FriendList([FromBody] BaseRequest _, CancellationToken ct)
|
||||
=> Task.FromResult<ActionResult<GuildFriendListResponse>>(new GuildFriendListResponse { Friends = new() });
|
||||
|
||||
[HttpPost("invite_user_list")]
|
||||
public Task<ActionResult<GuildInviteUserListResponse>> InviteUserList([FromBody] BaseRequest _, CancellationToken ct)
|
||||
=> Task.FromResult<ActionResult<GuildInviteUserListResponse>>(new GuildInviteUserListResponse { Users = new() });
|
||||
|
||||
[HttpPost("invited_guild_list")]
|
||||
public Task<ActionResult<GuildInvitedGuildListResponse>> InvitedGuildList([FromBody] GuildInvitedGuildListRequest req, CancellationToken ct)
|
||||
=> Task.FromResult<ActionResult<GuildInvitedGuildListResponse>>(new GuildInvitedGuildListResponse { List = new() });
|
||||
|
||||
[HttpPost("invite")]
|
||||
public Task<ActionResult<EmptyResponse>> Invite([FromBody] GuildInviteRequest req, CancellationToken ct) => Stub();
|
||||
|
||||
[HttpPost("cancel_invite")]
|
||||
public Task<ActionResult<EmptyResponse>> CancelInvite([FromBody] GuildCancelInviteRequest req, CancellationToken ct) => Stub();
|
||||
|
||||
[HttpPost("reject_invite")]
|
||||
public Task<ActionResult<EmptyResponse>> RejectInvite([FromBody] GuildRejectInviteRequest req, CancellationToken ct) => Stub();
|
||||
|
||||
[HttpPost("join")]
|
||||
public Task<ActionResult<GuildJoinResponse>> Join([FromBody] GuildJoinEndpointRequest req, CancellationToken ct)
|
||||
=> Task.FromResult<ActionResult<GuildJoinResponse>>(new GuildJoinResponse { GuildStatus = 0 });
|
||||
|
||||
[HttpPost("cancel_join_request")]
|
||||
public Task<ActionResult<EmptyResponse>> CancelJoinRequest([FromBody] GuildCancelJoinRequestRequest req, CancellationToken ct) => Stub();
|
||||
|
||||
[HttpPost("join_request_list")]
|
||||
public Task<ActionResult<GuildJoinRequestListResponse>> JoinRequestList([FromBody] GuildJoinRequestListRequest req, CancellationToken ct)
|
||||
=> Task.FromResult<ActionResult<GuildJoinRequestListResponse>>(new GuildJoinRequestListResponse { Users = new() });
|
||||
|
||||
[HttpPost("join_request_accept")]
|
||||
public Task<ActionResult<EmptyResponse>> JoinRequestAccept([FromBody] GuildJoinRequestAcceptRequest req, CancellationToken ct) => Stub();
|
||||
|
||||
[HttpPost("reject_join_request")]
|
||||
public Task<ActionResult<EmptyResponse>> RejectJoinRequest([FromBody] GuildRejectJoinRequestRequest req, CancellationToken ct) => Stub();
|
||||
|
||||
[HttpPost("leave")]
|
||||
public Task<ActionResult<EmptyResponse>> Leave([FromBody] BaseRequest _, CancellationToken ct) => Stub();
|
||||
|
||||
[HttpPost("remove")]
|
||||
public Task<ActionResult<EmptyResponse>> Remove([FromBody] GuildRemoveRequest req, CancellationToken ct) => Stub();
|
||||
|
||||
[HttpPost("change_role")]
|
||||
public Task<ActionResult<GuildChangeRoleResponse>> ChangeRole([FromBody] GuildChangeRoleRequest req, CancellationToken ct)
|
||||
=> Task.FromResult<ActionResult<GuildChangeRoleResponse>>(new GuildChangeRoleResponse { Members = new() });
|
||||
|
||||
private static Task<ActionResult<EmptyResponse>> Stub() =>
|
||||
Task.FromResult<ActionResult<EmptyResponse>>(new EmptyResponse());
|
||||
}
|
||||
Reference in New Issue
Block a user