mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-08-01 17:48:41 +00:00
Refactor serialization system (#702)
* Initial work for serialization refactor * Experiment with new naming conventions * Mostly implement user and slot serialization. Still needs to be fine tuned to match original implementation Many things are left in a broken state like website features/api endpoints/lbp3 categories * Fix release building * Migrate scores, reviews, and more to new serialization system. Many things are still broken but progress is steadily being made * Fix Api responses and migrate serialization for most types * Make serialization better and fix bugs Fix recursive PrepareSerialization when recursive item is set during root item's PrepareSerialization, items, should be properly indexed in order but it's only tested to 1 level of recursion * Fix review serialization * Fix user serialization producing malformed SQL query * Remove DefaultIfEmpty query * MariaDB doesn't like double nested queries * Fix LBP1 tag counter * Implement lbp3 categories and add better deserialization handling * Implement expression tree caching to speed up reflection and write new serializer tests * Remove Game column from UserEntity and rename DatabaseContextModelSnapshot.cs back to DatabaseModelSnapshot.cs * Make UserEntity username not required * Fix recursive serialization of lists and add relevant unit tests * Actually commit the migration * Fix LocationTests to use new deserialization class * Fix comments not serializing the right author username * Replace all occurrences of StatusCode with their respective ASP.NET named result instead of StatusCode(403) everything is now in the form of Forbid() * Fix SlotBase.ConvertToEntity and LocationTests * Fix compilation error * Give Location a default value in GameUserSlot and GameUser * Reimplement stubbed website functions * Convert grief reports to new serialization system * Update DatabaseModelSnapshot and bump dotnet tool version * Remove unused directives * Fix broken type reference * Fix rated comments on website * Don't include banned users in website comments * Optimize score submission * Fix slot id calculating in in-game comment posting * Move serialization interfaces to types folder and add more documentation * Allow uploading of versus scores
This commit is contained in:
parent
307b2135a3
commit
329ab66043
248 changed files with 4993 additions and 2896 deletions
|
@ -1,4 +1,4 @@
|
|||
@model LBPUnion.ProjectLighthouse.Types.Entities.Profile.User
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Profile.UserEntity
|
||||
|
||||
<form method="post" action="/admin/user/@Model.UserId/setGrantedSlots">
|
||||
@Html.AntiForgeryToken()
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
@using System.IO
|
||||
@using LBPUnion.ProjectLighthouse.Localization
|
||||
@using LBPUnion.ProjectLighthouse.Servers.Website.Extensions
|
||||
@using LBPUnion.ProjectLighthouse.Types.Entities.Interaction
|
||||
@using LBPUnion.ProjectLighthouse.Types.Entities.Profile
|
||||
|
||||
@{
|
||||
|
@ -42,65 +43,70 @@
|
|||
<div class="ui divider"></div>
|
||||
}
|
||||
}
|
||||
|
||||
@{
|
||||
int i = 0;
|
||||
foreach (KeyValuePair<CommentEntity, RatedCommentEntity?> commentAndReaction in Model.Comments)
|
||||
{
|
||||
CommentEntity comment = commentAndReaction.Key;
|
||||
int yourThumb = commentAndReaction.Value?.Rating ?? 0;
|
||||
DateTimeOffset timestamp = DateTimeOffset.FromUnixTimeSeconds(comment.Timestamp / 1000).ToLocalTime();
|
||||
StringWriter messageWriter = new();
|
||||
HttpUtility.HtmlDecode(comment.getComment(), messageWriter);
|
||||
|
||||
@for(int i = 0; i < Model.Comments.Count; i++)
|
||||
{
|
||||
Comment comment = Model.Comments[i];
|
||||
DateTimeOffset timestamp = DateTimeOffset.FromUnixTimeSeconds(comment.Timestamp / 1000).ToLocalTime();
|
||||
StringWriter messageWriter = new();
|
||||
HttpUtility.HtmlDecode(comment.getComment(), messageWriter);
|
||||
string decodedMessage = messageWriter.ToString();
|
||||
string? url = Url.RouteUrl(ViewContext.RouteData.Values);
|
||||
if (url == null) continue;
|
||||
|
||||
string decodedMessage = messageWriter.ToString();
|
||||
string? url = Url.RouteUrl(ViewContext.RouteData.Values);
|
||||
if (url == null) continue;
|
||||
int rating = comment.ThumbsUp - comment.ThumbsDown;
|
||||
|
||||
int rating = comment.ThumbsUp - comment.ThumbsDown;
|
||||
|
||||
<div style="display: flex" id="@comment.CommentId">
|
||||
@{
|
||||
string style = "";
|
||||
if (Model.User?.UserId == comment.PosterUserId)
|
||||
{
|
||||
style = "pointer-events: none";
|
||||
<div style="display: flex" id="@comment.CommentId">
|
||||
@{
|
||||
string style = "";
|
||||
if (Model.User?.UserId == comment.PosterUserId)
|
||||
{
|
||||
style = "pointer-events: none";
|
||||
}
|
||||
}
|
||||
}
|
||||
<div class="voting" style="@(style)">
|
||||
<a href="@url/rateComment?commentId=@(comment.CommentId)&rating=@(comment.YourThumb == 1 ? 0 : 1)">
|
||||
<i class="fitted @(comment.YourThumb == 1 ? "green" : "grey") arrow up link icon" style="display: block"></i>
|
||||
</a>
|
||||
<span style="text-align: center; margin: auto; @(rating < 0 ? "margin-left: -5px" : "")">@(rating)</span>
|
||||
<a href="@url/rateComment?commentId=@(comment.CommentId)&rating=@(comment.YourThumb == -1 ? 0 : -1)">
|
||||
<i class="fitted @(comment.YourThumb == -1 ? "red" : "grey") arrow down link icon" style="display: block"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="voting" style="@(style)">
|
||||
<a href="@url/rateComment?commentId=@(comment.CommentId)&rating=@(yourThumb == 1 ? 0 : 1)">
|
||||
<i class="fitted @(yourThumb == 1 ? "green" : "grey") arrow up link icon" style="display: block"></i>
|
||||
</a>
|
||||
<span style="text-align: center; margin: auto; @(rating < 0 ? "margin-left: -5px" : "")">@(rating)</span>
|
||||
<a href="@url/rateComment?commentId=@(comment.CommentId)&rating=@(yourThumb == -1 ? 0 : -1)">
|
||||
<i class="fitted @(yourThumb == -1 ? "red" : "grey") arrow down link icon" style="display: block"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="comment">
|
||||
<b>@await comment.Poster.ToLink(Html, ViewData, language): </b>
|
||||
@if (comment.Deleted)
|
||||
{
|
||||
<i>
|
||||
<div class="comment">
|
||||
<b>@await comment.Poster.ToLink(Html, ViewData, language): </b>
|
||||
@if (comment.Deleted)
|
||||
{
|
||||
<i>
|
||||
<span>@decodedMessage</span>
|
||||
</i>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>@decodedMessage</span>
|
||||
</i>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>@decodedMessage</span>
|
||||
}
|
||||
@if (((Model.User?.IsModerator ?? false) || Model.User?.UserId == comment.PosterUserId || Model.User?.UserId == pageOwnerId) && !comment.Deleted)
|
||||
{
|
||||
<button class="ui red icon button" style="display:inline-flex; float: right" onclick="deleteComment(@comment.CommentId)">
|
||||
<i class="trash icon"></i>
|
||||
</button>
|
||||
}
|
||||
<p>
|
||||
<i>@TimeZoneInfo.ConvertTime(timestamp, timeZoneInfo).ToString("M/d/yyyy @ h:mm:ss tt")</i>
|
||||
</p>
|
||||
@if (i != Model.Comments.Count - 1)
|
||||
{
|
||||
<div class="ui divider"></div>
|
||||
}
|
||||
}
|
||||
@if (((Model.User?.IsModerator ?? false) || Model.User?.UserId == comment.PosterUserId || Model.User?.UserId == pageOwnerId) && !comment.Deleted)
|
||||
{
|
||||
<button class="ui red icon button" style="display:inline-flex; float: right" onclick="deleteComment(@comment.CommentId)">
|
||||
<i class="trash icon"></i>
|
||||
</button>
|
||||
}
|
||||
<p>
|
||||
<i>@TimeZoneInfo.ConvertTime(timestamp, timeZoneInfo).ToString("M/d/yyyy @ h:mm:ss tt")</i>
|
||||
</p>
|
||||
@if (i != Model.Comments.Count - 1)
|
||||
{
|
||||
<div class="ui divider"></div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
i++;
|
||||
}
|
||||
}
|
||||
<script>
|
||||
function deleteComment(commentId){
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<div class="ui list">
|
||||
@for(int i = 0; i < Model.Scores.Count; i++)
|
||||
{
|
||||
Score score = Model.Scores[i];
|
||||
ScoreEntity score = Model.Scores[i];
|
||||
string[] playerIds = score.PlayerIds;
|
||||
DatabaseContext database = Model.Database;
|
||||
<div class="item">
|
||||
|
@ -41,7 +41,7 @@
|
|||
<div class="list" style="padding-top: 0">
|
||||
@for (int j = 0; j < playerIds.Length; j++)
|
||||
{
|
||||
User? user = await database.Users.FirstOrDefaultAsync(u => u.Username == playerIds[j]);
|
||||
UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == playerIds[j]);
|
||||
<div class="item">
|
||||
<i class="minus icon" style="padding-top: 9px"></i>
|
||||
<div class="content" style="padding-left: 0">
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
@using LBPUnion.ProjectLighthouse.Database
|
||||
@using LBPUnion.ProjectLighthouse.Localization
|
||||
@using LBPUnion.ProjectLighthouse.Types.Users
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Profile.User
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Profile.UserEntity
|
||||
|
||||
@{
|
||||
string language = (string?)ViewData["Language"] ?? LocalizationManager.DefaultLang;
|
||||
string timeZone = (string?)ViewData["TimeZone"] ?? TimeZoneInfo.Local.Id;
|
||||
bool includeStatus = (bool?)ViewData["IncludeStatus"] ?? false;
|
||||
string userStatus = includeStatus ? Model.Status.ToTranslatedString(language, timeZone) : "";
|
||||
await using DatabaseContext database = new();
|
||||
string userStatus = includeStatus ? Model.GetStatus(database).ToTranslatedString(language, timeZone) : "";
|
||||
}
|
||||
|
||||
<a href="/user/@Model.UserId" title="@userStatus" class="user-link">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
@using LBPUnion.ProjectLighthouse.Types.Entities.Level
|
||||
@using LBPUnion.ProjectLighthouse.Types.Entities.Profile
|
||||
@using LBPUnion.ProjectLighthouse.Types.Moderation.Cases
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Moderation.ModerationCase
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Moderation.ModerationCaseEntity
|
||||
|
||||
@{
|
||||
DatabaseContext database = new();
|
||||
|
@ -62,7 +62,7 @@
|
|||
|
||||
@if (Model.Type.AffectsLevel())
|
||||
{
|
||||
Slot? slot = await Model.GetSlotAsync(database);
|
||||
SlotEntity? slot = await Model.GetSlotAsync(database);
|
||||
if (slot != null)
|
||||
{
|
||||
<p><strong>Affected level:</strong> <a href="/slot/@slot.SlotId">@slot.Name</a></p>
|
||||
|
@ -70,7 +70,7 @@
|
|||
}
|
||||
else if (Model.Type.AffectsUser())
|
||||
{
|
||||
User? user = await Model.GetUserAsync(database);
|
||||
UserEntity? user = await Model.GetUserAsync(database);
|
||||
if (user != null)
|
||||
{
|
||||
<p><strong>Affected user:</strong> <a href="/user/@user.UserId">@user.Username</a></p>
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
@using LBPUnion.ProjectLighthouse.Servers.Website.Extensions
|
||||
@using LBPUnion.ProjectLighthouse.Types.Entities.Profile
|
||||
@using LBPUnion.ProjectLighthouse.Types.Levels
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Profile.Photo
|
||||
@using LBPUnion.ProjectLighthouse.Types.Serialization
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Profile.PhotoEntity
|
||||
|
||||
@{
|
||||
string language = (string?)ViewData["Language"] ?? LocalizationManager.DefaultLang;
|
||||
|
@ -83,15 +84,17 @@
|
|||
</p>
|
||||
}
|
||||
<div id="hover-subjects-@Model.PhotoId">
|
||||
@foreach (PhotoSubject subject in Model.PhotoSubjects)
|
||||
@foreach (PhotoSubjectEntity subject in Model.PhotoSubjects)
|
||||
{
|
||||
@await subject.User.ToLink(Html, ViewData, language, timeZone)
|
||||
}
|
||||
</div>
|
||||
|
||||
@{
|
||||
PhotoSubject[] subjects = Model.PhotoSubjects.ToArray();
|
||||
foreach (PhotoSubject subject in subjects) subject.Username = subject.User.Username;
|
||||
GamePhotoSubject[] subjects = Model.PhotoSubjects.Select(GamePhotoSubject.CreateFromEntity).ToArray();
|
||||
foreach (GamePhotoSubject subject in subjects)
|
||||
{
|
||||
subject.Username = Model.PhotoSubjects.Where(ps => ps.UserId == subject.UserId).Select(ps => ps.User.Username).First();
|
||||
}
|
||||
}
|
||||
|
||||
<script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
@using LBPUnion.ProjectLighthouse.Types.Moderation.Reports
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Moderation.GriefReport
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Moderation.GriefReportEntity
|
||||
|
||||
@{
|
||||
string timeZone = (string?)ViewData["TimeZone"] ?? TimeZoneInfo.Local.Id;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
@using LBPUnion.ProjectLighthouse.Files
|
||||
@using LBPUnion.ProjectLighthouse.Helpers
|
||||
@using LBPUnion.ProjectLighthouse.Types.Entities.Level
|
||||
@using LBPUnion.ProjectLighthouse.Types.Serialization
|
||||
|
||||
@{
|
||||
bool isMobile = (bool?)ViewData["IsMobile"] ?? false;
|
||||
|
@ -30,7 +31,7 @@
|
|||
|
||||
@for(int i = 0; i < Model.Reviews.Count; i++)
|
||||
{
|
||||
Review review = Model.Reviews[i];
|
||||
ReviewEntity review = Model.Reviews[i];
|
||||
string faceHash = (review.Thumb switch {
|
||||
-1 => review.Reviewer?.BooHash,
|
||||
0 => review.Reviewer?.MehHash,
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
@using LBPUnion.ProjectLighthouse.Types.Entities.Profile
|
||||
@using LBPUnion.ProjectLighthouse.Types.Users
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Level.Slot
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Level.SlotEntity
|
||||
|
||||
@{
|
||||
User? user = (User?)ViewData["User"];
|
||||
UserEntity? user = (UserEntity?)ViewData["User"];
|
||||
|
||||
await using DatabaseContext database = new();
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
@using LBPUnion.ProjectLighthouse.Database
|
||||
@using LBPUnion.ProjectLighthouse.Localization
|
||||
@using LBPUnion.ProjectLighthouse.Types.Users
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Profile.User
|
||||
@model LBPUnion.ProjectLighthouse.Types.Entities.Profile.UserEntity
|
||||
|
||||
@{
|
||||
bool showLink = (bool?)ViewData["ShowLink"] ?? false;
|
||||
|
@ -40,14 +41,22 @@
|
|||
}
|
||||
</h1>
|
||||
}
|
||||
@{
|
||||
await using DatabaseContext context = new();
|
||||
|
||||
int hearts = Model.GetHeartCount(context);
|
||||
int comments = Model.GetCommentCount(context);
|
||||
int levels = Model.GetUsedSlotCount(context);
|
||||
int photos = Model.GetUploadedPhotoCount(context);
|
||||
}
|
||||
<span>
|
||||
<i>@Model.Status.ToTranslatedString(language, timeZone)</i>
|
||||
<i>@Model.GetStatus(context).ToTranslatedString(language, timeZone)</i>
|
||||
</span>
|
||||
<div class="cardStatsUnderTitle">
|
||||
<i class="pink heart icon" title="Hearts"></i> <span>@Model.Hearts</span>
|
||||
<i class="blue comment icon" title="Comments"></i> <span>@Model.Comments</span>
|
||||
<i class="green upload icon" title="Uploaded Levels"></i><span>@Model.UsedSlots</span>
|
||||
<i class="purple camera icon" title="Uploaded Photos"></i><span>@Model.PhotosByMe</span>
|
||||
<i class="pink heart icon" title="Hearts"></i> <span>@hearts</span>
|
||||
<i class="blue comment icon" title="Comments"></i> <span>@comments</span>
|
||||
<i class="green upload icon" title="Uploaded Levels"></i><span>@levels</span>
|
||||
<i class="purple camera icon" title="Uploaded Photos"></i><span>@photos</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
Add table
Add a link
Reference in a new issue