Radicade Public Code

This commit is contained in:
JogmansonReal
2026-10-16 23:33:13 -07:00
commit 55175acdf6
832 changed files with 363261 additions and 0 deletions
+278
View File
@@ -0,0 +1,278 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Text.Json.Nodes;
using RadicadeServer.API.Notifications;
using RadicadeServer.DB;
using RadicadeServer.Extensions;
using RadicadeServer.RecNet.Enums.Messages;
using RadicadeServer.RecNet.Notifications;
using RadicadeServer.RecNet.Moderation;
using RadicadeServer.RecNet.Relationships;
namespace RadicadeServer.API.Relationships.V1;
[Route("api/relationships/v1")]
public class RelationshipsV1(RecDBContext db) : Controller
{
[HttpPost("bulkignoreplatformusers")]
public IActionResult BulkIgnorePlatformUsers()
{
return Ok(Array.Empty<object>());
}
[HttpPost("~/api/relationships/sendfriendintroductions"), Authorize]
public async Task<IActionResult> SendFriendIntroductions()
{
var userId = User.GetUserId();
if (userId == null)
return Unauthorized();
var (toPlayerIds, aboutPlayerId) = await ReadIntroductionFieldsAsync();
aboutPlayerId = aboutPlayerId > 0 ? aboutPlayerId : userId.Value;
_ = toPlayerIds;
return Ok(new OkResponse { Success = true });
}
private async Task<(List<long> ToPlayerIds, long AboutPlayerId)> ReadIntroductionFieldsAsync()
{
var toPlayerIds = new List<long>();
long aboutPlayerId = 0;
void AddIds(JsonNode? node)
{
if (node is JsonValue value && long.TryParse(value.ToString(), out var single))
{
toPlayerIds.Add(single);
return;
}
if (node is not JsonArray array) return;
foreach (var entry in array)
if (long.TryParse(entry?.ToString(), out var id))
toPlayerIds.Add(id);
}
void ReadObject(JsonObject body)
{
foreach (var pair in body)
{
if (pair.Key.Equals("ToPlayerIds", StringComparison.OrdinalIgnoreCase) ||
pair.Key.Equals("PlayerIds", StringComparison.OrdinalIgnoreCase) ||
pair.Key.Equals("PlayerId", StringComparison.OrdinalIgnoreCase) ||
pair.Key.Equals("Id", StringComparison.OrdinalIgnoreCase))
AddIds(pair.Value);
else if (pair.Key.Equals("AboutPlayerId", StringComparison.OrdinalIgnoreCase) ||
pair.Key.Equals("AccountId", StringComparison.OrdinalIgnoreCase))
long.TryParse(pair.Value?.ToString(), out aboutPlayerId);
}
}
var request = Request;
if (request != null)
{
foreach (var key in new[] { "toPlayerIds", "ToPlayerIds", "playerIds", "PlayerIds", "playerId", "PlayerId", "id", "Id" })
if (request.Query.TryGetValue(key, out var query))
foreach (var raw in query)
if (long.TryParse(raw, out var queryId))
toPlayerIds.Add(queryId);
foreach (var key in new[] { "aboutPlayerId", "AboutPlayerId", "accountId", "AccountId" })
if (aboutPlayerId <= 0 && request.Query.TryGetValue(key, out var queryAbout) &&
long.TryParse(queryAbout.FirstOrDefault(), out var parsedAbout))
aboutPlayerId = parsedAbout;
if (request.ContentLength is > 0 && request.Body != null)
{
try
{
request.EnableBuffering();
var node = await JsonNode.ParseAsync(request.Body);
if (node is JsonObject bodyObject) ReadObject(bodyObject);
else AddIds(node);
request.Body.Position = 0;
}
catch
{
try { request.Body.Position = 0; } catch { }
}
}
}
return (toPlayerIds, aboutPlayerId);
}
[HttpGet("relationshipwith/{playerId:long}"), Authorize]
public async Task<IActionResult> RelationshipWith(long playerId)
{
var userId = User.GetUserId();
if (userId == null)
return Unauthorized();
var row = await db.Relationships.AsNoTracking()
.FirstOrDefaultAsync(x => x.AccountId == userId && x.PlayerId == playerId);
if (row != null)
return Ok(new Relationship(row));
return Ok(new Relationship(new RealRelationship { AccountId = (long)userId, PlayerId = playerId }));
}
[HttpGet("mutualfriends"), Authorize]
[HttpGet("~/api/relationships/mutualfriends"), Authorize]
public async Task<List<object>> MutualFriends([FromQuery] long id)
{
var userId = User.GetUserId();
if (userId == null || id <= 0 || id == userId)
return new List<object>();
var mine = await db.Relationships.AsNoTracking()
.Where(x => x.AccountId == userId && x.RelationshipType == RelationshipType.Friend)
.Select(x => x.PlayerId)
.ToListAsync();
var theirs = await db.Relationships.AsNoTracking()
.Where(x => x.AccountId == id && x.RelationshipType == RelationshipType.Friend)
.Select(x => x.PlayerId)
.ToListAsync();
var mutual = mine.Intersect(theirs).OrderBy(x => x).Take(50).ToList();
if (mutual.Count == 0)
return new List<object>();
var accounts = await db.Profiles.AsNoTracking()
.Where(p => mutual.Contains(p.accountId))
.ToDictionaryAsync(p => p.accountId);
return mutual
.Where(accounts.ContainsKey)
.Select(accountId => (object)new
{
AccountId = accountId,
Username = accounts[accountId].username,
DisplayName = accounts[accountId].displayName,
ProfileImage = accounts[accountId].profileImage ?? ""
})
.ToList();
}
[HttpGet("favorite"), Authorize]
[HttpPost("favorite"), Authorize]
[HttpGet("favorite/{id:long}"), Authorize]
[HttpPost("favorite/{id:long}"), Authorize]
public async Task<Relationship> Favorite()
=> await ToggleFlag(await ReadTargetPlayerIdAsync(), r => r.Favorited, (r, v) => r.Favorited = v, true);
[HttpGet("unfavorite"), Authorize]
[HttpPost("unfavorite"), Authorize]
[HttpGet("unfavorite/{id:long}"), Authorize]
[HttpPost("unfavorite/{id:long}"), Authorize]
public async Task<Relationship> Unfavorite()
=> await ToggleFlag(await ReadTargetPlayerIdAsync(), r => r.Favorited, (r, v) => r.Favorited = v, false);
private static readonly string[] TargetIdKeys =
{
"id", "Id", "playerId", "PlayerId", "targetPlayerId", "TargetPlayerId",
"accountId", "AccountId", "otherPlayerId", "OtherPlayerId"
};
private async Task<long> ReadTargetPlayerIdAsync()
{
var routeData = RouteData;
if (routeData != null &&
routeData.Values.TryGetValue("id", out var route) &&
long.TryParse(route?.ToString(), out var routeId) && routeId > 0)
return routeId;
var request = Request;
if (request == null) return 0;
foreach (var key in TargetIdKeys)
if (request.Query.TryGetValue(key, out var query) &&
long.TryParse(query.FirstOrDefault(), out var queryId) && queryId > 0)
return queryId;
if (request.ContentLength is > 0 && request.Body != null)
{
try
{
request.EnableBuffering();
if (await JsonNode.ParseAsync(request.Body) is JsonObject body)
foreach (var pair in body)
if (TargetIdKeys.Contains(pair.Key, StringComparer.OrdinalIgnoreCase) &&
long.TryParse(pair.Value?.ToString(), out var bodyId) && bodyId > 0)
{
request.Body.Position = 0;
return bodyId;
}
request.Body.Position = 0;
}
catch
{
try { request.Body.Position = 0; } catch { }
}
}
if (request.HasFormContentType)
{
var form = await request.ReadFormAsync();
foreach (var key in TargetIdKeys)
if (form.TryGetValue(key, out var formValue) &&
long.TryParse(formValue.FirstOrDefault(), out var formId) && formId > 0)
return formId;
}
return 0;
}
[HttpPost("mute"), Authorize]
[HttpPost("mute/{id:long}"), Authorize]
[HttpGet("mute"), Authorize]
[HttpGet("mute/{id:long}"), Authorize]
public async Task<IActionResult> Mute()
=> await ToggleFlagActionResult(await ReadTargetPlayerIdAsync(), r => r.Muted, (r, v) => r.Muted = v, true);
[HttpPost("unmute"), Authorize]
[HttpPost("unmute/{id:long}"), Authorize]
[HttpGet("unmute"), Authorize]
[HttpGet("unmute/{id:long}"), Authorize]
public async Task<IActionResult> Unmute()
=> await ToggleFlagActionResult(await ReadTargetPlayerIdAsync(), r => r.Muted, (r, v) => r.Muted = v, false);
[HttpPost("ignore"), Authorize]
[HttpPost("ignore/{id:long}"), Authorize]
[HttpGet("ignore"), Authorize]
[HttpGet("ignore/{id:long}"), Authorize]
public async Task<IActionResult> Ignore()
=> await ToggleFlagActionResult(await ReadTargetPlayerIdAsync(), r => r.Ignored, (r, v) => r.Ignored = v, true);
[HttpPost("unignore"), Authorize]
[HttpPost("unignore/{id:long}"), Authorize]
[HttpGet("unignore"), Authorize]
[HttpGet("unignore/{id:long}"), Authorize]
public async Task<IActionResult> Unignore()
=> await ToggleFlagActionResult(await ReadTargetPlayerIdAsync(), r => r.Ignored, (r, v) => r.Ignored = v, false);
private async Task<Relationship> ToggleFlag(long id, Func<RealRelationship, ReciprocalStatus> getter, Action<RealRelationship, ReciprocalStatus> setter, bool enabling)
{
var userId = (long)User.GetUserId()!;
var mine = await RelationshipsShared.GetOrCreate(db, userId, id);
var theirs = await RelationshipsShared.GetOrCreate(db, id, userId);
RelationshipsShared.SetReciprocalStatus(mine, theirs, getter, setter, enabling);
await db.SaveChangesAsync();
await Notify.SendNotify(userId, new Notification { Id = Notifs.RelationshipChanged, Msg = new Relationship(mine) });
await Notify.SendNotify(id, new Notification { Id = Notifs.RelationshipChanged, Msg = new Relationship(theirs) });
return new Relationship(mine);
}
private async Task<IActionResult> ToggleFlagActionResult(long id, Func<RealRelationship, ReciprocalStatus> getter, Action<RealRelationship, ReciprocalStatus> setter, bool enabling)
{
if (id <= 0)
return BadRequest(new { error = "invalid player id" });
return Ok(await ToggleFlag(id, getter, setter, enabling));
}
}