diff --git a/ProjectLighthouse.Servers.API/Program.cs b/ProjectLighthouse.Servers.API/Program.cs index e689dc98..a27c46c3 100644 --- a/ProjectLighthouse.Servers.API/Program.cs +++ b/ProjectLighthouse.Servers.API/Program.cs @@ -1,36 +1,22 @@ +using LBPUnion.ProjectLighthouse; using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Logging.Loggers.AspNet; using LBPUnion.ProjectLighthouse.Servers.API.Startup; using LBPUnion.ProjectLighthouse.Types.Misc; -using Microsoft.Extensions.DependencyInjection.Extensions; -namespace LBPUnion.ProjectLighthouse.Servers.API; +await StartupTasks.Run(ServerType.Api); -public static class Program +IHostBuilder builder = Host.CreateDefaultBuilder(); +builder.ConfigureWebHostDefaults(webBuilder => { - public static void Main(string[] args) - { - StartupTasks.Run(args, ServerType.Api); + webBuilder.UseStartup(); + webBuilder.UseUrls(ServerConfiguration.Instance.ApiListenUrl); +}); - CreateHostBuilder(args).Build().Run(); - } +builder.ConfigureLogging(logging => +{ + logging.ClearProviders(); + logging.AddProvider(new AspNetToLighthouseLoggerProvider()); +}); - public static IHostBuilder CreateHostBuilder(string[] args) - => Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults - ( - webBuilder => - { - webBuilder.UseStartup(); - webBuilder.UseUrls(ServerConfiguration.Instance.ApiListenUrl); - } - ) - .ConfigureLogging - ( - logging => - { - logging.ClearProviders(); - logging.Services.TryAddEnumerable(ServiceDescriptor.Singleton()); - } - ); -} \ No newline at end of file +await builder.Build().RunAsync(); \ No newline at end of file diff --git a/ProjectLighthouse.Servers.API/Responses/ApiSlot.cs b/ProjectLighthouse.Servers.API/Responses/ApiSlot.cs index 38582101..b859d8fe 100644 --- a/ProjectLighthouse.Servers.API/Responses/ApiSlot.cs +++ b/ProjectLighthouse.Servers.API/Responses/ApiSlot.cs @@ -68,7 +68,7 @@ public struct ApiSlot PlaysUnique = slot.PlaysUnique, PlaysComplete = slot.PlaysComplete, CommentsEnabled = slot.CommentsEnabled, - AverageRating = slot.RatingLBP1, + AverageRating = context.RatedLevels.Where(r => r.SlotId == slot.SlotId).Average(r => (double?)r.RatingLBP1) ?? 3.0, LevelType = slot.LevelType, }; } \ No newline at end of file diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Matching/MatchController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Matching/MatchController.cs index 6b15d445..4059d37a 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Matching/MatchController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Matching/MatchController.cs @@ -98,17 +98,22 @@ public class MatchController : ControllerBase case FindBestRoom diveInData when MatchHelper.UserLocations.Count > 1: #endif { - FindBestRoomResponse? response = RoomHelper.FindBestRoom - (user, token.GameVersion, diveInData.RoomSlot, token.Platform, token.UserLocation); + FindBestRoomResponse? response = RoomHelper.FindBestRoom(this.database, + user, + token.GameVersion, + diveInData.RoomSlot, + token.Platform, + token.UserLocation); if (response == null) return this.NotFound(); string serialized = JsonSerializer.Serialize(response, typeof(FindBestRoomResponse)); - foreach (Player player in response.Players) MatchHelper.AddUserRecentlyDivedIn(user.UserId, player.User.UserId); + foreach (Player player in response.Players) + MatchHelper.AddUserRecentlyDivedIn(user.UserId, player.User.UserId); return this.Ok($"[{{\"StatusCode\":200}},{serialized}]"); } - case CreateRoom createRoom when MatchHelper.UserLocations.Count >= 1: + case CreateRoom createRoom when !MatchHelper.UserLocations.IsEmpty: { List users = new(); foreach (string playerUsername in createRoom.Players) @@ -139,9 +144,8 @@ public class MatchController : ControllerBase } room.PlayerIds = users.Select(u => u.UserId).ToList(); - await RoomHelper.CleanupRooms(null, room); + await RoomHelper.CleanupRooms(this.database, null, room); } - break; } } diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Resources/PhotosController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Resources/PhotosController.cs index 2c3261b1..84509369 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Resources/PhotosController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Resources/PhotosController.cs @@ -34,17 +34,17 @@ public class PhotosController : ControllerBase [HttpPost("uploadPhoto")] public async Task UploadPhoto() { - UserEntity? user = await this.database.UserFromGameToken(this.GetToken()); - if (user == null) return this.Forbid(); + GameTokenEntity token = this.GetToken(); - if (user.GetUploadedPhotoCount(this.database) >= ServerConfiguration.Instance.UserGeneratedContentLimits.PhotosQuota) return this.BadRequest(); + int photoCount = await this.database.Photos.CountAsync(p => p.CreatorId == token.UserId); + if (photoCount >= ServerConfiguration.Instance.UserGeneratedContentLimits.PhotosQuota) return this.BadRequest(); GamePhoto? photo = await this.DeserializeBody(); if (photo == null) return this.BadRequest(); - foreach (PhotoEntity p in this.database.Photos.Where(p => p.CreatorId == user.UserId)) + foreach (PhotoEntity p in this.database.Photos.Where(p => p.CreatorId == token.UserId)) { - if (p.LargeHash == photo.LargeHash) return this.Ok(); // photo already uplaoded + if (p.LargeHash == photo.LargeHash) return this.Ok(); // photo already uploaded if (p.MediumHash == photo.MediumHash) return this.Ok(); if (p.SmallHash == photo.SmallHash) return this.Ok(); if (p.PlanHash == photo.PlanHash) return this.Ok(); @@ -52,8 +52,7 @@ public class PhotosController : ControllerBase PhotoEntity photoEntity = new() { - CreatorId = user.UserId, - Creator = user, + CreatorId = token.UserId, SmallHash = photo.SmallHash, MediumHash = photo.MediumHash, LargeHash = photo.LargeHash, @@ -145,12 +144,14 @@ public class PhotosController : ControllerBase await this.database.SaveChangesAsync(); + string username = await this.database.UsernameFromGameToken(token); + await WebhookHelper.SendWebhook ( new EmbedBuilder { Title = "New photo uploaded!", - Description = $"{user.Username} uploaded a new photo.", + Description = $"{username} uploaded a new photo.", ImageUrl = $"{ServerConfiguration.Instance.ExternalUrl}/gameAssets/{photo.LargeHash}", Color = WebhookHelper.GetEmbedColor(), } diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs index 57c07031..1607dbee 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs @@ -12,7 +12,6 @@ using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Token; using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Levels; -using LBPUnion.ProjectLighthouse.Types.Matchmaking.Rooms; using LBPUnion.ProjectLighthouse.Types.Misc; using LBPUnion.ProjectLighthouse.Types.Serialization; using LBPUnion.ProjectLighthouse.Types.Users; diff --git a/ProjectLighthouse.Servers.GameServer/Program.cs b/ProjectLighthouse.Servers.GameServer/Program.cs index 50ef3ad6..dc274357 100644 --- a/ProjectLighthouse.Servers.GameServer/Program.cs +++ b/ProjectLighthouse.Servers.GameServer/Program.cs @@ -1,36 +1,22 @@ +using LBPUnion.ProjectLighthouse; using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Logging.Loggers.AspNet; using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup; using LBPUnion.ProjectLighthouse.Types.Misc; -using Microsoft.Extensions.DependencyInjection.Extensions; -namespace LBPUnion.ProjectLighthouse.Servers.GameServer; +await StartupTasks.Run(ServerType.GameServer); -public static class Program +IHostBuilder builder = Host.CreateDefaultBuilder(); +builder.ConfigureWebHostDefaults(webBuilder => { - public static void Main(string[] args) - { - StartupTasks.Run(args, ServerType.GameServer); + webBuilder.UseStartup(); + webBuilder.UseUrls(ServerConfiguration.Instance.GameApiListenUrl); +}); - CreateHostBuilder(args).Build().Run(); - } +builder.ConfigureLogging(logging => +{ + logging.ClearProviders(); + logging.AddProvider(new AspNetToLighthouseLoggerProvider()); +}); - public static IHostBuilder CreateHostBuilder(string[] args) - => Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults - ( - webBuilder => - { - webBuilder.UseStartup(); - webBuilder.UseUrls(ServerConfiguration.Instance.GameApiListenUrl); - } - ) - .ConfigureLogging - ( - logging => - { - logging.ClearProviders(); - logging.Services.TryAddEnumerable(ServiceDescriptor.Singleton()); - } - ); -} \ No newline at end of file +await builder.Build().RunAsync(); \ No newline at end of file diff --git a/ProjectLighthouse.Servers.GameServer/Startup/GameServerStartup.cs b/ProjectLighthouse.Servers.GameServer/Startup/GameServerStartup.cs index 6b414b9f..86dfd571 100644 --- a/ProjectLighthouse.Servers.GameServer/Startup/GameServerStartup.cs +++ b/ProjectLighthouse.Servers.GameServer/Startup/GameServerStartup.cs @@ -113,6 +113,5 @@ public class GameServerStartup app.UseAuthorization(); app.UseEndpoints(endpoints => endpoints.MapControllers()); - app.UseEndpoints(endpoints => endpoints.MapRazorPages()); } } diff --git a/ProjectLighthouse.Servers.Website/Pages/Admin/AdminPanelPage.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Admin/AdminPanelPage.cshtml.cs index 92bff838..345f722d 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Admin/AdminPanelPage.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Admin/AdminPanelPage.cshtml.cs @@ -8,14 +8,12 @@ using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; using LBPUnion.ProjectLighthouse.Servers.Website.Types; using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Logging; -using LBPUnion.ProjectLighthouse.Types.Maintenance; using Microsoft.AspNetCore.Mvc; namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Admin; public class AdminPanelPage : BaseLayout { - public List Commands = MaintenanceHelper.Commands; public AdminPanelPage(DatabaseContext database) : base(database) { } @@ -40,7 +38,7 @@ public class AdminPanelPage : BaseLayout args = command + " " + args; string[] split = args.Split(" "); - List runCommand = await MaintenanceHelper.RunCommand(split); + List runCommand = await MaintenanceHelper.RunCommand(this.HttpContext.RequestServices, split); return this.Redirect($"~/admin?log={CryptoHelper.ToBase64(runCommand.ToLogString())}"); } diff --git a/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml index c04f20e5..af71ec13 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml @@ -1,10 +1,12 @@ @page "/debug/roomVisualizer" +@using LBPUnion.ProjectLighthouse.Database @using LBPUnion.ProjectLighthouse.Extensions @using LBPUnion.ProjectLighthouse.Helpers @using LBPUnion.ProjectLighthouse.Types.Entities.Profile @using LBPUnion.ProjectLighthouse.Types.Matchmaking.Rooms @using LBPUnion.ProjectLighthouse.Types.Users @model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Debug.RoomVisualizerPage +@inject DatabaseContext Database @{ Layout = "Layouts/BaseLayout"; @@ -59,7 +61,7 @@ #nullable enable if (version == GameVersion.LittleBigPlanet1 || version == GameVersion.LittleBigPlanetPSP || version == GameVersion.Unknown) continue; - FindBestRoomResponse? response = RoomHelper.FindBestRoom(null, version, null, null, null); + FindBestRoomResponse? response = RoomHelper.FindBestRoom(Database, null, version, null, null, null); string text = response == null ? "No room found." : "Room " + response.RoomId;

Best room for @version.ToPrettyString(): @text

diff --git a/ProjectLighthouse.Servers.Website/Pages/Layouts/BaseLayout.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Layouts/BaseLayout.cshtml.cs index fbc5ad11..5c1ce0f8 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Layouts/BaseLayout.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Layouts/BaseLayout.cshtml.cs @@ -29,7 +29,7 @@ public class BaseLayout : PageModel public BaseLayout(DatabaseContext database) { this.Database = database; - + this.NavigationItems.Add(new PageNavigationItem(BaseLayoutStrings.HeaderUsers, "/users/0", "user friends")); this.NavigationItems.Add(new PageNavigationItem(BaseLayoutStrings.HeaderPhotos, "/photos/0", "camera")); this.NavigationItems.Add(new PageNavigationItem(BaseLayoutStrings.HeaderSlots, "/slots/0", "globe americas")); diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml index 3f20a152..18d66580 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml @@ -1,9 +1,11 @@ @using System.Web @using System.IO +@using LBPUnion.ProjectLighthouse.Database @using LBPUnion.ProjectLighthouse.Localization @using LBPUnion.ProjectLighthouse.Servers.Website.Extensions @using LBPUnion.ProjectLighthouse.Types.Entities.Interaction @using LBPUnion.ProjectLighthouse.Types.Entities.Profile +@inject DatabaseContext Database @{ string language = (string?)ViewData["Language"] ?? LocalizationManager.DefaultLang; @@ -50,7 +52,7 @@ int yourThumb = commentAndReaction.Value?.Rating ?? 0; DateTimeOffset timestamp = DateTimeOffset.FromUnixTimeSeconds(comment.Timestamp / 1000).ToLocalTime(); StringWriter messageWriter = new(); - HttpUtility.HtmlDecode(comment.GetCommentMessage(), messageWriter); + HttpUtility.HtmlDecode(comment.GetCommentMessage(Database), messageWriter); string decodedMessage = messageWriter.ToString(); string? url = Url.RouteUrl(ViewContext.RouteData.Values); diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/Links/UserLinkPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/Links/UserLinkPartial.cshtml index 2dedb34f..4d889b33 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/Links/UserLinkPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/Links/UserLinkPartial.cshtml @@ -1,14 +1,15 @@ @using LBPUnion.ProjectLighthouse.Database @using LBPUnion.ProjectLighthouse.Localization @using LBPUnion.ProjectLighthouse.Servers.Website.Extensions -@model LBPUnion.ProjectLighthouse.Types.Entities.Profile.UserEntity +@using LBPUnion.ProjectLighthouse.Types.Entities.Profile +@model UserEntity +@inject DatabaseContext Database @{ string language = (string?)ViewData["Language"] ?? LocalizationManager.DefaultLang; string timeZone = (string?)ViewData["TimeZone"] ?? TimeZoneInfo.Local.Id; bool includeStatus = (bool?)ViewData["IncludeStatus"] ?? false; - await using DatabaseContext database = DatabaseContext.CreateNewInstance(); - string userStatus = includeStatus ? Model.GetStatus(database).ToTranslatedString(language, timeZone) : ""; + string userStatus = includeStatus ? Model.GetStatus(Database).ToTranslatedString(language, timeZone) : ""; } diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/ModerationCasePartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/ModerationCasePartial.cshtml index 60f73d77..2f108dec 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/ModerationCasePartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/ModerationCasePartial.cshtml @@ -4,9 +4,9 @@ @using LBPUnion.ProjectLighthouse.Types.Entities.Profile @using LBPUnion.ProjectLighthouse.Types.Moderation.Cases @model LBPUnion.ProjectLighthouse.Types.Entities.Moderation.ModerationCaseEntity +@inject DatabaseContext Database @{ - DatabaseContext database = DatabaseContext.CreateNewInstance(); string color = "blue"; string timeZone = (string?)ViewData["TimeZone"] ?? TimeZoneInfo.Local.Id; @@ -70,7 +70,7 @@ @if (Model.Type.AffectsLevel()) { - SlotEntity? slot = await Model.GetSlotAsync(database); + SlotEntity? slot = await Model.GetSlotAsync(Database); if (slot != null) {

Affected level: @slot.Name

@@ -78,7 +78,7 @@ } else if (Model.Type.AffectsUser()) { - UserEntity? user = await Model.GetUserAsync(database); + UserEntity? user = await Model.GetUserAsync(Database); if (user != null) {

Affected user: @user.Username

diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml index 23f0c039..43ac3423 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml @@ -7,12 +7,11 @@ @using LBPUnion.ProjectLighthouse.Types.Users @using Microsoft.EntityFrameworkCore @model LBPUnion.ProjectLighthouse.Types.Entities.Level.SlotEntity +@inject DatabaseContext Database @{ UserEntity? user = (UserEntity?)ViewData["User"]; - await using DatabaseContext database = DatabaseContext.CreateNewInstance(); - string slotName = HttpUtility.HtmlDecode(string.IsNullOrEmpty(Model!.Name) ? "Unnamed Level" : Model.Name); bool isMobile = (bool?)ViewData["IsMobile"] ?? false; @@ -26,8 +25,8 @@ if (user != null) { - isQueued = await database.QueuedLevels.FirstOrDefaultAsync(h => h.SlotId == Model.SlotId && h.UserId == user.UserId) != null; - isHearted = await database.HeartedLevels.FirstOrDefaultAsync(h => h.SlotId == Model.SlotId && h.UserId == user.UserId) != null; + isQueued = await Database.QueuedLevels.AnyAsync(h => h.SlotId == Model.SlotId && h.UserId == user.UserId); + isHearted = await Database.HeartedLevels.AnyAsync(h => h.SlotId == Model.SlotId && h.UserId == user.UserId); } string callbackUrl = (string)ViewData["CallbackUrl"]!; @@ -81,15 +80,24 @@ }
- @Model.Hearts + @{ + var slotStats = await Database.Slots.Where(s => s.SlotId == Model.SlotId).Select(_ => new + { + HeartCount = Database.HeartedLevels.Count(h => h.SlotId == Model.SlotId), + ThumbsUp = Database.RatedLevels.Count(r => r.SlotId == Model.SlotId && r.Rating == 1), + ThumbsDown = Database.RatedLevels.Count(r => r.SlotId == Model.SlotId && r.Rating == -1), + RatingLbp1 = Database.RatedLevels.Where(r => r.SlotId == Model.SlotId).Average(r => (double?)r.RatingLBP1) ?? 3.0, + }).OrderBy(_ => 1).FirstAsync(); + } + @slotStats.HeartCount @Model.PlaysUnique - @Model.Thumbsup - @Model.Thumbsdown + @slotStats.ThumbsUp + @slotStats.ThumbsDown @if (Model.GameVersion == GameVersion.LittleBigPlanet1) { - @(Math.Round(Model.RatingLBP1 * 10) / 10) + @(Math.Round(slotStats.RatingLbp1 * 10) / 10) }
@if (Model.Creator != null) diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/UserCardPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/UserCardPartial.cshtml index b06a3359..429d239c 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/UserCardPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/UserCardPartial.cshtml @@ -1,7 +1,9 @@ @using LBPUnion.ProjectLighthouse.Database @using LBPUnion.ProjectLighthouse.Localization @using LBPUnion.ProjectLighthouse.Servers.Website.Extensions; +@using Microsoft.EntityFrameworkCore @model LBPUnion.ProjectLighthouse.Types.Entities.Profile.UserEntity +@inject DatabaseContext Database @{ bool showLink = (bool?)ViewData["ShowLink"] ?? false; @@ -42,21 +44,22 @@ } @{ - await using DatabaseContext context = DatabaseContext.CreateNewInstance(); - - int hearts = Model.GetHeartCount(context); - int comments = Model.GetCommentCount(context); - int levels = Model.GetUsedSlotCount(context); - int photos = Model.GetUploadedPhotoCount(context); + var stats = await Database.Users.Where(u => u.UserId == Model.UserId).Select(_ => new + { + HeartCount = Database.HeartedProfiles.Count(hp => hp.HeartedUserId == Model.UserId), + CommentCount = Database.Comments.Count(c => c.PosterUserId == Model.UserId), + LevelCount = Database.Slots.Count(s => s.CreatorId == Model.UserId), + PhotoCount = Database.Photos.Count(p => p.CreatorId == Model.UserId), + }).OrderBy(_ => 1).FirstAsync(); } - @Model.GetStatus(context).ToTranslatedString(language, timeZone) + @Model.GetStatus(Database).ToTranslatedString(language, timeZone)
- @hearts - @comments - @levels - @photos + @stats.HeartCount + @stats.CommentCount + @stats.LevelCount + @stats.PhotoCount
\ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Pages/PhotosPage.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/PhotosPage.cshtml.cs index e5920739..57803da8 100644 --- a/ProjectLighthouse.Servers.Website/Pages/PhotosPage.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/PhotosPage.cshtml.cs @@ -10,7 +10,6 @@ namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; public class PhotosPage : BaseLayout { - public int PageAmount; public int PageNumber; diff --git a/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml index 8d947cb9..dbfe7235 100644 --- a/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml @@ -9,6 +9,7 @@ @using LBPUnion.ProjectLighthouse.Types.Moderation.Cases @using LBPUnion.ProjectLighthouse.Types.Users @model LBPUnion.ProjectLighthouse.Servers.Website.Pages.SlotPage +@inject DatabaseContext Database @{ Layout = "Layouts/BaseLayout"; @@ -55,7 +56,7 @@ string[] authorLabels; if (Model.Slot?.GameVersion == GameVersion.LittleBigPlanet1) { - authorLabels = Model.Slot.LevelTags(DatabaseContext.CreateNewInstance()); + authorLabels = Model.Slot.LevelTags(Database); } else { diff --git a/ProjectLighthouse.Servers.Website/Program.cs b/ProjectLighthouse.Servers.Website/Program.cs index 32d396e6..cea68c8a 100644 --- a/ProjectLighthouse.Servers.Website/Program.cs +++ b/ProjectLighthouse.Servers.Website/Program.cs @@ -1,38 +1,22 @@ -#nullable enable +using LBPUnion.ProjectLighthouse; using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Logging.Loggers.AspNet; using LBPUnion.ProjectLighthouse.Servers.Website.Startup; using LBPUnion.ProjectLighthouse.Types.Misc; -using Microsoft.Extensions.DependencyInjection.Extensions; -namespace LBPUnion.ProjectLighthouse.Servers.Website; +await StartupTasks.Run(ServerType.Website); -public static class Program +IHostBuilder builder = Host.CreateDefaultBuilder(); +builder.ConfigureWebHostDefaults(webBuilder => { - public static void Main(string[] args) - { - StartupTasks.Run(args, ServerType.Website); + webBuilder.UseStartup(); + webBuilder.UseUrls(ServerConfiguration.Instance.WebsiteListenUrl); + webBuilder.UseWebRoot("StaticFiles"); +}); - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) - => Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults - ( - webBuilder => - { - webBuilder.UseStartup(); - webBuilder.UseWebRoot("StaticFiles"); - webBuilder.UseUrls(ServerConfiguration.Instance.WebsiteListenUrl); - } - ) - .ConfigureLogging - ( - logging => - { - logging.ClearProviders(); - logging.Services.TryAddEnumerable(ServiceDescriptor.Singleton()); - } - ); -} \ No newline at end of file +builder.ConfigureLogging(logging => +{ + logging.ClearProviders(); + logging.AddProvider(new AspNetToLighthouseLoggerProvider()); +}); +await builder.Build().RunAsync(); \ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Startup/WebsiteStartup.cs b/ProjectLighthouse.Servers.Website/Startup/WebsiteStartup.cs index 42f83e85..c391fc5e 100644 --- a/ProjectLighthouse.Servers.Website/Startup/WebsiteStartup.cs +++ b/ProjectLighthouse.Servers.Website/Startup/WebsiteStartup.cs @@ -42,7 +42,7 @@ public class WebsiteStartup { // jank but works string projectDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..")); - + options.FileProviders.Clear(); options.FileProviders.Add(new PhysicalFileProvider(projectDir)); }); @@ -131,7 +131,10 @@ public class WebsiteStartup app.UseRequestLocalization(); - app.UseEndpoints(endpoints => endpoints.MapControllers()); - app.UseEndpoints(endpoints => endpoints.MapRazorPages()); + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + endpoints.MapRazorPages(); + }); } } diff --git a/ProjectLighthouse.Tests.GameApiTests/Unit/Controllers/ControllerExtensionTests.cs b/ProjectLighthouse.Tests.GameApiTests/Unit/Controllers/ControllerExtensionTests.cs index 54343ffe..4a00ab68 100644 --- a/ProjectLighthouse.Tests.GameApiTests/Unit/Controllers/ControllerExtensionTests.cs +++ b/ProjectLighthouse.Tests.GameApiTests/Unit/Controllers/ControllerExtensionTests.cs @@ -1,12 +1,9 @@ -using System.Collections.Generic; -using System.Linq; -using LBPUnion.ProjectLighthouse.Filter; +using LBPUnion.ProjectLighthouse.Filter; using LBPUnion.ProjectLighthouse.Filter.Filters; using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots; using LBPUnion.ProjectLighthouse.Servers.GameServer.Extensions; using LBPUnion.ProjectLighthouse.Tests.Helpers; using LBPUnion.ProjectLighthouse.Types.Entities.Token; -using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Users; using Microsoft.AspNetCore.Http; using Xunit; diff --git a/ProjectLighthouse.Tests/Helpers/IntegrationHelper.cs b/ProjectLighthouse.Tests/Helpers/IntegrationHelper.cs index 2f570755..5562036a 100644 --- a/ProjectLighthouse.Tests/Helpers/IntegrationHelper.cs +++ b/ProjectLighthouse.Tests/Helpers/IntegrationHelper.cs @@ -8,9 +8,12 @@ namespace LBPUnion.ProjectLighthouse.Tests.Helpers; public static class IntegrationHelper { - private static readonly Lazy dbConnected = new(IsDbConnected); + private static readonly Lazy dbConnected = new(() => + { + using DatabaseContext database = DatabaseContext.CreateNewInstance(); + return database.Database.CanConnect(); + }); - private static bool IsDbConnected() => ServerStatics.DbConnected; /// /// Resets the database to a clean state and returns a new DatabaseContext. diff --git a/ProjectLighthouse.Tests/Integration/DatabaseFactAttribute.cs b/ProjectLighthouse.Tests/Integration/DatabaseFactAttribute.cs deleted file mode 100644 index 51cdc8a7..00000000 --- a/ProjectLighthouse.Tests/Integration/DatabaseFactAttribute.cs +++ /dev/null @@ -1,23 +0,0 @@ -using LBPUnion.ProjectLighthouse.Configuration; -using LBPUnion.ProjectLighthouse.Database; -using Microsoft.EntityFrameworkCore; -using Xunit; - -namespace LBPUnion.ProjectLighthouse.Tests.Integration; - -public sealed class DatabaseFactAttribute : FactAttribute -{ - private static readonly object migrateLock = new(); - - public DatabaseFactAttribute() - { - ServerConfiguration.Instance.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse"; - if (!ServerStatics.DbConnected) this.Skip = "Database not available"; - else - lock (migrateLock) - { - using DatabaseContext database = DatabaseContext.CreateNewInstance(); - database.Database.Migrate(); - } - } -} \ No newline at end of file diff --git a/ProjectLighthouse/Administration/Maintenance/Commands/CreateAPIKeyCommand.cs b/ProjectLighthouse/Administration/Maintenance/Commands/CreateAPIKeyCommand.cs index de6f8a68..6d17bec7 100644 --- a/ProjectLighthouse/Administration/Maintenance/Commands/CreateAPIKeyCommand.cs +++ b/ProjectLighthouse/Administration/Maintenance/Commands/CreateAPIKeyCommand.cs @@ -6,31 +6,34 @@ using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Types.Entities.Token; using LBPUnion.ProjectLighthouse.Types.Logging; using LBPUnion.ProjectLighthouse.Types.Maintenance; +using Microsoft.Extensions.DependencyInjection; -namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.Commands +namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.Commands; + +public class CreateApiKeyCommand : ICommand { - public class CreateApiKeyCommand : ICommand - { - public string Name() => "Create API Key"; - public string[] Aliases() => new[] { "createAPIKey", }; - public string Arguments() => ""; - public int RequiredArgs() => 1; - - public async Task Run(string[] args, Logger logger) + public string Name() => "Create API Key"; + public string[] Aliases() => + new[] { - ApiKeyEntity key = new() { Description = args[0], }; - if (string.IsNullOrWhiteSpace(key.Description)) - { - key.Description = ""; - } - key.Key = CryptoHelper.GenerateAuthToken(); - key.Created = DateTime.Now; - DatabaseContext database = DatabaseContext.CreateNewInstance(); - await database.APIKeys.AddAsync(key); - await database.SaveChangesAsync(); - logger.LogSuccess($"The API key has been created (id: {key.Id}), however for security the token will only be shown once.", LogArea.Command); - logger.LogInfo($"Key: {key.Key}", LogArea.Command); - } - } -} + "createAPIKey", + }; + public string Arguments() => ""; + public int RequiredArgs() => 1; + public async Task Run(IServiceProvider provider, string[] args, Logger logger) + { + ApiKeyEntity key = new() { Description = args[0], }; + if (string.IsNullOrWhiteSpace(key.Description)) + { + key.Description = ""; + } + key.Key = CryptoHelper.GenerateAuthToken(); + key.Created = DateTime.Now; + DatabaseContext database = provider.GetRequiredService(); + await database.APIKeys.AddAsync(key); + await database.SaveChangesAsync(); + logger.LogSuccess($"The API key has been created (id: {key.Id}), however for security the token will only be shown once.", LogArea.Command); + logger.LogInfo($"Key: {key.Key}", LogArea.Command); + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Administration/Maintenance/Commands/CreateUserCommand.cs b/ProjectLighthouse/Administration/Maintenance/Commands/CreateUserCommand.cs index e5c59dcd..3078920d 100644 --- a/ProjectLighthouse/Administration/Maintenance/Commands/CreateUserCommand.cs +++ b/ProjectLighthouse/Administration/Maintenance/Commands/CreateUserCommand.cs @@ -1,4 +1,5 @@ #nullable enable +using System; using System.Threading.Tasks; using LBPUnion.ProjectLighthouse.Database; using LBPUnion.ProjectLighthouse.Helpers; @@ -7,47 +8,46 @@ using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Logging; using LBPUnion.ProjectLighthouse.Types.Maintenance; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.Commands; public class CreateUserCommand : ICommand { - private readonly DatabaseContext _database = DatabaseContext.CreateNewInstance(); + public string Name() => "Create New User"; + public string[] Aliases() => + new[] + { + "useradd", "adduser", "newuser", "createUser", + }; + public string Arguments() => " "; + public int RequiredArgs() => 2; - public async Task Run(string[] args, Logger logger) + public async Task Run(IServiceProvider provider, string[] args, Logger logger) { + + DatabaseContext database = provider.GetRequiredService(); string onlineId = args[0]; string password = args[1]; password = CryptoHelper.Sha256Hash(password); - UserEntity? user = await this._database.Users.FirstOrDefaultAsync(u => u.Username == onlineId); + UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == onlineId); if (user == null) - { - user = await this._database.CreateUser(onlineId, CryptoHelper.BCryptHash(password)); - logger.LogSuccess($"Created user {user.UserId} with online ID (username) {user.Username} and the specified password.", LogArea.Command); - - user.PasswordResetRequired = true; - logger.LogInfo("This user will need to reset their password when they log in.", LogArea.Command); - - await this._database.SaveChangesAsync(); - logger.LogInfo("Database changes saved.", LogArea.Command); - } - else { logger.LogError("A user with this username already exists.", LogArea.Command); + return; } + + user = await database.CreateUser(onlineId, CryptoHelper.BCryptHash(password)); + logger.LogSuccess( + $"Created user {user.UserId} with online ID (username) {user.Username} and the specified password.", + LogArea.Command); + + user.PasswordResetRequired = true; + logger.LogInfo("This user will need to reset their password when they log in.", LogArea.Command); + + await database.SaveChangesAsync(); + logger.LogInfo("Database changes saved.", LogArea.Command); } - - public string Name() => "Create New User"; - - public string[] Aliases() - => new[] - { - "useradd", "adduser", "newuser", "createUser", - }; - - public string Arguments() => " "; - - public int RequiredArgs() => 2; } \ No newline at end of file diff --git a/ProjectLighthouse/Administration/Maintenance/Commands/DeleteUserCommand.cs b/ProjectLighthouse/Administration/Maintenance/Commands/DeleteUserCommand.cs index 96d6ed1d..5cf779c9 100644 --- a/ProjectLighthouse/Administration/Maintenance/Commands/DeleteUserCommand.cs +++ b/ProjectLighthouse/Administration/Maintenance/Commands/DeleteUserCommand.cs @@ -7,12 +7,12 @@ using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Logging; using LBPUnion.ProjectLighthouse.Types.Maintenance; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.Commands; public class DeleteUserCommand : ICommand { - private readonly DatabaseContext database = DatabaseContext.CreateNewInstance(); public string Name() => "Delete User"; public string[] Aliases() => new[] @@ -21,22 +21,22 @@ public class DeleteUserCommand : ICommand }; public string Arguments() => ""; public int RequiredArgs() => 1; - public async Task Run(string[] args, Logger logger) + + public async Task Run(IServiceProvider provider, string[] args, Logger logger) { - UserEntity? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username.Length > 0 && u.Username == args[0]); + DatabaseContext database = provider.GetRequiredService(); + UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username.Length > 0 && u.Username == args[0]); if (user == null) - try - { - user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == Convert.ToInt32(args[0])); - if (user == null) throw new Exception(); - } - catch + { + user = await database.Users.FirstOrDefaultAsync(u => u.UserId == Convert.ToInt32(args[0])); + if (user == null) { logger.LogError($"Could not find user by parameter '{args[0]}'", LogArea.Command); return; } + } - await this.database.RemoveUser(user); + await database.RemoveUser(user); logger.LogSuccess($"Successfully deleted user {user.Username}", LogArea.Command); } } \ No newline at end of file diff --git a/ProjectLighthouse/Administration/Maintenance/Commands/FlushRedisCommand.cs b/ProjectLighthouse/Administration/Maintenance/Commands/FlushRedisCommand.cs index fc53b58b..5c2e2e50 100644 --- a/ProjectLighthouse/Administration/Maintenance/Commands/FlushRedisCommand.cs +++ b/ProjectLighthouse/Administration/Maintenance/Commands/FlushRedisCommand.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.StorableLists; @@ -8,14 +9,14 @@ namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.Commands; public class FlushRedisCommand : ICommand { public string Name() => "Flush Redis"; - public string[] Aliases() => new[] { - "flush", "flush-redis", - }; + public string[] Aliases() => + new[] + { + "flush", "flush-redis", + }; public string Arguments() => ""; public int RequiredArgs() => 0; - public async Task Run(string[] args, Logger logger) - { - await RedisDatabase.FlushAll(); - } + public async Task Run(IServiceProvider provider, string[] args, Logger logger) => await RedisDatabase.FlushAll(); + } \ No newline at end of file diff --git a/ProjectLighthouse/Administration/Maintenance/Commands/RenameUserCommand.cs b/ProjectLighthouse/Administration/Maintenance/Commands/RenameUserCommand.cs index 02a37ec9..67a380b6 100644 --- a/ProjectLighthouse/Administration/Maintenance/Commands/RenameUserCommand.cs +++ b/ProjectLighthouse/Administration/Maintenance/Commands/RenameUserCommand.cs @@ -7,32 +7,12 @@ using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Logging; using LBPUnion.ProjectLighthouse.Types.Maintenance; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.Commands; public class RenameUserCommand : ICommand { - private readonly DatabaseContext database = DatabaseContext.CreateNewInstance(); - public async Task Run(string[] args, Logger logger) - { - UserEntity? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == args[0]); - if (user == null) - try - { - user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == Convert.ToInt32(args[0])); - if (user == null) throw new Exception(); - } - catch - { - logger.LogError($"Could not find user by parameter '{args[0]}'", LogArea.Command); - return; - } - - user.Username = args[1]; - await this.database.SaveChangesAsync(); - - logger.LogSuccess($"The username for user {user.Username} (id: {user.UserId}) has been changed.", LogArea.Command); - } public string Name() => "Rename User"; public string[] Aliases() => new[] @@ -41,4 +21,26 @@ public class RenameUserCommand : ICommand }; public string Arguments() => " "; public int RequiredArgs() => 2; + + public async Task Run(IServiceProvider provider, string[] args, Logger logger) + { + DatabaseContext database = provider.GetRequiredService(); + UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == args[0]); + if (user == null) + { + _ = int.TryParse(args[0], out int userId); + user = await database.Users.FirstOrDefaultAsync(u => u.UserId == userId); + if (user == null) + { + logger.LogError($"Could not find user by parameter '{args[0]}'", LogArea.Command); + return; + } + } + + user.Username = args[1]; + await database.SaveChangesAsync(); + + logger.LogSuccess($"The username for user {user.Username} (id: {user.UserId}) has been changed.", + LogArea.Command); + } } \ No newline at end of file diff --git a/ProjectLighthouse/Administration/Maintenance/Commands/ResetPasswordCommand.cs b/ProjectLighthouse/Administration/Maintenance/Commands/ResetPasswordCommand.cs index 11c5dd82..f45c4266 100644 --- a/ProjectLighthouse/Administration/Maintenance/Commands/ResetPasswordCommand.cs +++ b/ProjectLighthouse/Administration/Maintenance/Commands/ResetPasswordCommand.cs @@ -8,12 +8,12 @@ using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Logging; using LBPUnion.ProjectLighthouse.Types.Maintenance; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.Commands; public class ResetPasswordCommand : ICommand { - private readonly DatabaseContext database = DatabaseContext.CreateNewInstance(); public string Name() => "Reset Password"; public string[] Aliases() => new[] @@ -23,28 +23,28 @@ public class ResetPasswordCommand : ICommand public string Arguments() => " "; public int RequiredArgs() => 2; - public async Task Run(string[] args, Logger logger) + public async Task Run(IServiceProvider provider, string[] args, Logger logger) { - UserEntity? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == args[0]); + DatabaseContext database = provider.GetRequiredService(); + UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == args[0]); if (user == null) - try - { - user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == Convert.ToInt32(args[0])); - if (user == null) throw new Exception(); - } - catch + { + _ = int.TryParse(args[0], out int userId); + user = await database.Users.FirstOrDefaultAsync(u => u.UserId == userId); + if (user == null) { logger.LogError($"Could not find user by parameter '{args[0]}'", LogArea.Command); return; } - + } + string password = args[1]; if (password.Length != 64) password = CryptoHelper.Sha256Hash(password); user.Password = CryptoHelper.BCryptHash(password); user.PasswordResetRequired = true; - await this.database.SaveChangesAsync(); + await database.SaveChangesAsync(); logger.LogSuccess($"The password for user {user.Username} (id: {user.UserId}) has been reset.", LogArea.Command); } diff --git a/ProjectLighthouse/Administration/Maintenance/Commands/TestWebhookCommand.cs b/ProjectLighthouse/Administration/Maintenance/Commands/TestWebhookCommand.cs index 3c65fe36..7d81ce3a 100644 --- a/ProjectLighthouse/Administration/Maintenance/Commands/TestWebhookCommand.cs +++ b/ProjectLighthouse/Administration/Maintenance/Commands/TestWebhookCommand.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Logging; @@ -7,10 +8,6 @@ namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.Commands; public class TestWebhookCommand : ICommand { - public async Task Run(string[] args, Logger logger) - { - await WebhookHelper.SendWebhook("Testing 123", "Someone is testing the Discord webhook from the admin panel."); - } public string Name() => "Test Discord Webhook"; public string[] Aliases() => new[] @@ -19,4 +16,7 @@ public class TestWebhookCommand : ICommand }; public string Arguments() => ""; public int RequiredArgs() => 0; + + public async Task Run(IServiceProvider provider, string[] args, Logger logger) => + await WebhookHelper.SendWebhook("Testing 123", "Someone is testing the Discord webhook from the admin panel."); } \ No newline at end of file diff --git a/ProjectLighthouse/Administration/Maintenance/Commands/WipeTokensForUserCommand.cs b/ProjectLighthouse/Administration/Maintenance/Commands/WipeTokensForUserCommand.cs index 59ec8501..dfc429a4 100644 --- a/ProjectLighthouse/Administration/Maintenance/Commands/WipeTokensForUserCommand.cs +++ b/ProjectLighthouse/Administration/Maintenance/Commands/WipeTokensForUserCommand.cs @@ -1,19 +1,18 @@ #nullable enable using System; -using System.Linq; using System.Threading.Tasks; using LBPUnion.ProjectLighthouse.Database; +using LBPUnion.ProjectLighthouse.Extensions; using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Maintenance; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.Commands; public class WipeTokensForUserCommand : ICommand { - private readonly DatabaseContext database = DatabaseContext.CreateNewInstance(); - public string Name() => "Wipe tokens for user"; public string[] Aliases() => new[] @@ -22,25 +21,24 @@ public class WipeTokensForUserCommand : ICommand }; public string Arguments() => ""; public int RequiredArgs() => 1; - public async Task Run(string[] args, Logger logger) + + public async Task Run(IServiceProvider provider, string[] args, Logger logger) { - UserEntity? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == args[0]); + DatabaseContext database = provider.GetRequiredService(); + UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == args[0]); if (user == null) - try - { - user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == Convert.ToInt32(args[0])); - if (user == null) throw new Exception(); - } - catch + { + _ = int.TryParse(args[0], out int userId); + user = await database.Users.FirstOrDefaultAsync(u => u.UserId == userId); + if (user == null) { Console.WriteLine(@$"Could not find user by parameter '{args[0]}'"); return; } + } - this.database.GameTokens.RemoveRange(this.database.GameTokens.Where(t => t.UserId == user.UserId)); - this.database.WebTokens.RemoveRange(this.database.WebTokens.Where(t => t.UserId == user.UserId)); - - await this.database.SaveChangesAsync(); + await database.GameTokens.RemoveWhere(t => t.UserId == user.UserId); + await database.WebTokens.RemoveWhere(t => t.UserId == user.UserId); Console.WriteLine(@$"Deleted all tokens for {user.Username} (id: {user.UserId})."); } diff --git a/ProjectLighthouse/Administration/Maintenance/MaintenanceHelper.cs b/ProjectLighthouse/Administration/Maintenance/MaintenanceHelper.cs index 1c4af73d..dd17d8e3 100644 --- a/ProjectLighthouse/Administration/Maintenance/MaintenanceHelper.cs +++ b/ProjectLighthouse/Administration/Maintenance/MaintenanceHelper.cs @@ -30,11 +30,11 @@ public static class MaintenanceHelper public static List MigrationTasks { get; } public static List RepeatingTasks { get; } - public static async Task> RunCommand(string[] args) + public static async Task> RunCommand(IServiceProvider provider, string[] args) { if (args.Length < 1) - throw new Exception - ("This should never happen. " + "If it did, its because you tried to run a command before validating that the user actually wants to run one."); + throw new Exception("This should never happen. " + + "If it did, its because you tried to run a command before validating that the user actually wants to run one."); string baseCmd = args[0]; args = args.Skip(1).ToArray(); @@ -44,21 +44,32 @@ public static class MaintenanceHelper InMemoryLogger memoryLogger = new(); logger.AddLogger(memoryLogger); - IEnumerable suitableCommands = Commands.Where - (command => command.Aliases().Any(a => a.ToLower() == baseCmd.ToLower())) - .Where(command => args.Length >= command.RequiredArgs()); - foreach (ICommand command in suitableCommands) + ICommand? command = Commands + .Where(command => + command.Aliases().Any(a => string.Equals(a, baseCmd, StringComparison.CurrentCultureIgnoreCase))) + .FirstOrDefault(command => args.Length >= command.RequiredArgs()); + if (command == null) { - logger.LogInfo("Running command " + command.Name(), LogArea.Command); - - await command.Run(args, logger); + logger.LogError("Failed to find command", LogArea.Command); logger.Flush(); return memoryLogger.Lines; } + try + { + logger.LogInfo("Running command " + command.Name(), LogArea.Command); - logger.LogError("Command not found.", LogArea.Command); - logger.Flush(); - return memoryLogger.Lines; + await command.Run(provider, args, logger); + + logger.Flush(); + return memoryLogger.Lines; + } + catch(Exception e) + { + logger.LogError($"Failed to run command: {e.Message}", LogArea.Command); + logger.LogError(e.ToDetailedException(), LogArea.Command); + logger.Flush(); + return memoryLogger.Lines; + } } public static async Task RunMaintenanceJob(string jobName) @@ -69,9 +80,8 @@ public static class MaintenanceHelper await job.Run(); } - public static async Task RunMigration(IMigrationTask migrationTask, DatabaseContext? database = null) + public static async Task RunMigration(DatabaseContext database, IMigrationTask migrationTask) { - database ??= DatabaseContext.CreateNewInstance(); // Migrations should never be run twice. Debug.Assert(!await database.CompletedMigrations.Has(m => m.MigrationName == migrationTask.GetType().Name)); diff --git a/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/CleanupBrokenPhotosMaintenanceJob.cs b/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/CleanupBrokenPhotosMaintenanceJob.cs index 2e9e02b3..4c69e6e3 100644 --- a/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/CleanupBrokenPhotosMaintenanceJob.cs +++ b/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/CleanupBrokenPhotosMaintenanceJob.cs @@ -14,14 +14,15 @@ namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.MaintenanceJobs; public class CleanupBrokenPhotosMaintenanceJob : IMaintenanceJob { - private readonly DatabaseContext database = DatabaseContext.CreateNewInstance(); public string Name() => "Cleanup Broken Photos"; public string Description() => "Deletes all photos that have missing assets or invalid photo subjects."; [SuppressMessage("ReSharper", "LoopCanBePartlyConvertedToQuery")] public async Task Run() { - foreach (PhotoEntity photo in this.database.Photos) + + await using DatabaseContext database = DatabaseContext.CreateNewInstance(); + foreach (PhotoEntity photo in database.Photos) { bool hashNullOrEmpty = false; bool noHashesExist = false; @@ -44,8 +45,7 @@ public class CleanupBrokenPhotosMaintenanceJob : IMaintenanceJob goto removePhoto; } - hashNullOrEmpty = string.IsNullOrEmpty - (photo.LargeHash) || + hashNullOrEmpty = string.IsNullOrEmpty(photo.LargeHash) || string.IsNullOrEmpty(photo.MediumHash) || string.IsNullOrEmpty(photo.SmallHash) || string.IsNullOrEmpty(photo.PlanHash); @@ -86,18 +86,18 @@ public class CleanupBrokenPhotosMaintenanceJob : IMaintenanceJob Console.WriteLine ( - $"Removing photo (id: {photo.PhotoId}): " + - $"{nameof(hashNullOrEmpty)}: {hashNullOrEmpty}, " + - $"{nameof(noHashesExist)}: {noHashesExist}, " + - $"{nameof(largeHashIsInvalidFile)}: {largeHashIsInvalidFile}, " + - $"{nameof(tooManyPhotoSubjects)}: {tooManyPhotoSubjects}" + - $"{nameof(duplicatePhotoSubjects)}: {duplicatePhotoSubjects}" + - $"{nameof(takenInTheFuture)}: {takenInTheFuture}" + @$"Removing photo (id: {photo.PhotoId}): " + + @$"{nameof(hashNullOrEmpty)}: {hashNullOrEmpty}, " + + @$"{nameof(noHashesExist)}: {noHashesExist}, " + + @$"{nameof(largeHashIsInvalidFile)}: {largeHashIsInvalidFile}, " + + @$"{nameof(tooManyPhotoSubjects)}: {tooManyPhotoSubjects}" + + @$"{nameof(duplicatePhotoSubjects)}: {duplicatePhotoSubjects}" + + @$"{nameof(takenInTheFuture)}: {takenInTheFuture}" ); - this.database.Photos.Remove(photo); + database.Photos.Remove(photo); } - await this.database.SaveChangesAsync(); + await database.SaveChangesAsync(); } } \ No newline at end of file diff --git a/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/DeleteAllTokensMaintenanceJob.cs b/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/DeleteAllTokensMaintenanceJob.cs index 36335b87..579e5eb6 100644 --- a/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/DeleteAllTokensMaintenanceJob.cs +++ b/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/DeleteAllTokensMaintenanceJob.cs @@ -1,23 +1,21 @@ using System; using System.Threading.Tasks; using LBPUnion.ProjectLighthouse.Database; +using LBPUnion.ProjectLighthouse.Extensions; using LBPUnion.ProjectLighthouse.Types.Maintenance; namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.MaintenanceJobs; public class DeleteAllTokensMaintenanceJob : IMaintenanceJob { - private readonly DatabaseContext database = DatabaseContext.CreateNewInstance(); - public string Name() => "Delete ALL Tokens"; public string Description() => "Deletes ALL game tokens and web tokens."; + public async Task Run() { - this.database.GameTokens.RemoveRange(this.database.GameTokens); - this.database.WebTokens.RemoveRange(this.database.WebTokens); - - await this.database.SaveChangesAsync(); - - Console.WriteLine("Deleted ALL tokens."); + await using DatabaseContext database = DatabaseContext.CreateNewInstance(); + await database.GameTokens.RemoveWhere(t => true); + await database.WebTokens.RemoveWhere(t => true); + Console.WriteLine(@"Deleted ALL tokens."); } } \ No newline at end of file diff --git a/ProjectLighthouse/Administration/Maintenance/RepeatingTasks/CleanupRoomsTask.cs b/ProjectLighthouse/Administration/Maintenance/RepeatingTasks/CleanupRoomsTask.cs index 1809d921..84f5da85 100644 --- a/ProjectLighthouse/Administration/Maintenance/RepeatingTasks/CleanupRoomsTask.cs +++ b/ProjectLighthouse/Administration/Maintenance/RepeatingTasks/CleanupRoomsTask.cs @@ -11,5 +11,5 @@ public class CleanupRoomsTask : IRepeatingTask public string Name => "Cleanup Rooms"; public TimeSpan RepeatInterval => TimeSpan.FromSeconds(10); public DateTime LastRan { get; set; } - public Task Run(DatabaseContext database) => RoomHelper.CleanupRooms(); + public Task Run(DatabaseContext database) => RoomHelper.CleanupRooms(database); } \ No newline at end of file diff --git a/ProjectLighthouse/Configuration/ServerStatics.cs b/ProjectLighthouse/Configuration/ServerStatics.cs index 23bb4c16..11a63edd 100644 --- a/ProjectLighthouse/Configuration/ServerStatics.cs +++ b/ProjectLighthouse/Configuration/ServerStatics.cs @@ -1,9 +1,6 @@ #nullable enable using System; using System.Linq; -using LBPUnion.ProjectLighthouse.Database; -using LBPUnion.ProjectLighthouse.Logging; -using LBPUnion.ProjectLighthouse.Types.Logging; using LBPUnion.ProjectLighthouse.Types.Misc; namespace LBPUnion.ProjectLighthouse.Configuration; @@ -12,21 +9,6 @@ public static class ServerStatics { public const int PageSize = 20; - public static bool DbConnected { - get { - try - { - using DatabaseContext db = DatabaseContext.CreateNewInstance(); - return db.Database.CanConnect(); - } - catch(Exception e) - { - Logger.Error(e.ToString(), LogArea.Database); - return false; - } - } - } - // FIXME: This needs to go at some point. public static bool IsUnitTesting => AppDomain.CurrentDomain.GetAssemblies().Any(assembly => assembly.FullName!.StartsWith("xunit")); diff --git a/ProjectLighthouse/Extensions/DatabaseExtensions.cs b/ProjectLighthouse/Extensions/DatabaseExtensions.cs index 86a3ef3a..8a5c5b44 100644 --- a/ProjectLighthouse/Extensions/DatabaseExtensions.cs +++ b/ProjectLighthouse/Extensions/DatabaseExtensions.cs @@ -11,6 +11,13 @@ public static class DatabaseExtensions public static async Task Has(this IQueryable queryable, Expression> predicate) => await queryable.FirstOrDefaultAsync(predicate) != null; - public static async Task RemoveWhere(this DbSet queryable, Expression> predicate) where T : class - => await queryable.Where(predicate).ExecuteDeleteAsync(); + /// + /// Deletes all records matching a given predicate + /// Deletes are executed immediately without calling SaveChanges() + /// + /// The database set to source from + /// The predicate used to determine which records to delete + /// The record type contained within the DbSet + public static async Task RemoveWhere(this DbSet dbSet, Expression> predicate) where T : class + => await dbSet.Where(predicate).ExecuteDeleteAsync(); } \ No newline at end of file diff --git a/ProjectLighthouse/Helpers/RoomHelper.cs b/ProjectLighthouse/Helpers/RoomHelper.cs index 5d98f624..021e86ec 100644 --- a/ProjectLighthouse/Helpers/RoomHelper.cs +++ b/ProjectLighthouse/Helpers/RoomHelper.cs @@ -27,7 +27,7 @@ public static class RoomHelper private static int roomIdIncrement; internal static int RoomIdIncrement => roomIdIncrement++; - public static FindBestRoomResponse? FindBestRoom(UserEntity? user, GameVersion roomVersion, RoomSlot? slot, Platform? platform, string? location) + public static FindBestRoomResponse? FindBestRoom(DatabaseContext database, UserEntity? user, GameVersion roomVersion, RoomSlot? slot, Platform? platform, string? location) { if (roomVersion == GameVersion.LittleBigPlanet1 || roomVersion == GameVersion.LittleBigPlanetPSP) { @@ -87,7 +87,7 @@ public static class RoomHelper Locations = new List(), }; - foreach (UserEntity player in room.GetPlayers(DatabaseContext.CreateNewInstance())) + foreach (UserEntity player in room.GetPlayers(database)) { response.Players.Add ( @@ -157,8 +157,8 @@ public static class RoomHelper RoomVersion = roomVersion, RoomPlatform = roomPlatform, }; - - CleanupRooms(room.HostId, room); + using DatabaseContext database = DatabaseContext.CreateNewInstance(); + CleanupRooms(database, room.HostId, room); lock(RoomLock) Rooms.Add(room); Logger.Info($"Created room (id: {room.RoomId}) for host {room.HostId}", LogArea.Match); @@ -175,20 +175,11 @@ public static class RoomHelper public static Room? FindRoomByUserId(int userId) { - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (Room room in Rooms) - { - if (room.PlayerIds.Any(p => p == userId)) - { - return room; - } - } - - return null; + return Rooms.FirstOrDefault(room => room.PlayerIds.Any(p => p == userId)); } [SuppressMessage("ReSharper", "InvertIf")] - public static Task CleanupRooms(int? hostId = null, Room? newRoom = null, DatabaseContext? database = null) + public static Task CleanupRooms(DatabaseContext database, int? hostId = null, Room? newRoom = null) { #if DEBUG Stopwatch stopwatch = new(); @@ -204,8 +195,6 @@ public static class RoomHelper #endif int roomCountBeforeCleanup = rooms.Count(); - database ??= DatabaseContext.CreateNewInstance(); - // Remove offline players from rooms foreach (Room room in rooms) { diff --git a/ProjectLighthouse/Helpers/StatisticsHelper.cs b/ProjectLighthouse/Helpers/StatisticsHelper.cs index 92e20379..0f0070ab 100644 --- a/ProjectLighthouse/Helpers/StatisticsHelper.cs +++ b/ProjectLighthouse/Helpers/StatisticsHelper.cs @@ -9,7 +9,6 @@ namespace LBPUnion.ProjectLighthouse.Helpers; public static class StatisticsHelper { - public static async Task RecentMatches(DatabaseContext database) => await database.LastContacts.Where(l => TimeHelper.Timestamp - l.Timestamp < 300).CountAsync(); public static async Task RecentMatchesForGame(DatabaseContext database, GameVersion gameVersion) diff --git a/ProjectLighthouse/Logging/Loggers/FileLogger.cs b/ProjectLighthouse/Logging/Loggers/FileLogger.cs index a0f9b28d..f2d33803 100644 --- a/ProjectLighthouse/Logging/Loggers/FileLogger.cs +++ b/ProjectLighthouse/Logging/Loggers/FileLogger.cs @@ -23,6 +23,5 @@ public class FileLogger : ILogger File.AppendAllText(Path.Combine(logsDirectory, "all.log"), contentAll); } catch(IOException) {} // windows, ya goofed - } } \ No newline at end of file diff --git a/ProjectLighthouse/StartupTasks.cs b/ProjectLighthouse/StartupTasks.cs index 9080806f..2fdfc76a 100644 --- a/ProjectLighthouse/StartupTasks.cs +++ b/ProjectLighthouse/StartupTasks.cs @@ -27,7 +27,7 @@ namespace LBPUnion.ProjectLighthouse; public static class StartupTasks { - public static void Run(string[] args, ServerType serverType) + public static async Task Run(ServerType serverType) { // Log startup time Stopwatch stopwatch = new(); @@ -42,7 +42,7 @@ public static class StartupTasks Logger.Info($"Welcome to the Project Lighthouse {serverType.ToString()}!", LogArea.Startup); Logger.Info("Loading configurations...", LogArea.Startup); - if (!loadConfigurations()) + if (!LoadConfigurations()) { Logger.Error("Failed to load one or more configurations", LogArea.Config); Environment.Exit(1); @@ -50,22 +50,26 @@ public static class StartupTasks // Version info depends on ServerConfig Logger.Info($"You are running version {VersionHelper.FullVersion}", LogArea.Startup); - Logger.Info("Connecting to the database...", LogArea.Startup); - bool dbConnected = ServerStatics.DbConnected; - if (!dbConnected) + + await using DatabaseContext database = DatabaseContext.CreateNewInstance(); + try { - Logger.Error("Database unavailable! Exiting.", LogArea.Startup); + if (!await database.Database.CanConnectAsync()) + { + Logger.Error("Database unavailable! Exiting.", LogArea.Startup); + Logger.Error("Ensure that you have set the dbConnectionString field in lighthouse.yml", LogArea.Startup); + Environment.Exit(-1); + } } - else + catch (Exception e) { - Logger.Success("Connected to the database!", LogArea.Startup); + Logger.Error("There was an error connecting to the database:", LogArea.Startup); + Logger.Error(e.ToDetailedException(), LogArea.Startup); + Environment.Exit(-1); } - if (!dbConnected) Environment.Exit(1); - using DatabaseContext database = DatabaseContext.CreateNewInstance(); - - migrateDatabase(database).Wait(); + await MigrateDatabase(database); Logger.Debug ( @@ -76,13 +80,6 @@ public static class StartupTasks ); Logger.Debug("You can do so by running any dotnet command with the flag: \"-c Release\". ", LogArea.Startup); - if (args.Length != 0) - { - List logLines = MaintenanceHelper.RunCommand(args).Result; - Console.WriteLine(logLines.ToLogString()); - return; - } - if (ServerConfiguration.Instance.WebsiteConfiguration.ConvertAssetsOnStartup && serverType == ServerType.Website) { @@ -102,7 +99,7 @@ public static class StartupTasks admin.PermissionLevel = PermissionLevel.Administrator; admin.PasswordResetRequired = true; - database.SaveChanges(); + await database.SaveChangesAsync(); Logger.Success("No users were found, so an admin user was created. " + $"The username is 'admin' and the password is '{passwordClear}'.", LogArea.Startup); @@ -112,7 +109,7 @@ public static class StartupTasks Logger.Success($"Ready! Startup took {stopwatch.ElapsedMilliseconds}ms. Passing off control to ASP.NET...", LogArea.Startup); } - private static bool loadConfigurations() + private static bool LoadConfigurations() { Assembly assembly = Assembly.GetAssembly(typeof(ConfigurationBase<>)); if (assembly == null) return false; @@ -147,7 +144,7 @@ public static class StartupTasks return didLoad; } - private static async Task migrateDatabase(DatabaseContext database) + private static async Task MigrateDatabase(DatabaseContext database) { int? originalTimeout = database.Database.GetCommandTimeout(); database.Database.SetCommandTimeout(TimeSpan.FromMinutes(5)); @@ -179,7 +176,7 @@ public static class StartupTasks foreach (IMigrationTask migrationTask in migrationsToRun) { - MaintenanceHelper.RunMigration(migrationTask, database).Wait(); + MaintenanceHelper.RunMigration(database, migrationTask).Wait(); } stopwatch.Stop(); diff --git a/ProjectLighthouse/Types/Entities/Level/SlotEntity.cs b/ProjectLighthouse/Types/Entities/Level/SlotEntity.cs index 1ab0ec3e..73e84072 100644 --- a/ProjectLighthouse/Types/Entities/Level/SlotEntity.cs +++ b/ProjectLighthouse/Types/Entities/Level/SlotEntity.cs @@ -1,11 +1,9 @@ #nullable enable using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using LBPUnion.ProjectLighthouse.Database; -using LBPUnion.ProjectLighthouse.Types.Entities.Interaction; using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Levels; using LBPUnion.ProjectLighthouse.Types.Misc; @@ -79,21 +77,13 @@ public class SlotEntity public string[] LevelTags(DatabaseContext database) { - if (this.GameVersion != GameVersion.LittleBigPlanet1) return Array.Empty(); - // Sort tags by most popular - SortedDictionary occurrences = new(); - foreach (RatedLevelEntity r in database.RatedLevels.Where(r => r.SlotId == this.SlotId && r.TagLBP1.Length > 0)) - { - if (!occurrences.ContainsKey(r.TagLBP1)) - occurrences.Add(r.TagLBP1, 1); - else - occurrences[r.TagLBP1]++; - } - - return occurrences.OrderBy(r => r.Value).Select(r => r.Key).ToArray(); - + return database.RatedLevels.Where(r => r.SlotId == this.SlotId && r.TagLBP1.Length > 0) + .GroupBy(r => r.TagLBP1) + .OrderByDescending(kvp => kvp.Count()) + .Select(kvp => kvp.Key) + .ToArray(); } public string BackgroundHash { get; set; } = ""; @@ -140,18 +130,6 @@ public class SlotEntity public bool CommentsEnabled { get; set; } = true; - [NotMapped] - public int Hearts => DatabaseContext.CreateNewInstance().HeartedLevels.Count(s => s.SlotId == this.SlotId); - - [NotMapped] - public int Comments => DatabaseContext.CreateNewInstance().Comments.Count(c => c.Type == CommentType.Level && c.TargetId == this.SlotId); - - [NotMapped] - public int Photos => DatabaseContext.CreateNewInstance().Photos.Count(p => p.SlotId == this.SlotId); - - [NotMapped] - public int PhotosWithAuthor => DatabaseContext.CreateNewInstance().Photos.Count(p => p.SlotId == this.SlotId && p.CreatorId == this.CreatorId); - [NotMapped] public int Plays => this.PlaysLBP1 + this.PlaysLBP2 + this.PlaysLBP3; @@ -160,12 +138,4 @@ public class SlotEntity [NotMapped] public int PlaysComplete => this.PlaysLBP1Complete + this.PlaysLBP2Complete + this.PlaysLBP3Complete; - - public double RatingLBP1 => DatabaseContext.CreateNewInstance().RatedLevels.Where(r => r.SlotId == this.SlotId).Average(r => (double?)r.RatingLBP1) ?? 3.0; - - [NotMapped] - public int Thumbsup => DatabaseContext.CreateNewInstance().RatedLevels.Count(r => r.SlotId == this.SlotId && r.Rating == 1); - - [NotMapped] - public int Thumbsdown => DatabaseContext.CreateNewInstance().RatedLevels.Count(r => r.SlotId == this.SlotId && r.Rating == -1); } \ No newline at end of file diff --git a/ProjectLighthouse/Types/Entities/Profile/CommentEntity.cs b/ProjectLighthouse/Types/Entities/Profile/CommentEntity.cs index 5fa73204..ec2cd640 100644 --- a/ProjectLighthouse/Types/Entities/Profile/CommentEntity.cs +++ b/ProjectLighthouse/Types/Entities/Profile/CommentEntity.cs @@ -38,7 +38,7 @@ public class CommentEntity public int ThumbsUp { get; set; } public int ThumbsDown { get; set; } - public string GetCommentMessage() + public string GetCommentMessage(DatabaseContext database) { if (!this.Deleted) { @@ -50,7 +50,6 @@ public class CommentEntity return "This comment has been deleted by the author."; } - using DatabaseContext database = DatabaseContext.CreateNewInstance(); UserEntity deletedBy = database.Users.FirstOrDefault(u => u.Username == this.DeletedBy); if (deletedBy != null && deletedBy.UserId == this.TargetId) diff --git a/ProjectLighthouse/Types/Entities/Profile/UserEntity.cs b/ProjectLighthouse/Types/Entities/Profile/UserEntity.cs index 43e3cec5..d0a9f0fe 100644 --- a/ProjectLighthouse/Types/Entities/Profile/UserEntity.cs +++ b/ProjectLighthouse/Types/Entities/Profile/UserEntity.cs @@ -2,7 +2,6 @@ using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Diagnostics.CodeAnalysis; -using System.Linq; using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Database; using LBPUnion.ProjectLighthouse.Types.Misc; @@ -49,10 +48,6 @@ public class UserEntity } public UserStatus GetStatus(DatabaseContext database) => new(database, this.UserId); - public int GetHeartCount(DatabaseContext database) => database.HeartedProfiles.Count(hp => hp.HeartedUserId == this.UserId); - public int GetCommentCount(DatabaseContext database) => database.Comments.Count(c => c.TargetId == this.UserId && c.Type == CommentType.Profile); - public int GetUsedSlotCount(DatabaseContext database) => database.Slots.Count(s => s.CreatorId == this.UserId); - public int GetUploadedPhotoCount(DatabaseContext database) => database.Photos.Count(p => p.CreatorId == this.UserId); /// /// The location of the profile card on the user's earth diff --git a/ProjectLighthouse/Types/Maintenance/ICommand.cs b/ProjectLighthouse/Types/Maintenance/ICommand.cs index 84a15e7b..c04e5697 100644 --- a/ProjectLighthouse/Types/Maintenance/ICommand.cs +++ b/ProjectLighthouse/Types/Maintenance/ICommand.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using JetBrains.Annotations; using LBPUnion.ProjectLighthouse.Logging; @@ -8,7 +9,7 @@ namespace LBPUnion.ProjectLighthouse.Types.Maintenance; public interface ICommand { public string FirstAlias => this.Aliases()[0]; - public Task Run(string[] args, Logger logger); + public Task Run(IServiceProvider provider, string[] args, Logger logger); public string Name(); diff --git a/ProjectLighthouse/Types/Serialization/GameDeveloperSlot.cs b/ProjectLighthouse/Types/Serialization/GameDeveloperSlot.cs index e1a83115..175fb65b 100644 --- a/ProjectLighthouse/Types/Serialization/GameDeveloperSlot.cs +++ b/ProjectLighthouse/Types/Serialization/GameDeveloperSlot.cs @@ -32,7 +32,8 @@ public class GameDeveloperSlot : SlotBase, INeedsPreparationForSerialization public async Task PrepareSerialization(DatabaseContext database) { - var stats = await database.Slots.Select(_ => new + var stats = await database.Slots.Where(s => s.SlotId == this.InternalSlotId) + .Select(_ => new { CommentCount = database.Comments.Count(c => c.TargetId == this.SlotId && c.Type == CommentType.Level), PhotoCount = database.Photos.Count(p => p.SlotId == this.SlotId), diff --git a/ProjectLighthouse/Types/Serialization/GameUserSlot.cs b/ProjectLighthouse/Types/Serialization/GameUserSlot.cs index 326b7744..d6735b20 100644 --- a/ProjectLighthouse/Types/Serialization/GameUserSlot.cs +++ b/ProjectLighthouse/Types/Serialization/GameUserSlot.cs @@ -235,7 +235,7 @@ public class GameUserSlot : SlotBase, INeedsPreparationForSerialization public async Task PrepareSerialization(DatabaseContext database) { - var stats = await database.Slots + var stats = await database.Slots.Where(s => s.SlotId == this.SlotId) .Select(_ => new { ThumbsUp = database.RatedLevels.Count(r => r.SlotId == this.SlotId && r.Rating == 1), diff --git a/ProjectLighthouse/Types/Serialization/GenericSerializableList.cs b/ProjectLighthouse/Types/Serialization/GenericSerializableList.cs index 7a1fd2b1..985c4a25 100644 --- a/ProjectLighthouse/Types/Serialization/GenericSerializableList.cs +++ b/ProjectLighthouse/Types/Serialization/GenericSerializableList.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Xml.Serialization; using LBPUnion.ProjectLighthouse.Types.Filter;