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

184 lines
5.3 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using RadicadeServer.DB;
using RadicadeServer.Extensions;
using System.Text.Json;
namespace RadicadeServer.Clubs;
[Route("clubs/subscription")]
[Route("clubs/subscriptions")]
[Route("api/clubs/v1/subscription")]
[Route("api/clubs/v2/subscription")]
[Route("api/clubs/v1/subscriptions")]
[Route("api/clubs/v2/subscriptions")]
public class ClubSubscriptionAPI(RecDBContext db) : Controller
{
private static readonly string[] TargetIdKeys =
{
"playerId", "PlayerId", "accountId", "AccountId", "creatorAccountId", "CreatorAccountId",
"subscriptionId", "SubscriptionId", "id", "Id", "targetPlayerId", "TargetPlayerId"
};
[HttpGet("mine/member")]
[HttpGet("my/member")]
public IActionResult GetMyMemberships() => Ok(Array.Empty<object>());
[HttpGet("my/subscriptions")]
public async Task<IActionResult> GetMySubscriptions()
{
var userId = User.GetUserId();
if (userId == null) return Ok(Array.Empty<long>());
return Ok(await PlayerSubscriptions.SubscriptionIdsAsync(db, userId.Value));
}
[HttpGet("my/subscribers")]
public async Task<IActionResult> GetMySubscribers()
{
var userId = User.GetUserId();
if (userId == null) return Ok(Array.Empty<long>());
return Ok(await PlayerSubscriptions.SubscriberIdsAsync(db, userId.Value));
}
[HttpGet("details/{accountId:long}")]
public async Task<IActionResult> GetAccountSubscriptionDetails(long accountId) => Ok(new
{
clubId = PlayerSubscriptions.PersonalClubId(accountId),
accountId,
subscriberCount = await PlayerSubscriptions.SubscriberCountAsync(db, accountId)
});
[HttpGet("details/{subscription}")]
public IActionResult GetNamedSubscriptionDetails(string subscription) => Ok(new { });
[HttpGet("subscriberCount/{accountId:long}")]
public async Task<IActionResult> GetSubscriberCount(long accountId)
=> Ok(await PlayerSubscriptions.SubscriberCountAsync(db, accountId));
[HttpGet("top/creators")]
public async Task<IActionResult> GetTopCreators() => Ok(await PlayerSubscriptions.TopCreatorsAsync(db, 100));
[HttpGet("top/creators/count")]
public async Task<IActionResult> GetTopCreatorCount()
=> Ok((await PlayerSubscriptions.TopCreatorsAsync(db, int.MaxValue)).Count);
[HttpPost("{playerId:long}"), Authorize]
public async Task<IActionResult> Subscribe(long playerId)
{
var userId = User.GetUserId();
if (userId == null) return Unauthorized();
if (playerId > 0)
await PlayerSubscriptions.SubscribeAsync(db, userId.Value, playerId);
return Ok(new
{
value = PlayerSubscriptions.PersonalClubId(playerId),
success = true,
errorId = (object?)null,
error = (object?)null
});
}
[HttpPost(""), Authorize]
public async Task<IActionResult> SubscribeBare()
{
var userId = User.GetUserId();
if (userId == null) return Unauthorized();
var playerId = await ReadTargetPlayerIdAsync();
if (playerId > 0)
await PlayerSubscriptions.SubscribeAsync(db, userId.Value, playerId);
return Ok(new
{
value = PlayerSubscriptions.PersonalClubId(playerId),
success = true,
errorId = (object?)null,
error = (object?)null
});
}
[HttpDelete("{playerId:long}"), Authorize]
[HttpPost("{playerId:long}/unsubscribe"), Authorize]
public async Task<IActionResult> Unsubscribe(long playerId)
{
var userId = User.GetUserId();
if (userId == null) return Unauthorized();
if (playerId > 0)
await PlayerSubscriptions.UnsubscribeAsync(db, userId.Value, playerId);
return Ok(new { success = true, errorId = (object?)null, error = (object?)null });
}
[HttpDelete(""), Authorize]
public async Task<IActionResult> UnsubscribeBare()
{
var userId = User.GetUserId();
if (userId == null) return Unauthorized();
var playerId = await ReadTargetPlayerIdAsync();
if (playerId > 0)
await PlayerSubscriptions.UnsubscribeAsync(db, userId.Value, playerId);
return Ok(new { success = true, errorId = (object?)null, error = (object?)null });
}
private async Task<long> ReadTargetPlayerIdAsync()
{
foreach (var key in TargetIdKeys)
{
var value = Request.Query[key].FirstOrDefault();
if (long.TryParse(value, out var fromQuery) && fromQuery > 0) return fromQuery;
}
if (Request.HasFormContentType)
{
var form = await Request.ReadFormAsync();
foreach (var key in TargetIdKeys)
{
var value = form[key].FirstOrDefault();
if (long.TryParse(value, out var fromForm) && fromForm > 0) return fromForm;
}
return 0;
}
if (Request.ContentLength is not > 0) return 0;
try
{
Request.EnableBuffering();
using var reader = new StreamReader(Request.Body, leaveOpen: true);
var body = await reader.ReadToEndAsync();
if (Request.Body.CanSeek) Request.Body.Position = 0;
if (string.IsNullOrWhiteSpace(body)) return 0;
var trimmed = body.Trim();
if (trimmed.StartsWith("{"))
{
using var document = JsonDocument.Parse(trimmed);
if (document.RootElement.ValueKind == JsonValueKind.Object)
{
foreach (var property in document.RootElement.EnumerateObject())
{
if (!TargetIdKeys.Any(key => key.Equals(property.Name, StringComparison.OrdinalIgnoreCase))) continue;
if (long.TryParse(property.Value.ToString(), out var fromBody) && fromBody > 0) return fromBody;
}
}
}
else if (long.TryParse(trimmed, out var fromRaw) && fromRaw > 0)
{
return fromRaw;
}
}
catch
{
}
return 0;
}
}