diff --git a/ProjectLighthouse/Controllers/PhotosController.cs b/ProjectLighthouse/Controllers/PhotosController.cs index 9ce5c655..89c96849 100644 --- a/ProjectLighthouse/Controllers/PhotosController.cs +++ b/ProjectLighthouse/Controllers/PhotosController.cs @@ -1,4 +1,5 @@ #nullable enable +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -39,7 +40,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers photo.CreatorId = user.UserId; photo.Creator = user; - foreach (PhotoSubject subject in photo.Subjects) + foreach (PhotoSubject subject in photo.SubjectsXmlDontUse) // fine for here { subject.User = await this.database.Users.FirstOrDefaultAsync(u => u.Username == subject.Username); @@ -71,15 +72,41 @@ namespace LBPUnion.ProjectLighthouse.Controllers } [HttpGet("photos/by")] - public async Task UserPhotos([FromQuery] string user) + public async Task UserPhotosBy([FromQuery] string user, [FromQuery] int pageStart, [FromQuery] int pageSize) { User? userFromQuery = await this.database.Users.FirstOrDefaultAsync(u => u.Username == user); // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (user == null) return this.NotFound(); - List photos = await this.database.Photos.Where(p => p.CreatorId == userFromQuery.UserId).Take(10).ToListAsync(); + List photos = await this.database.Photos.Where(p => p.CreatorId == userFromQuery.UserId) + .OrderByDescending(s => s.Timestamp) + .Skip(pageStart - 1) + .Take(Math.Min(pageSize, 30)) + .ToListAsync(); string response = photos.Aggregate(string.Empty, (s, photo) => s + photo.Serialize(0)); return this.Ok(LbpSerializer.StringElement("photos", response)); } + + [HttpGet("photos/with")] + public async Task UserPhotosWith([FromQuery] string user, [FromQuery] int pageStart, [FromQuery] int pageSize) + { + User? userFromQuery = await this.database.Users.FirstOrDefaultAsync(u => u.Username == user); + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (user == null) return this.NotFound(); + + List photos = new(); + foreach (Photo photo in this.database.Photos) + { + photos.AddRange(photo.Subjects.Where(subject => subject.User.UserId == userFromQuery.UserId).Select(_ => photo)); + } + + string response = photos.OrderByDescending + (s => s.Timestamp) + .Skip(pageStart - 1) + .Take(Math.Min(pageSize, 30)) + .Aggregate(string.Empty, (s, photo) => s + photo.Serialize(0)); + + return this.Ok(LbpSerializer.StringElement("photos", response)); + } } } \ No newline at end of file diff --git a/ProjectLighthouse/Types/Photo.cs b/ProjectLighthouse/Types/Photo.cs index e6c0f576..48346c7d 100644 --- a/ProjectLighthouse/Types/Photo.cs +++ b/ProjectLighthouse/Types/Photo.cs @@ -33,20 +33,41 @@ namespace LBPUnion.ProjectLighthouse.Types [XmlElement("plan")] public string PlanHash { get; set; } -// [XmlIgnore] -// public int SlotId { get; set; } -// -// [XmlIgnore] -// [ForeignKey(nameof(SlotId))] -// public Slot Slot { get; set; } + [NotMapped] + private List? subjects; - /// - /// Only use when parsing from XML. - /// [NotMapped] [XmlArray("subjects")] [XmlArrayItem("subject")] - public List Subjects { get; set; } + public List SubjectsXmlDontUse { + get => null!; + set => Subjects = value; + } + + [NotMapped] + public List Subjects { + get { + if (this.subjects != null) return this.subjects; + + List response = new(); + using Database database = new(); + + foreach (string idStr in this.PhotoSubjectIds) + { + if (string.IsNullOrEmpty(idStr)) continue; + + if (!int.TryParse(idStr, out int id)) throw new InvalidCastException(idStr + " is not a valid number."); + + PhotoSubject? photoSubject = database.PhotoSubjects.Include(p => p.User).FirstOrDefault(p => p.PhotoSubjectId == id); + if (photoSubject == null) continue; + + response.Add(photoSubject); + } + + return response; + } + set => this.subjects = value; + } [NotMapped] [XmlIgnore] @@ -62,32 +83,11 @@ namespace LBPUnion.ProjectLighthouse.Types [ForeignKey(nameof(CreatorId))] public User Creator { get; set; } - public List GetSubjects() - { - List response = new(); - - using Database database = new(); - - foreach (string idStr in this.PhotoSubjectIds) - { - if (string.IsNullOrEmpty(idStr)) continue; - - if (!int.TryParse(idStr, out int id)) throw new InvalidCastException(idStr + " is not a valid number."); - - PhotoSubject? photoSubject = database.PhotoSubjects.Include(p => p.User).FirstOrDefault(p => p.PhotoSubjectId == id); - if (photoSubject == null) continue; - - response.Add(photoSubject); - } - - return response; - } - public string Serialize(int slotId) { string slot = LbpSerializer.TaggedStringElement("slot", LbpSerializer.StringElement("id", slotId), "type", "user"); - string subjects = this.GetSubjects().Aggregate(string.Empty, (s, subject) => s + subject.Serialize()); + string subjectsAggregate = this.Subjects.Aggregate(string.Empty, (s, subject) => s + subject.Serialize()); string photo = LbpSerializer.StringElement("id", this.PhotoId) + LbpSerializer.StringElement("small", this.SmallHash) + @@ -95,7 +95,7 @@ namespace LBPUnion.ProjectLighthouse.Types LbpSerializer.StringElement("large", this.LargeHash) + LbpSerializer.StringElement("plan", this.PlanHash) + LbpSerializer.StringElement("author", this.CreatorId) + - LbpSerializer.StringElement("subjects", subjects) + + LbpSerializer.StringElement("subjects", subjectsAggregate) + slot; return LbpSerializer.TaggedStringElement("photo", photo, "timestamp", Timestamp * 1000); diff --git a/ProjectLighthouse/Types/User.cs b/ProjectLighthouse/Types/User.cs index 17737855..c148f7d4 100644 --- a/ProjectLighthouse/Types/User.cs +++ b/ProjectLighthouse/Types/User.cs @@ -37,7 +37,12 @@ namespace LBPUnion.ProjectLighthouse.Types } [NotMapped] - public int PhotosWithMeCount { get; set; } + public int PhotosWithMeCount { + get { + using Database database = new(); + return Enumerable.Sum(database.Photos, photo => photo.Subjects.Count(subject => subject.User.UserId == this.UserId)); + } + } public bool CommentsEnabled { get; set; } diff --git a/README.md b/README.md index 25b17a2d..40814d97 100644 --- a/README.md +++ b/README.md @@ -74,11 +74,11 @@ Some modifications may require updates to the database schema. You can automatic ## Compatibility across games and platforms -| Game | Console (PS3/Vita) | Emulator (RPCS3) | Next-Gen (PS4/PS5) | -|----------|-----------------------------------|------------------------------------------------|--------------------| -| LBP1 | Compatible | Incompatible, crashes on entering pod computer | N/A | -| LBP2 | Compatible | Compatible with patched RPCS3 | N/A | -| LBP3 | Somewhat compatible | Somewhat compatible with workaround | Incompatible | -| LBP Vita | Potentially compatible | N/A | N/A | +| Game | Console (PS3/Vita) | Emulator (RPCS3) | Next-Gen (PS4/PS5) | +|----------|-------------------------------------|------------------------------------------------|--------------------| +| LBP1 | Compatible | Incompatible, crashes on entering pod computer | N/A | +| LBP2 | Compatible | Compatible with patched RPCS3 | N/A | +| LBP3 | Somewhat compatible | Somewhat compatible with workaround | Incompatible | +| LBP Vita | Somewhat compatible with workaround | N/A | N/A | Project Lighthouse is still a heavy work in progress, so this is subject to change at any point.