Files
VORTEX-REC-LEAK/Controllers/Api/RelationshipsController.cs
T
2026-07-23 18:21:43 -07:00

365 lines
13 KiB
C#

using DeluxeBackend.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Numerics;
using DeluxeBackend.Models;
using System.Security.Claims;
using static DeluxeBackend.Enums;
namespace DeluxeBackend.Controllers.Api
{
[Route("api/relationships")]
[ApiController]
public class RelationshipsController : ControllerBase//this is from KittyRec https://git.tabbycluster.net/KittyRec/KittyRec-Api/src/branch/main/Controllers/relationshipsController.cs
{
private readonly ILiteDbService db;
private readonly IJwtService jwt;
private readonly INotificationService ws;
private readonly IMessageService messageService;
public RelationshipsController(ILiteDbService _db, IJwtService _jwt, INotificationService _ws, IMessageService _messageService)
{
db = _db;
jwt = _jwt;
ws = _ws;
messageService = _messageService;
}
private long? GetCurrentPlayerId()
{
string? raw = User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? User.FindFirst("sub")?.Value;
if (long.TryParse(raw, out long id)) return id;
return null;
}
private Relationship? GetRelationship(long playerId, long targetId) =>
db.Relationships
.Include(x => x.Player)
.Include(x => x.TargetPlayer)
.FindOne(x => x.Player.Id == playerId && x.TargetPlayer.Id == targetId);
private Relationship GetOrCreate(long playerId, long targetId)
{
var rel = GetRelationship(playerId, targetId);
if (rel != null) return rel;
rel = new Relationship
{
Player = db.Accounts.FindById(playerId),
TargetPlayer = db.Accounts.FindById(targetId)
};
db.Relationships.Insert(rel);
return rel;
}
private async Task PushRelToPlayer(long toPlayerId, long aboutPlayerId)
{
var rel = GetRelationship(toPlayerId, aboutPlayerId);
await ws.SendToPlayer(toPlayerId, PushNotification.RelationshipChanged, new Dictionary<string, object>
{
["PlayerID"] = aboutPlayerId,
["RelationshipType"] = (int)(rel?.RelationshipType ?? RelationshipType.None),
["Muted"] = (int)(rel?.Muted ?? MuteState.None),
["Ignored"] = (int)(rel?.Ignored ?? IgnoreState.None),
["Favorited"] = rel?.Favorited ?? 0
});
}
private void DeleteFriendInvites(long fromPlayerId, long toPlayerId)
{
var messageToDelete = db.Messages.FindOne(m =>
m.FromPlayer.Id == fromPlayerId &&
m.Player.Id == toPlayerId &&
m.Type == MessageType.FriendInvite);
if (messageToDelete != null)
{
db.Messages.Delete(messageToDelete.Id);
ws.SendToPlayer(toPlayerId, PushNotification.MessageDeleted, new Dictionary<string, object>
{
["Id"] = messageToDelete.Id
});
}
}
[HttpGet("v2/get")]
[Authorize]
public async Task<IActionResult> get()
{
long? pid = GetCurrentPlayerId();
if (pid == null) return Unauthorized();
var rels = db.Relationships
.Query()
.Include(x => x.Player)
.Include(x => x.TargetPlayer)
.Where(x => x.Player.Id == pid.Value)
.ToList()
.Select(r => r.ToDictionary())
.ToList();
return Ok(rels);
}
[HttpGet("v2/sendfriendrequest")]
[Authorize]
public async Task<IActionResult> SendFriendRequest([FromQuery] long id = 0)
{
long? pid = GetCurrentPlayerId();
if (pid == null) return Unauthorized();
if (id == 0 || id == pid || db.Accounts.FindById(id) == null)
return Ok();
var myRel = GetOrCreate(pid.Value, id);
var theirRel = GetOrCreate(id, pid.Value);
if (myRel.RelationshipType == RelationshipType.Friend)
return Ok();
// they already sent us one — auto-accept both sides
if (theirRel.RelationshipType == RelationshipType.Sent || myRel.RelationshipType == RelationshipType.Received)
{
myRel.RelationshipType = RelationshipType.Friend;
theirRel.RelationshipType = RelationshipType.Friend;
db.Relationships.Update(myRel);
db.Relationships.Update(theirRel);
DeleteFriendInvites(pid.Value, id);
Account me = db.Accounts.FindById(pid.Value);
Account them = db.Accounts.FindById(id);
await messageService.SendMessage(me, them, MessageType.FriendRequestAccepted, pid.Value.ToString());
await PushRelToPlayer(id, pid.Value);
await PushRelToPlayer(pid.Value, id);
return Ok();
}
// new outgoing request
myRel.RelationshipType = RelationshipType.Sent;
theirRel.RelationshipType = RelationshipType.Received;
db.Relationships.Update(myRel);
db.Relationships.Update(theirRel);
DeleteFriendInvites(id, pid.Value);
Account sender = db.Accounts.FindById(pid.Value);
Account recipient = db.Accounts.FindById(id);
await messageService.SendMessage(sender, recipient, MessageType.FriendInvite, pid.Value.ToString());
await PushRelToPlayer(id, pid.Value);
await PushRelToPlayer(pid.Value, id);
return Ok(myRel.ToDictionary());
}
[HttpGet("v2/addfriend")]
[Authorize]
public async Task<IActionResult> AddFriend([FromQuery] long id = 0) =>
await SendFriendRequest(id);
[HttpGet("v2/acceptfriendrequest")]
[Authorize]
public async Task<IActionResult> AcceptFriendRequest([FromQuery] long id = 0)
{
long? pid = GetCurrentPlayerId();
if (pid == null) return Unauthorized();
if (id == 0 || id == pid)
return Ok();
var myRel = GetOrCreate(pid.Value, id);
var theirRel = GetOrCreate(id, pid.Value);
if (theirRel.RelationshipType != RelationshipType.Sent && myRel.RelationshipType != RelationshipType.Received)
return Ok();
myRel.RelationshipType = RelationshipType.Friend;
theirRel.RelationshipType = RelationshipType.Friend;
db.Relationships.Update(myRel);
db.Relationships.Update(theirRel);
DeleteFriendInvites(pid.Value, id);
Account me = db.Accounts.FindById(pid.Value);
Account them = db.Accounts.FindById(id);
await messageService.SendMessage(me, them, MessageType.FriendRequestAccepted, pid.Value.ToString());
await PushRelToPlayer(id, pid.Value);
await PushRelToPlayer(pid.Value, id);
return Ok(myRel.ToDictionary());
}
[HttpGet("v2/removefriend")]
[Authorize]
public async Task<IActionResult> RemoveFriend([FromQuery] long id = 0)
{
long? pid = GetCurrentPlayerId();
if (pid == null) return Unauthorized();
if (id != 0 && id != pid)
{
var myRel = GetRelationship(pid.Value, id);
var theirRel = GetRelationship(id, pid.Value);
if (myRel != null) { myRel.RelationshipType = RelationshipType.None; db.Relationships.Update(myRel); }
if (theirRel != null) { theirRel.RelationshipType = RelationshipType.None; db.Relationships.Update(theirRel); }
DeleteFriendInvites(pid.Value, id);
DeleteFriendInvites(id, pid.Value);
await PushRelToPlayer(id, pid.Value);
await PushRelToPlayer(pid.Value, id);
Dictionary<string, object> gg = new()
{
["PlayerID"] = pid,
["RelationshipType"] = (int)(myRel?.RelationshipType ?? RelationshipType.None),
["Muted"] = (int)(myRel?.Muted ?? MuteState.None),
["Ignored"] = (int)(myRel?.Ignored ?? IgnoreState.None),
["Favorited"] = myRel?.Favorited ?? 0
};
return Ok(gg);
}
return Ok();
}
[HttpGet("v1/favorite")]
[Authorize]
public async Task<IActionResult> Favorite([FromQuery] long id = 0)
{
long? pid = GetCurrentPlayerId();
if (pid == null) return Unauthorized();
if (id != 0 && id != pid)
{
var rel = GetOrCreate(pid.Value, id);
rel.Favorited = 1;
db.Relationships.Update(rel);
return Ok(rel.ToDictionary());
}
return Ok();
}
[HttpGet("v1/unfavorite")]
[Authorize]
public async Task<IActionResult> Unfavorite([FromQuery] long id = 0)
{
long? pid = GetCurrentPlayerId();
if (pid == null) return Unauthorized();
if (id != 0 && id != pid)
{
var rel = GetOrCreate(pid.Value, id);
rel.Favorited = 0;
db.Relationships.Update(rel);
return Ok(rel.ToDictionary());
}
return Ok();
}
[HttpPost("v1/mute")]
[Authorize]
public async Task<IActionResult> Mute([FromForm(Name = "PlayerId"), Required] long playerId)
{
long? pid = GetCurrentPlayerId();
if (pid == null) return Unauthorized();
if (playerId == 0 || playerId == pid)
return Ok();
var myRel = GetOrCreate(pid.Value, playerId);
var theirRel = GetOrCreate(playerId, pid.Value);
myRel.Muted = MuteState.Local;
theirRel.Muted = MuteState.Remote;
db.Relationships.Update(myRel);
db.Relationships.Update(theirRel);
await PushRelToPlayer(pid.Value, playerId);
await PushRelToPlayer(playerId, pid.Value);
return Ok(myRel.ToDictionary());
}
[HttpPost("v1/unmute")]
[Authorize]
public async Task<IActionResult> Unmute([FromForm(Name = "PlayerId"), Required] long playerId)
{
long? pid = GetCurrentPlayerId();
if (pid == null) return Unauthorized();
if (playerId == 0 || playerId == pid)
return Ok();
var myRel = GetOrCreate(pid.Value, playerId);
var theirRel = GetOrCreate(playerId, pid.Value);
myRel.Muted = MuteState.None;
if (theirRel.Muted == MuteState.Remote) theirRel.Muted = MuteState.None;
db.Relationships.Update(myRel);
db.Relationships.Update(theirRel);
await PushRelToPlayer(pid.Value, playerId);
await PushRelToPlayer(playerId, pid.Value);
return Ok(myRel.ToDictionary());
}
[HttpPost("v1/ignore")]
[Authorize]
public async Task<IActionResult> Ignore([FromForm(Name = "PlayerId"), Required] long playerId)
{
long? pid = GetCurrentPlayerId();
if (pid == null) return Unauthorized();
if (playerId == 0 || playerId == pid)
return Ok();
var myRel = GetOrCreate(pid.Value, playerId);
var theirRel = GetOrCreate(playerId, pid.Value);
myRel.Ignored = IgnoreState.Local;
theirRel.Ignored = IgnoreState.Remote;
db.Relationships.Update(myRel);
db.Relationships.Update(theirRel);
await PushRelToPlayer(pid.Value, playerId);
await PushRelToPlayer(playerId, pid.Value);
return Ok(myRel.ToDictionary());
}
[HttpPost("v1/unignore")]
[Authorize]
public async Task<IActionResult> Unignore([FromForm(Name = "PlayerId"), Required] long playerId)
{
long? pid = GetCurrentPlayerId();
if (pid == null) return Unauthorized();
if (playerId == 0 || playerId == pid)
return Ok();
var myRel = GetOrCreate(pid.Value, playerId);
var theirRel = GetOrCreate(playerId, pid.Value);
myRel.Ignored = IgnoreState.None;
if (theirRel.Ignored == IgnoreState.Remote) theirRel.Ignored = IgnoreState.None;
db.Relationships.Update(myRel);
db.Relationships.Update(theirRel);
await PushRelToPlayer(pid.Value, playerId);
await PushRelToPlayer(playerId, pid.Value);
return Ok(myRel.ToDictionary());
}
[HttpPost("v1/bulkignoreplatformusers")]
public IActionResult BulkIgnorePlatformUsers() =>
Ok();
}
}