From 2b521be45c22542faa04e256ffbbc98176d6a97b Mon Sep 17 00:00:00 2001 From: jvyden Date: Wed, 16 Feb 2022 20:24:57 -0500 Subject: [PATCH] Add user status api endpoint --- .../Controllers/Api/UserEndpoints.cs | 20 +++++++++ .../Controllers/GameApi/CommentController.cs | 23 +++++----- .../Types/ApiEndpointController.cs | 2 +- .../Types/Profiles/StatusType.cs | 7 ++++ .../Types/Profiles/UserStatus.cs | 42 +++++++++++++++++++ ProjectLighthouse/Types/User.cs | 11 +---- 6 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 ProjectLighthouse/Types/Profiles/StatusType.cs create mode 100644 ProjectLighthouse/Types/Profiles/UserStatus.cs diff --git a/ProjectLighthouse/Controllers/Api/UserEndpoints.cs b/ProjectLighthouse/Controllers/Api/UserEndpoints.cs index 7fc505eb..63510326 100644 --- a/ProjectLighthouse/Controllers/Api/UserEndpoints.cs +++ b/ProjectLighthouse/Controllers/Api/UserEndpoints.cs @@ -1,10 +1,13 @@ #nullable enable using System.Threading.Tasks; using LBPUnion.ProjectLighthouse.Types; +using LBPUnion.ProjectLighthouse.Types.Profiles; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +// ReSharper disable RouteTemplates.ActionRoutePrefixCanBeExtractedToControllerRoute + namespace LBPUnion.ProjectLighthouse.Controllers.Api; /// @@ -36,4 +39,21 @@ public class UserEndpoints : ApiEndpointController return this.Ok(user); } + + /// + /// Gets a user and their information from the database. + /// + /// The ID of the user + /// The user's status + /// The user's status, if successful. + /// The user could not be found. + [HttpGet("user/{id:int}/status")] + [ProducesResponseType(typeof(UserStatus), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetUserStatus(int id) + { + UserStatus userStatus = new(this.database, id); + + return this.Ok(userStatus); + } } \ No newline at end of file diff --git a/ProjectLighthouse/Controllers/GameApi/CommentController.cs b/ProjectLighthouse/Controllers/GameApi/CommentController.cs index cfca4f09..e2ca484c 100644 --- a/ProjectLighthouse/Controllers/GameApi/CommentController.cs +++ b/ProjectLighthouse/Controllers/GameApi/CommentController.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using System.Xml.Serialization; -using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Serialization; using LBPUnion.ProjectLighthouse.Types; using LBPUnion.ProjectLighthouse.Types.Levels; @@ -39,14 +38,13 @@ public class CommentController : ControllerBase return this.Ok(); } - [HttpGet("comments/user/{slotId:int}")] [HttpGet("userComments/{username}")] public async Task GetComments([FromQuery] int pageStart, [FromQuery] int pageSize, string? username, int? slotId) { User? user = await this.database.UserFromGameRequest(this.Request); if (user == null) return this.StatusCode(403, ""); - + int targetId = slotId.GetValueOrDefault(); CommentType type = CommentType.Level; if (!string.IsNullOrWhiteSpace(username)) @@ -55,24 +53,24 @@ public class CommentController : ControllerBase type = CommentType.Profile; } - List comments = await this.database.Comments - .Include(c => c.Poster) + List comments = await this.database.Comments.Include + (c => c.Poster) .Where(c => c.TargetId == targetId && c.Type == type) .OrderByDescending(c => c.Timestamp) .Skip(pageStart - 1) - .Take(Math.Min(pageSize, - 30)) + .Take(Math.Min(pageSize, 30)) .ToListAsync(); - string outputXml = comments.Aggregate(string.Empty, (current, comment) => current + - comment.Serialize(this.getReaction(user.UserId, comment.CommentId).Result)); + string outputXml = comments.Aggregate + (string.Empty, (current, comment) => current + comment.Serialize(this.getReaction(user.UserId, comment.CommentId).Result)); return this.Ok(LbpSerializer.StringElement("comments", outputXml)); } - public async Task getReaction(int userId, int commentId) + private async Task getReaction(int userId, int commentId) { Reaction? reaction = await this.database.Reactions.FirstOrDefaultAsync(r => r.UserId == userId && r.TargetId == commentId); if (reaction == null) return 0; + return reaction.Rating; } @@ -80,11 +78,11 @@ public class CommentController : ControllerBase [HttpPost("postComment/user/{slotId:int}")] public async Task PostComment(string? username, int? slotId) { - this.Request.Body.Position = 0; + this.Request.Body.Position = 0; string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync(); XmlSerializer serializer = new(typeof(Comment)); - Comment? comment = (Comment?) serializer.Deserialize(new StringReader(bodyString)); + Comment? comment = (Comment?)serializer.Deserialize(new StringReader(bodyString)); CommentType type = (slotId.GetValueOrDefault() == 0 ? CommentType.Profile : CommentType.Level); @@ -112,6 +110,7 @@ public class CommentController : ControllerBase Comment? comment = await this.database.Comments.FirstOrDefaultAsync(c => c.CommentId == commentId); if (comment == null) return this.NotFound(); + // if you are not the poster if (comment.PosterUserId != user.UserId) { diff --git a/ProjectLighthouse/Types/ApiEndpointController.cs b/ProjectLighthouse/Types/ApiEndpointController.cs index e026df83..7a717cab 100644 --- a/ProjectLighthouse/Types/ApiEndpointController.cs +++ b/ProjectLighthouse/Types/ApiEndpointController.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Mvc; namespace LBPUnion.ProjectLighthouse.Types; [ApiController] -[Route("/api/v1/")] +[Route("/api/v1")] [Produces("application/json")] public class ApiEndpointController : ControllerBase {} \ No newline at end of file diff --git a/ProjectLighthouse/Types/Profiles/StatusType.cs b/ProjectLighthouse/Types/Profiles/StatusType.cs new file mode 100644 index 00000000..ea7d99a6 --- /dev/null +++ b/ProjectLighthouse/Types/Profiles/StatusType.cs @@ -0,0 +1,7 @@ +namespace LBPUnion.ProjectLighthouse.Types.Profiles; + +public enum StatusType +{ + Offline = 0, + Online = 1, +} \ No newline at end of file diff --git a/ProjectLighthouse/Types/Profiles/UserStatus.cs b/ProjectLighthouse/Types/Profiles/UserStatus.cs new file mode 100644 index 00000000..67cde0f6 --- /dev/null +++ b/ProjectLighthouse/Types/Profiles/UserStatus.cs @@ -0,0 +1,42 @@ +#nullable enable +using System.Linq; +using LBPUnion.ProjectLighthouse.Helpers; + +namespace LBPUnion.ProjectLighthouse.Types.Profiles; + +public class UserStatus +{ + public StatusType StatusType { get; set; } + public GameVersion? CurrentVersion { get; set; } + + public UserStatus() + {} + + public UserStatus(Database database, int userId) + { + LastContact? lastContact = database.LastContacts.Where(l => l.UserId == userId).FirstOrDefault(l => TimestampHelper.Timestamp - l.Timestamp < 300); + + if (lastContact == null) + { + StatusType = StatusType.Offline; + CurrentVersion = null; + } + else + { + StatusType = StatusType.Online; + CurrentVersion = lastContact.GameVersion; + } + } + + public override string ToString() + { + CurrentVersion ??= GameVersion.Unknown; + + return this.StatusType switch + { + StatusType.Online => $"Currently online on {((GameVersion)this.CurrentVersion).ToPrettyString()}", + StatusType.Offline => "Offline", + _ => "Unknown", + }; + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Types/User.cs b/ProjectLighthouse/Types/User.cs index 7b730d49..a370aaef 100644 --- a/ProjectLighthouse/Types/User.cs +++ b/ProjectLighthouse/Types/User.cs @@ -2,7 +2,6 @@ using System.ComponentModel.DataAnnotations.Schema; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.Json.Serialization; -using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Serialization; using LBPUnion.ProjectLighthouse.Types.Profiles; using LBPUnion.ProjectLighthouse.Types.Settings; @@ -153,16 +152,10 @@ public class User #nullable enable [NotMapped] [JsonIgnore] - public string Status { + public UserStatus Status { get { using Database database = new(); - LastContact? lastMatch = database.LastContacts.Where - (l => l.UserId == this.UserId) - .FirstOrDefault(l => TimestampHelper.Timestamp - l.Timestamp < 300); - - if (lastMatch == null) return "Offline"; - - return "Currently online on " + lastMatch.GameVersion.ToPrettyString(); + return new UserStatus(database, this.UserId); } } #nullable disable