ProjectLighthouse/ProjectLighthouse.Servers.GameServer/Controllers/CommentController.cs
Zaprit 3fcfaaf5cc
Profile Blocking (#662)
* Added blocked user DB object

* Added user blocking functions

* Fixed DB Migration

* Updated DB Functions

* Added blocked user support to website

* Fixed DB Migration

* I forgot to save 🫠

* More migration pain

* Fixed Unblock label

* Update ProjectLighthouse.Servers.Website/Pages/UserPage.cshtml

sounds cool

Co-authored-by: koko <68549366+sudokoko@users.noreply.github.com>

* Removed unnecessary imports in database

* Removed unnecessary  imports in UserPage.cshtml.cs

* Made comments in-game respect blocked users

* Update ProjectLighthouse/Database.cs

Co-authored-by: Josh <josh@slendy.pw>

* Update ProjectLighthouse/Database.cs

Co-authored-by: Josh <josh@slendy.pw>

* DB Code cleanup

* Cleaned up userPage block detection code

* Get only the creator id in lieu of the whole object

* Fixed null condition when not logged in

* Fixed null condition when not logged in

* Potential DB Optimisation

* Apply suggestions from code review

Co-authored-by: Josh <josh@slendy.pw>

* Fix errors and null warning

* Use explicit type in lieu of var

* changed block icons

* Optimize blocked user check and save changes when unblocking

---------

Co-authored-by: koko <68549366+sudokoko@users.noreply.github.com>
Co-authored-by: Josh <josh@slendy.pw>
2023-02-11 08:25:06 +00:00

180 lines
No EOL
6.9 KiB
C#

#nullable enable
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Levels;
using LBPUnion.ProjectLighthouse.PlayerData;
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
[ApiController]
[Authorize]
[Route("LITTLEBIGPLANETPS3_XML/")]
[Produces("text/xml")]
public class CommentController : ControllerBase
{
private readonly Database database;
public CommentController(Database database)
{
this.database = database;
}
[HttpPost("rateUserComment/{username}")]
[HttpPost("rateComment/{slotType}/{slotId:int}")]
public async Task<IActionResult> RateComment([FromQuery] int commentId, [FromQuery] int rating, string? username, string? slotType, int slotId)
{
GameToken token = this.GetToken();
// Return bad request if both are true or both are false
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
bool success = await this.database.RateComment(token.UserId, commentId, rating);
if (!success) return this.BadRequest();
return this.Ok();
}
[HttpGet("comments/{slotType}/{slotId:int}")]
[HttpGet("userComments/{username}")]
public async Task<IActionResult> GetComments([FromQuery] int pageStart, [FromQuery] int pageSize, string? username, string? slotType, int slotId)
{
GameToken token = this.GetToken();
if (pageSize <= 0 || pageStart < 0) return this.BadRequest();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
int targetId;
CommentType type = username == null ? CommentType.Level : CommentType.Profile;
if (type == CommentType.Level)
{
targetId = await this.database.Slots.Where(s => s.SlotId == slotId)
.Where(s => s.CommentsEnabled && !s.Hidden)
.Select(s => s.SlotId)
.FirstOrDefaultAsync();
}
else
{
targetId = await this.database.Users.Where(u => u.Username == username)
.Where(u => u.CommentsEnabled)
.Select(u => u.UserId)
.FirstOrDefaultAsync();
}
if (targetId == 0) return this.NotFound();
List<int> blockedUsers = await (
from blockedProfile in this.database.BlockedProfiles
where blockedProfile.UserId == token.UserId
select blockedProfile.BlockedUserId
).ToListAsync();
List<Comment> comments = await this.database.Comments.Include(c => c.Poster)
.Where(c => c.TargetId == targetId && c.Type == type && !c.Poster.IsBanned)
.Where(c => !blockedUsers.Contains(c.PosterUserId))
.OrderByDescending(c => c.Timestamp)
.Skip(Math.Max(0, pageStart - 1))
.Take(Math.Min(pageSize, 30))
.ToListAsync();
string outputXml = comments.Aggregate
(string.Empty, (current, comment) => current + comment.Serialize(this.getReaction(token.UserId, comment.CommentId).Result));
return this.Ok(LbpSerializer.StringElement("comments", outputXml));
}
private async Task<int> getReaction(int userId, int commentId)
{
return await this.database.Reactions.Where(r => r.UserId == userId)
.Where(r => r.TargetId == commentId)
.Select(r => r.Rating)
.FirstOrDefaultAsync();
}
[HttpPost("postUserComment/{username}")]
[HttpPost("postComment/{slotType}/{slotId:int}")]
public async Task<IActionResult> PostComment(string? username, string? slotType, int slotId)
{
GameToken token = this.GetToken();
Comment? comment = await this.DeserializeBody<Comment>();
if (comment == null) return this.BadRequest();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
CommentType type = username == null ? CommentType.Level : CommentType.Profile;
int targetId;
if (type == CommentType.Level)
{
slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
targetId = await this.database.Slots.Where(s => s.SlotId == slotId)
.Where(s => s.CommentsEnabled && !s.Hidden)
.Select(s => s.SlotId)
.FirstOrDefaultAsync();
}
else
{
targetId = await this.database.UserIdFromUsername(username!);
}
string filteredText = CensorHelper.FilterMessage(comment.Message);
bool success = await this.database.PostComment(token.UserId, targetId, type, filteredText);
if (success) return this.Ok();
return this.BadRequest();
}
[HttpPost("deleteUserComment/{username}")]
[HttpPost("deleteComment/{slotType}/{slotId:int}")]
public async Task<IActionResult> DeleteComment([FromQuery] int commentId, string? username, string? slotType, int slotId)
{
GameToken token = this.GetToken();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
Comment? comment = await this.database.Comments.FirstOrDefaultAsync(c => c.CommentId == commentId);
if (comment == null) return this.NotFound();
if (comment.Deleted) return this.Ok();
bool canDelete;
if (comment.Type == CommentType.Profile)
{
canDelete = comment.PosterUserId == token.UserId || comment.TargetId == token.UserId;
}
else
{
if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
if (slotId != comment.TargetId) return this.BadRequest();
int slotCreator = await this.database.Slots.Where(s => s.SlotId == comment.TargetId)
.Where(s => s.CommentsEnabled)
.Select(s => s.CreatorId)
.FirstOrDefaultAsync();
// Comments are disabled or the slot doesn't have a creator
if (slotCreator == 0) return this.BadRequest();
canDelete = comment.PosterUserId == token.UserId || slotCreator == token.UserId;
}
if (!canDelete) return this.StatusCode(403, "");
comment.Deleted = true;
comment.DeletedBy = await this.database.UsernameFromGameToken(token);
comment.DeletedType = "user";
await this.database.SaveChangesAsync();
return this.Ok();
}
}