Merge pull request #102 from LumaLivy/main

Support Level Reviews (without mucking up the main repo)
This commit is contained in:
jvyden 2021-12-11 14:27:08 -05:00 committed by GitHub
commit 1ec7bdf1f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 1537 additions and 41 deletions

8
.gitignore vendored
View file

@ -21,3 +21,11 @@ riderModule.iml
lighthouse.config.json
gitBranch.txt
gitVersion.txt
ProjectLighthouse/.vscode/tasks.json
ProjectLighthouse/.vscode/launch.json
logs/Startup.log
logs/LoggerInfo.log
logs/all.log
.vscode/tasks.json
.vscode/launch.json
.editorconfig

View file

@ -1,10 +1,17 @@
#nullable enable
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Levels;
using LBPUnion.ProjectLighthouse.Types.Reviews;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using LBPUnion.ProjectLighthouse.Serialization;
namespace LBPUnion.ProjectLighthouse.Controllers
{
@ -69,10 +76,242 @@ namespace LBPUnion.ProjectLighthouse.Controllers
ratedLevel.Rating = Math.Max(Math.Min(1, rating), -1);
Review? review = await this.database.Reviews.FirstOrDefaultAsync(r => r.SlotId == slotId && r.ReviewerId == user.UserId);
if (review != null)
{
review.Thumb = ratedLevel.Rating;
}
await this.database.SaveChangesAsync();
return this.Ok();
}
[HttpPost("postReview/user/{slotId:int}")]
public async Task<IActionResult> PostReview(int slotId)
{
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
Review? review = await this.database.Reviews.FirstOrDefaultAsync(r => r.SlotId == slotId && r.ReviewerId == user.UserId);
Review? newReview = await this.GetReviewFromBody();
if (newReview == null) return this.BadRequest();
if (review == null)
{
review = new();
review.SlotId = slotId;
review.ReviewerId = user.UserId;
review.DeletedBy = DeletedBy.None;
review.ThumbsUp = 0;
review.ThumbsDown = 0;
this.database.Reviews.Add(review);
}
review.Thumb = newReview.Thumb;
review.LabelCollection = newReview.LabelCollection;
review.Text = newReview.Text;
review.Deleted = false;
review.Timestamp = TimeHelper.UnixTimeMilliseconds();
// sometimes the game posts/updates a review rating without also calling dpadrate/user/etc (why??)
RatedLevel? ratedLevel = await this.database.RatedLevels.FirstOrDefaultAsync(r => r.SlotId == slotId && r.UserId == user.UserId);
if (ratedLevel == null)
{
ratedLevel = new RatedLevel();
ratedLevel.SlotId = slotId;
ratedLevel.UserId = user.UserId;
ratedLevel.RatingLBP1 = 0;
this.database.RatedLevels.Add(ratedLevel);
}
ratedLevel.Rating = newReview.Thumb;
await this.database.SaveChangesAsync();
return this.Ok();
}
[HttpGet("reviewsFor/user/{slotId:int}")]
public async Task<IActionResult> ReviewsFor(int slotId, [FromQuery] int pageStart = 1, [FromQuery] int pageSize = 10)
{
(User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request);
if (userAndToken == null) return this.StatusCode(403, "");
// ReSharper disable once PossibleInvalidOperationException
User user = userAndToken.Value.Item1;
GameToken gameToken = userAndToken.Value.Item2;
GameVersion gameVersion = gameToken.GameVersion;
Random rand = new();
Review? yourReview = await this.database.Reviews.FirstOrDefaultAsync(r => r.ReviewerId == user.UserId && r.SlotId == slotId && r.Slot.GameVersion <= gameVersion);
VisitedLevel? visitedLevel = await this.database.VisitedLevels.FirstOrDefaultAsync(v => v.UserId == user.UserId && v.SlotId == slotId && v.Slot.GameVersion <= gameVersion);
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slotId);
if (slot == null) return this.BadRequest();
Boolean canNowReviewLevel = slot.CreatorId != user.UserId && visitedLevel != null && yourReview == null;
if (canNowReviewLevel)
{
RatedLevel? ratedLevel = await this.database.RatedLevels.FirstOrDefaultAsync(r => r.UserId == user.UserId && r.SlotId == slotId && r.Slot.GameVersion <= gameVersion);
yourReview = new();
yourReview.ReviewerId = user.UserId;
yourReview.Reviewer = user;
yourReview.Thumb = ratedLevel?.Rating == null ? 0 : ratedLevel.Rating;
yourReview.Slot = slot;
yourReview.SlotId = slotId;
yourReview.Deleted = false;
yourReview.DeletedBy = DeletedBy.None;
yourReview.Text = "You haven't reviewed this level yet. Edit this blank review to upload one!";
yourReview.LabelCollection = "";
yourReview.Timestamp = TimeHelper.UnixTimeMilliseconds();
}
IQueryable<Review?> reviews = this.database.Reviews.Where(r => r.SlotId == slotId && r.Slot.GameVersion <= gameVersion)
.Include(r => r.Reviewer)
.Include(r => r.Slot)
.OrderByDescending(r => r.ThumbsUp)
.ThenByDescending(_ => EF.Functions.Random())
.Skip(pageStart - 1)
.Take(pageSize);
IEnumerable<Review?> prependedReviews;
if (canNowReviewLevel) // this can only be true if you have not posted a review but have visited the level
{
// prepend the fake review to the top of the list to be easily edited
prependedReviews = reviews.ToList().Prepend(yourReview);
}
else
{
prependedReviews = reviews.ToList();
}
string inner = Enumerable.Aggregate(prependedReviews, string.Empty, (current, review) =>
{
if (review == null) return current;
return current + review.Serialize();
});
string response = LbpSerializer.TaggedStringElement("reviews", inner, new Dictionary<string, object>
{
{
"hint_start", pageStart + pageSize
},
{
"hint", pageStart // not sure
},
});
return this.Ok(response);
}
[HttpGet("reviewsBy/{username}")]
public async Task<IActionResult> ReviewsBy(string username, [FromQuery] int pageStart = 1, [FromQuery] int pageSize = 10)
{
(User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request);
if (userAndToken == null) return this.StatusCode(403, "");
// ReSharper disable once PossibleInvalidOperationException
User user = userAndToken.Value.Item1;
GameToken gameToken = userAndToken.Value.Item2;
GameVersion gameVersion = gameToken.GameVersion;
IEnumerable<Review> reviews = this.database.Reviews.Where(r => r.Reviewer.Username == username && r.Slot.GameVersion <= gameVersion)
.Include(r => r.Reviewer)
.Include(r => r.Slot)
.OrderByDescending(r => r.Timestamp)
.Skip(pageStart - 1)
.Take(pageSize);
string inner = Enumerable.Aggregate(reviews, string.Empty, (current, review) =>
{
//RatedLevel? ratedLevel = this.database.RatedLevels.FirstOrDefault(r => r.SlotId == review.SlotId && r.UserId == user.UserId);
//RatedReview? ratedReview = this.database.RatedReviews.FirstOrDefault(r => r.ReviewId == review.ReviewId && r.UserId == user.UserId);
return current + review.Serialize(/*, ratedReview*/);
});
string response = LbpSerializer.TaggedStringElement("reviews", inner, new Dictionary<string, object>
{
{
"hint_start", pageStart
},
{
"hint", reviews.Last().Timestamp // Seems to be the timestamp of oldest
},
});
return this.Ok(response);
}
[HttpPost("rateReview/user/{slotId:int}/{username}")]
public async Task<IActionResult> RateReview(int slotId, string username, [FromQuery] int rating = 0)
{
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
User? reviewer = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
if (reviewer == null) return this.StatusCode(400, "");
Review? review = await this.database.Reviews.FirstOrDefaultAsync(r => r.SlotId == slotId && r.ReviewerId == reviewer.UserId);
if (review == null) return this.StatusCode(400, "");
RatedReview? ratedReview = await this.database.RatedReviews.FirstOrDefaultAsync(r => r.ReviewId == review.ReviewId && r.UserId == user.UserId);
if (ratedReview == null)
{
ratedReview = new RatedReview();
ratedReview.ReviewId = review.ReviewId;
ratedReview.UserId = user.UserId;
ratedReview.Thumb = 0;
this.database.RatedReviews.Add(ratedReview);
}
int oldThumb = ratedReview.Thumb;
ratedReview.Thumb = Math.Max(Math.Min(1, rating), -1);
if (oldThumb != ratedReview.Thumb)
{
if (oldThumb == -1) review.ThumbsDown--;
else if (oldThumb == 1) review.ThumbsUp--;
if (ratedReview.Thumb == -1) review.ThumbsDown++;
else if (ratedReview.Thumb == 1) review.ThumbsUp++;
}
await this.database.SaveChangesAsync();
return this.Ok();
}
[HttpPost("deleteReview/user/{slotId:int}/{username}")]
public async Task<IActionResult> DeleteReview(int slotId, string username)
{
User? reviewer = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
if (reviewer == null) return this.StatusCode(403, "");
Review? review = await this.database.Reviews.FirstOrDefaultAsync(r => r.SlotId == slotId && r.ReviewerId == reviewer.UserId);
if (review == null) return this.StatusCode(403, "");
review.Deleted = true;
review.DeletedBy = DeletedBy.LevelAuthor;
await this.database.SaveChangesAsync();
return this.Ok();
}
public async Task<Review?> GetReviewFromBody()
{
this.Request.Body.Position = 0;
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
XmlSerializer serializer = new(typeof(Review));
Review? review = (Review?)serializer.Deserialize(new StringReader(bodyString));
return review;
}
}
}

View file

@ -7,6 +7,7 @@ using LBPUnion.ProjectLighthouse.Logging;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Levels;
using LBPUnion.ProjectLighthouse.Types.Profiles;
using LBPUnion.ProjectLighthouse.Types.Reviews;
using LBPUnion.ProjectLighthouse.Types.Settings;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
@ -31,6 +32,8 @@ namespace LBPUnion.ProjectLighthouse
public DbSet<VisitedLevel> VisitedLevels { get; set; }
public DbSet<RatedLevel> RatedLevels { get; set; }
public DbSet<AuthenticationAttempt> AuthenticationAttempts { get; set; }
public DbSet<Review> Reviews { get; set; }
public DbSet<RatedReview> RatedReviews { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseMySql(ServerSettings.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);

View file

@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
#nullable enable
using System.Threading.Tasks;
using JetBrains.Annotations;
using Kettu;
@ -21,7 +20,7 @@ namespace LBPUnion.ProjectLighthouse.Maintenance.Commands
string password = args[1];
password = HashHelper.Sha256Hash(password);
User? user = await this._database.Users.FirstOrDefaultAsync(u => u.Username == onlineId);
if (user == null)
{

View file

@ -1,3 +1,4 @@
#nullable enable
using System;
using System.Linq;
using System.Threading.Tasks;

View file

@ -0,0 +1,837 @@
// <auto-generated />
using LBPUnion.ProjectLighthouse;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(Database))]
[Migration("20211211045823_AddLevelReviews")]
partial class AddLevelReviews
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b =>
{
b.Property<int>("AuthenticationAttemptId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("GameTokenId")
.HasColumnType("int");
b.Property<string>("IPAddress")
.HasColumnType("longtext");
b.Property<int>("Platform")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("AuthenticationAttemptId");
b.HasIndex("GameTokenId");
b.ToTable("AuthenticationAttempts");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<bool>("Approved")
.HasColumnType("tinyint(1)");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserLocation")
.HasColumnType("longtext");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("GameTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.Property<int>("HeartedProfileId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("HeartedUserId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedProfileId");
b.HasIndex("HeartedUserId");
b.HasIndex("UserId");
b.ToTable("HeartedProfiles");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.Property<int>("HeartedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("HeartedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.Property<int>("QueuedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("QueuedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("QueuedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.Property<int>("RatedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("Rating")
.HasColumnType("int");
b.Property<double>("RatingLBP1")
.HasColumnType("double");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("RatedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("RatedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.Property<int>("SlotId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AuthorLabels")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("BackgroundHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("FirstUploaded")
.HasColumnType("bigint");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<string>("IconHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("InitiallyLocked")
.HasColumnType("tinyint(1)");
b.Property<long>("LastUpdated")
.HasColumnType("bigint");
b.Property<bool>("Lbp1Only")
.HasColumnType("tinyint(1)");
b.Property<string>("LevelType")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<int>("MaximumPlayers")
.HasColumnType("int");
b.Property<int>("MinimumPlayers")
.HasColumnType("int");
b.Property<bool>("MoveRequired")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaComplete")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaUnique")
.HasColumnType("int");
b.Property<string>("ResourceCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("RootLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Shareable")
.HasColumnType("int");
b.Property<bool>("SubLevel")
.HasColumnType("tinyint(1)");
b.Property<bool>("TeamPick")
.HasColumnType("tinyint(1)");
b.HasKey("SlotId");
b.HasIndex("CreatorId");
b.HasIndex("LocationId");
b.ToTable("Slots");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.Property<int>("VisitedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("VisitedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("VisitedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.Property<int>("PhotoId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("LargeHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MediumHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PhotoSubjectCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PlanHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("SmallHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("PhotoId");
b.HasIndex("CreatorId");
b.ToTable("Photos");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.Property<int>("PhotoSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Bounds")
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("PhotoSubjectId");
b.HasIndex("UserId");
b.ToTable("PhotoSubjects");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.Property<int>("CommentId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<int>("PosterUserId")
.HasColumnType("int");
b.Property<int>("TargetUserId")
.HasColumnType("int");
b.Property<int>("ThumbsDown")
.HasColumnType("int");
b.Property<int>("ThumbsUp")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("CommentId");
b.HasIndex("PosterUserId");
b.HasIndex("TargetUserId");
b.ToTable("Comments");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastContact", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("UserId");
b.ToTable("LastContacts");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("X")
.HasColumnType("int");
b.Property<int>("Y")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.RatedReview", b =>
{
b.Property<int>("RatedReviewId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ReviewId")
.HasColumnType("int");
b.Property<int>("Thumb")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("RatedReviewId");
b.HasIndex("ReviewId");
b.HasIndex("UserId");
b.ToTable("RatedReviews");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.Review", b =>
{
b.Property<int>("ReviewId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<bool>("Deleted")
.HasColumnType("tinyint(1)");
b.Property<int>("DeletedBy")
.HasColumnType("int");
b.Property<string>("LabelCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("ReviewerId")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Thumb")
.HasColumnType("int");
b.Property<int>("ThumbsDown")
.HasColumnType("int");
b.Property<int>("ThumbsUp")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("ReviewId");
b.HasIndex("ReviewerId");
b.HasIndex("SlotId");
b.ToTable("Reviews");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.Property<int>("ScoreId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("PlayerIdCollection")
.HasColumnType("longtext");
b.Property<int>("Points")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("ScoreId");
b.HasIndex("SlotId");
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Biography")
.HasColumnType("longtext");
b.Property<string>("BooHash")
.HasColumnType("longtext");
b.Property<int>("Game")
.HasColumnType("int");
b.Property<string>("IconHash")
.HasColumnType("longtext");
b.Property<bool>("IsAdmin")
.HasColumnType("tinyint(1)");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<string>("MehHash")
.HasColumnType("longtext");
b.Property<string>("Password")
.HasColumnType("longtext");
b.Property<bool>("PasswordResetRequired")
.HasColumnType("tinyint(1)");
b.Property<string>("Pins")
.HasColumnType("longtext");
b.Property<string>("PlanetHash")
.HasColumnType("longtext");
b.Property<string>("Username")
.HasColumnType("longtext");
b.Property<string>("YayHash")
.HasColumnType("longtext");
b.HasKey("UserId");
b.HasIndex("LocationId");
b.ToTable("Users");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.WebToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("WebTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.GameToken", "GameToken")
.WithMany()
.HasForeignKey("GameTokenId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("GameToken");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
.WithMany()
.HasForeignKey("HeartedUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("HeartedUser");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
b.Navigation("Location");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
.WithMany()
.HasForeignKey("PosterUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
.WithMany()
.HasForeignKey("TargetUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Poster");
b.Navigation("Target");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.RatedReview", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Reviews.Review", "Review")
.WithMany()
.HasForeignKey("ReviewId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Review");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.Review", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Reviewer")
.WithMany()
.HasForeignKey("ReviewerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Reviewer");
b.Navigation("Slot");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Location");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,107 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
public partial class AddLevelReviews : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Reviews",
columns: table => new
{
ReviewId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ReviewerId = table.Column<int>(type: "int", nullable: false),
SlotId = table.Column<int>(type: "int", nullable: false),
Timestamp = table.Column<long>(type: "bigint", nullable: false),
LabelCollection = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Deleted = table.Column<bool>(type: "tinyint(1)", nullable: false),
DeletedBy = table.Column<int>(type: "int", nullable: false),
Text = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Thumb = table.Column<int>(type: "int", nullable: false),
ThumbsUp = table.Column<int>(type: "int", nullable: false),
ThumbsDown = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Reviews", x => x.ReviewId);
table.ForeignKey(
name: "FK_Reviews_Slots_SlotId",
column: x => x.SlotId,
principalTable: "Slots",
principalColumn: "SlotId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Reviews_Users_ReviewerId",
column: x => x.ReviewerId,
principalTable: "Users",
principalColumn: "UserId",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "RatedReviews",
columns: table => new
{
RatedReviewId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
UserId = table.Column<int>(type: "int", nullable: false),
ReviewId = table.Column<int>(type: "int", nullable: false),
Thumb = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_RatedReviews", x => x.RatedReviewId);
table.ForeignKey(
name: "FK_RatedReviews_Reviews_ReviewId",
column: x => x.ReviewId,
principalTable: "Reviews",
principalColumn: "ReviewId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_RatedReviews_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "UserId",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_RatedReviews_ReviewId",
table: "RatedReviews",
column: "ReviewId");
migrationBuilder.CreateIndex(
name: "IX_RatedReviews_UserId",
table: "RatedReviews",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_Reviews_ReviewerId",
table: "Reviews",
column: "ReviewerId");
migrationBuilder.CreateIndex(
name: "IX_Reviews_SlotId",
table: "Reviews",
column: "SlotId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "RatedReviews");
migrationBuilder.DropTable(
name: "Reviews");
}
}
}

View file

@ -439,6 +439,77 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.RatedReview", b =>
{
b.Property<int>("RatedReviewId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ReviewId")
.HasColumnType("int");
b.Property<int>("Thumb")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("RatedReviewId");
b.HasIndex("ReviewId");
b.HasIndex("UserId");
b.ToTable("RatedReviews");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.Review", b =>
{
b.Property<int>("ReviewId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<bool>("Deleted")
.HasColumnType("tinyint(1)");
b.Property<int>("DeletedBy")
.HasColumnType("int");
b.Property<string>("LabelCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("ReviewerId")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Thumb")
.HasColumnType("int");
b.Property<int>("ThumbsDown")
.HasColumnType("int");
b.Property<int>("ThumbsUp")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("ReviewId");
b.HasIndex("ReviewerId");
b.HasIndex("SlotId");
b.ToTable("Reviews");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.Property<int>("ScoreId")
@ -699,6 +770,44 @@ namespace ProjectLighthouse.Migrations
b.Navigation("Target");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.RatedReview", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Reviews.Review", "Review")
.WithMany()
.HasForeignKey("ReviewId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Review");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.Review", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Reviewer")
.WithMany()
.HasForeignKey("ReviewerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Reviewer");
b.Navigation("Slot");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")

View file

@ -12,7 +12,7 @@ namespace LBPUnion.ProjectLighthouse.Pages.ExternalAuth
public class AuthenticationPage : BaseLayout
{
public AuthenticationPage(Database database) : base(database)
{}
{ }
public List<AuthenticationAttempt> AuthenticationAttempts;

View file

@ -0,0 +1,16 @@
using System.Xml.Serialization;
namespace LBPUnion.ProjectLighthouse.Types
{
[XmlRoot("deleted_by")]
public enum DeletedBy
{
[XmlEnum(Name = "none")]
None,
[XmlEnum(Name = "moderator")]
Moderator,
[XmlEnum(Name = "level_author")]
LevelAuthor
// TODO: deletion types for comments (profile etc)
}
}

View file

@ -6,6 +6,7 @@ using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types.Profiles;
using LBPUnion.ProjectLighthouse.Types.Reviews;
namespace LBPUnion.ProjectLighthouse.Types.Levels
{
@ -40,7 +41,8 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels
[NotMapped]
[XmlElement("resource")]
public string[] Resources {
public string[] Resources
{
get => this.ResourceCollection.Split(",");
set => this.ResourceCollection = string.Join(',', value);
}
@ -102,8 +104,10 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels
[XmlIgnore]
[NotMapped]
public int Hearts {
get {
public int Hearts
{
get
{
using Database database = new();
return database.HeartedLevels.Count(s => s.SlotId == this.SlotId);
@ -160,8 +164,10 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels
[NotMapped]
[XmlElement("thumbsup")]
public int Thumbsup {
get {
public int Thumbsup
{
get
{
using Database database = new();
return database.RatedLevels.Count(r => r.SlotId == this.SlotId && r.Rating == 1);
@ -170,8 +176,10 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels
[NotMapped]
[XmlElement("thumbsdown")]
public int Thumbsdown {
get {
public int Thumbsdown
{
get
{
using Database database = new();
return database.RatedLevels.Count(r => r.SlotId == this.SlotId && r.Rating == -1);
@ -180,8 +188,10 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels
[NotMapped]
[XmlElement("averageRating")]
public double RatingLBP1 {
get {
public double RatingLBP1
{
get
{
using Database database = new();
IQueryable<RatedLevel> ratedLevels = database.RatedLevels.Where(r => r.SlotId == this.SlotId && r.RatingLBP1 > 0);
@ -191,6 +201,18 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels
}
}
[NotMapped]
[XmlElement("reviewCount")]
public int ReviewCount
{
get
{
using Database database = new();
return database.Reviews.Count(r => r.SlotId == this.SlotId);
}
}
[XmlElement("leveltype")]
public string LevelType { get; set; } = "";
@ -200,7 +222,7 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels
LbpSerializer.StringElement("sizeOfResources", this.Resources.Sum(FileHelper.ResourceSize));
}
public string Serialize(RatedLevel? yourRatingStats = null, VisitedLevel? yourVisitedStats = null)
public string Serialize(RatedLevel? yourRatingStats = null, VisitedLevel? yourVisitedStats = null, Review? yourReview = null)
{
string slotData = LbpSerializer.StringElement("name", this.Name) +
@ -249,7 +271,11 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels
LbpSerializer.StringElement("yourLBP2PlayCount", yourVisitedStats?.PlaysLBP2) +
LbpSerializer.StringElement("yourLBP3PlayCount", yourVisitedStats?.PlaysLBP3) +
LbpSerializer.StringElement
("yourLBPVitaPlayCount", yourVisitedStats?.PlaysLBPVita); // i doubt this is the right name but we'll go with it
("yourLBPVitaPlayCount", yourVisitedStats?.PlaysLBPVita) + // i doubt this is the right name but we'll go with it
yourReview?.Serialize("yourReview") +
LbpSerializer.StringElement("reviewsEnabled", true) +
LbpSerializer.StringElement("commentsEnabled", false) +
LbpSerializer.StringElement("reviewCount", this.ReviewCount);
return LbpSerializer.TaggedStringElement("slot", slotData, "type", "user");
}

View file

@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace LBPUnion.ProjectLighthouse.Types.Reviews
{
public class RatedReview
{
// ReSharper disable once UnusedMember.Global
[Key]
public int RatedReviewId { get; set; }
public int UserId { get; set; }
[ForeignKey(nameof(UserId))]
public User User { get; set; }
public int ReviewId { get; set; }
[ForeignKey(nameof(ReviewId))]
public Review Review { get; set; }
public int Thumb { get; set; }
}
}

View file

@ -0,0 +1,100 @@
#nullable enable
using System;
using System.IO;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using LBPUnion.ProjectLighthouse.Types.Levels;
using LBPUnion.ProjectLighthouse.Serialization;
using System.Xml;
using System.Xml.Serialization;
namespace LBPUnion.ProjectLighthouse.Types.Reviews
{
[XmlRoot("review")]
[XmlType("review")]
public class Review
{
// ReSharper disable once UnusedMember.Global
[Key]
public int ReviewId { get; set; }
[XmlIgnore]
public int ReviewerId { get; set; }
[ForeignKey(nameof(ReviewerId))]
public User Reviewer { get; set; }
[XmlElement("slot_id")]
public int SlotId { get; set; }
[ForeignKey(nameof(SlotId))]
public Slot Slot { get; set; }
[XmlElement("timestamp")]
public long Timestamp { get; set; }
[XmlElement("labels")]
public string LabelCollection { get; set; }
[NotMapped]
[XmlIgnore]
public string[] Labels
{
get => this.LabelCollection.Split(",");
set => this.LabelCollection = string.Join(',', value);
}
[XmlElement("deleted")]
public Boolean Deleted { get; set; }
[XmlElement("deleted_by")]
public DeletedBy DeletedBy { get; set; }
[XmlElement("text")]
public string Text { get; set; }
[XmlElement("thumb")]
public int Thumb { get; set; }
[XmlElement("thumbsup")]
public int ThumbsUp { get; set; }
[XmlElement("thumbsdown")]
public int ThumbsDown { get; set; }
public string Serialize(RatedLevel? yourLevelRating = null, RatedReview? yourRatingStats = null)
{
return this.Serialize("review", yourLevelRating, yourRatingStats);
}
public string Serialize(string elementOverride, RatedLevel? yourLevelRating = null, RatedReview? yourRatingStats = null)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
XmlSerializer serializer = new(typeof(DeletedBy));
StringWriter stringWriter = new StringWriter();
using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, settings))
{
serializer.Serialize(xmlWriter, this.DeletedBy);
}
string deletedBy = stringWriter.ToString();
string reviewData = LbpSerializer.TaggedStringElement("slot_id", this.SlotId, "type", this.Slot.Type) +
LbpSerializer.StringElement("reviewer", this.Reviewer.Username) +
LbpSerializer.StringElement("thumb", this.Thumb) +
LbpSerializer.StringElement("timestamp", this.Timestamp) +
LbpSerializer.StringElement("labels", this.LabelCollection) +
LbpSerializer.StringElement("deleted", this.Deleted) +
deletedBy +
LbpSerializer.StringElement("text", this.Text) +
LbpSerializer.StringElement("thumbsup", this.ThumbsUp) +
LbpSerializer.StringElement("thumbsdown", this.ThumbsDown) +
LbpSerializer.StringElement("yourthumb", yourRatingStats?.Thumb == null ? 0 : yourRatingStats?.Thumb);
return LbpSerializer.TaggedStringElement(elementOverride, reviewData, "id", this.SlotId + "." + this.Reviewer.Username);
}
}
}

View file

@ -10,13 +10,15 @@ namespace LBPUnion.ProjectLighthouse.Types.Settings
{
public const string ServerName = "ProjectLighthouse";
public static bool DbConnected {
get {
public static bool DbConnected
{
get
{
try
{
return new Database().Database.CanConnect();
}
catch(Exception e)
catch (Exception e)
{
Logger.Log(e.ToString(), LoggerLevelDatabase.Instance);
return false;

View file

@ -26,27 +26,40 @@ namespace LBPUnion.ProjectLighthouse.Types
public string Biography { get; set; }
[NotMapped]
public int Reviews => 0;
public int Reviews
{
get
{
using Database database = new();
return database.Reviews.Count(r => r.ReviewerId == this.UserId);
}
}
[NotMapped]
public int Comments {
get {
public int Comments
{
get
{
using Database database = new();
return database.Comments.Count(c => c.TargetUserId == this.UserId);
}
}
[NotMapped]
public int PhotosByMe {
get {
public int PhotosByMe
{
get
{
using Database database = new();
return database.Photos.Count(p => p.CreatorId == this.UserId);
}
}
[NotMapped]
public int PhotosWithMe {
get {
public int PhotosWithMe
{
get
{
using Database database = new();
return Enumerable.Sum(database.Photos, photo => photo.Subjects.Count(subject => subject.User.UserId == this.UserId));
}
@ -61,24 +74,30 @@ namespace LBPUnion.ProjectLighthouse.Types
public Location Location { get; set; }
[NotMapped]
public int HeartedLevels {
get {
public int HeartedLevels
{
get
{
using Database database = new();
return database.HeartedLevels.Count(p => p.UserId == this.UserId);
}
}
[NotMapped]
public int HeartedUsers {
get {
public int HeartedUsers
{
get
{
using Database database = new();
return database.HeartedProfiles.Count(p => p.UserId == this.UserId);
}
}
[NotMapped]
public int QueuedLevels {
get {
public int QueuedLevels
{
get
{
using Database database = new();
return database.QueuedLevels.Count(p => p.UserId == this.UserId);
}
@ -88,8 +107,10 @@ namespace LBPUnion.ProjectLighthouse.Types
public string PlanetHash { get; set; } = "";
public int Hearts {
get {
public int Hearts
{
get
{
using Database database = new();
return database.HeartedProfiles.Count(s => s.HeartedUserId == this.UserId);
@ -104,10 +125,12 @@ namespace LBPUnion.ProjectLighthouse.Types
public string BooHash { get; set; } = "";
public string MehHash { get; set; } = "";
#nullable enable
#nullable enable
[NotMapped]
public string Status {
get {
public string Status
{
get
{
using Database database = new();
LastContact? lastMatch = database.LastContacts.Where
(l => l.UserId == this.UserId)
@ -118,7 +141,7 @@ namespace LBPUnion.ProjectLighthouse.Types
return "Currently online on " + lastMatch.GameVersion.ToPrettyString();
}
}
#nullable disable
#nullable disable
public string Serialize(GameVersion gameVersion = GameVersion.LittleBigPlanet1)
{
@ -156,8 +179,10 @@ namespace LBPUnion.ProjectLighthouse.Types
/// The number of used slots on the earth
/// </summary>
[NotMapped]
public int UsedSlots {
get {
public int UsedSlots
{
get
{
using Database database = new();
return database.Slots.Count(s => s.CreatorId == this.UserId);
}
@ -218,7 +243,7 @@ namespace LBPUnion.ProjectLighthouse.Types
#endregion Slots
#nullable enable
#nullable enable
public override bool Equals(object? obj)
{
if (obj is User user) return user.UserId == UserId;
@ -238,6 +263,6 @@ namespace LBPUnion.ProjectLighthouse.Types
[SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")]
public override int GetHashCode() => this.UserId;
#nullable disable
#nullable disable
}
}