From 9b7686bb91d36e1ce9584747517bbc5cb1e2ab08 Mon Sep 17 00:00:00 2001 From: jvyden Date: Fri, 5 Nov 2021 21:54:43 -0400 Subject: [PATCH] Fully implement photos for users --- .../Controllers/PhotosController.cs | 23 +- ProjectLighthouse/Database.cs | 3 + ...211106010424_AddCreatorToPhoto.Designer.cs | 541 ++++++++++++++++++ .../20211106010424_AddCreatorToPhoto.cs | 49 ++ .../Migrations/DatabaseModelSnapshot.cs | 16 + ProjectLighthouse/Types/Photo.cs | 34 +- ProjectLighthouse/Types/PhotoSubject.cs | 10 + ProjectLighthouse/Types/User.cs | 9 +- 8 files changed, 679 insertions(+), 6 deletions(-) create mode 100644 ProjectLighthouse/Migrations/20211106010424_AddCreatorToPhoto.Designer.cs create mode 100644 ProjectLighthouse/Migrations/20211106010424_AddCreatorToPhoto.cs diff --git a/ProjectLighthouse/Controllers/PhotosController.cs b/ProjectLighthouse/Controllers/PhotosController.cs index 71a80042..97a5d321 100644 --- a/ProjectLighthouse/Controllers/PhotosController.cs +++ b/ProjectLighthouse/Controllers/PhotosController.cs @@ -1,3 +1,4 @@ +#nullable enable using System.Collections.Generic; using System.IO; using System.Linq; @@ -25,14 +26,19 @@ namespace LBPUnion.ProjectLighthouse.Controllers [HttpPost("uploadPhoto")] public async Task UploadPhoto() { + User? user = await this.database.UserFromRequest(this.Request); + if (user == null) return this.StatusCode(403, ""); + this.Request.Body.Position = 0; string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync(); XmlSerializer serializer = new(typeof(Photo)); - Photo photo = (Photo)serializer.Deserialize(new StringReader(bodyString)); - + Photo? photo = (Photo?)serializer.Deserialize(new StringReader(bodyString)); if (photo == null) return this.BadRequest(); + photo.CreatorId = user.UserId; + photo.Creator = user; + foreach (PhotoSubject subject in photo.Subjects) { subject.User = await this.database.Users.FirstOrDefaultAsync(u => u.Username == subject.Username); @@ -59,10 +65,19 @@ namespace LBPUnion.ProjectLighthouse.Controllers [HttpGet("photos/user/{id:int}")] public async Task SlotPhotos(int id) { - List photos = await this.database.Photos.Take(50).ToListAsync(); - + List photos = await this.database.Photos.Take(10).ToListAsync(); string response = photos.Aggregate(string.Empty, (s, photo) => s + photo.Serialize(id)); + return this.Ok(LbpSerializer.StringElement("photos", response)); + } + [HttpGet("photos/by")] + public async Task UserPhotos([FromQuery] string user) + { + User? userFromQuery = await this.database.Users.FirstOrDefaultAsync(u => u.Username == user); + if (user == null) return this.NotFound(); + + List photos = await this.database.Photos.Where(p => p.CreatorId == userFromQuery.UserId).Take(10).ToListAsync(); + string response = photos.Aggregate(string.Empty, (s, photo) => s + photo.Serialize(0)); return this.Ok(LbpSerializer.StringElement("photos", response)); } } diff --git a/ProjectLighthouse/Database.cs b/ProjectLighthouse/Database.cs index 57c9dee5..9d9e880a 100644 --- a/ProjectLighthouse/Database.cs +++ b/ProjectLighthouse/Database.cs @@ -107,6 +107,9 @@ namespace LBPUnion.ProjectLighthouse return (user, token); } + + public async Task PhotoFromSubject(PhotoSubject subject) + => await this.Photos.FirstOrDefaultAsync(p => p.PhotoSubjectIds.Contains(subject.PhotoSubjectId.ToString())); #nullable disable } } \ No newline at end of file diff --git a/ProjectLighthouse/Migrations/20211106010424_AddCreatorToPhoto.Designer.cs b/ProjectLighthouse/Migrations/20211106010424_AddCreatorToPhoto.Designer.cs new file mode 100644 index 00000000..dfaa00d8 --- /dev/null +++ b/ProjectLighthouse/Migrations/20211106010424_AddCreatorToPhoto.Designer.cs @@ -0,0 +1,541 @@ +// +using LBPUnion.ProjectLighthouse; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace ProjectLighthouse.Migrations +{ + [DbContext(typeof(Database))] + [Migration("20211106010424_AddCreatorToPhoto")] + partial class AddCreatorToPhoto + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 64) + .HasAnnotation("ProductVersion", "5.0.11"); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b => + { + b.Property("HeartedProfileId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("HeartedUserId") + .HasColumnType("int"); + + b.Property("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("HeartedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("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("QueuedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("QueuedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("QueuedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b => + { + b.Property("SlotId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuthorLabels") + .HasColumnType("longtext"); + + b.Property("BackgroundHash") + .HasColumnType("longtext"); + + b.Property("CreatorId") + .HasColumnType("int"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("FirstUploaded") + .HasColumnType("bigint"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("IconHash") + .HasColumnType("longtext"); + + b.Property("InitiallyLocked") + .HasColumnType("tinyint(1)"); + + b.Property("LastUpdated") + .HasColumnType("bigint"); + + b.Property("Lbp1Only") + .HasColumnType("tinyint(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("MaximumPlayers") + .HasColumnType("int"); + + b.Property("MinimumPlayers") + .HasColumnType("int"); + + b.Property("MoveRequired") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("ResourceCollection") + .HasColumnType("longtext"); + + b.Property("RootLevel") + .HasColumnType("longtext"); + + b.Property("Shareable") + .HasColumnType("int"); + + b.Property("SubLevel") + .HasColumnType("tinyint(1)"); + + b.Property("TeamPick") + .HasColumnType("tinyint(1)"); + + b.HasKey("SlotId"); + + b.HasIndex("CreatorId"); + + b.HasIndex("LocationId"); + + b.ToTable("Slots"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b => + { + b.Property("PhotoId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatorId") + .HasColumnType("int"); + + b.Property("LargeHash") + .HasColumnType("longtext"); + + b.Property("MediumHash") + .HasColumnType("longtext"); + + b.Property("PhotoSubjectCollection") + .HasColumnType("longtext"); + + b.Property("PlanHash") + .HasColumnType("longtext"); + + b.Property("SmallHash") + .HasColumnType("longtext"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("PhotoId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Photos"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b => + { + b.Property("PhotoSubjectId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Bounds") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("PhotoSubjectId"); + + b.HasIndex("UserId"); + + b.ToTable("PhotoSubjects"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b => + { + b.Property("CommentId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("PosterUserId") + .HasColumnType("int"); + + b.Property("TargetUserId") + .HasColumnType("int"); + + b.Property("ThumbsDown") + .HasColumnType("int"); + + b.Property("ThumbsUp") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("CommentId"); + + b.HasIndex("PosterUserId"); + + b.HasIndex("TargetUserId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("UserId"); + + b.ToTable("LastMatches"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("X") + .HasColumnType("int"); + + b.Property("Y") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b => + { + b.Property("ScoreId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("PlayerIdCollection") + .HasColumnType("longtext"); + + b.Property("Points") + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("ScoreId"); + + b.HasIndex("SlotId"); + + b.ToTable("Scores"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("UserToken") + .HasColumnType("longtext"); + + b.HasKey("TokenId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Biography") + .HasColumnType("longtext"); + + b.Property("BooHash") + .HasColumnType("longtext"); + + b.Property("CommentCount") + .HasColumnType("int"); + + b.Property("CommentsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("FavouriteSlotCount") + .HasColumnType("int"); + + b.Property("FavouriteUserCount") + .HasColumnType("int"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("HeartCount") + .HasColumnType("int"); + + b.Property("IconHash") + .HasColumnType("longtext"); + + b.Property("Lists") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("LolCatFtwCount") + .HasColumnType("int"); + + b.Property("PhotosByMeCount") + .HasColumnType("int"); + + b.Property("PhotosWithMeCount") + .HasColumnType("int"); + + b.Property("Pins") + .HasColumnType("longtext"); + + b.Property("PlanetHash") + .HasColumnType("longtext"); + + b.Property("ReviewCount") + .HasColumnType("int"); + + b.Property("StaffChallengeBronzeCount") + .HasColumnType("int"); + + b.Property("StaffChallengeGoldCount") + .HasColumnType("int"); + + b.Property("StaffChallengeSilverCount") + .HasColumnType("int"); + + b.Property("Username") + .HasColumnType("longtext"); + + b.Property("YayHash") + .HasColumnType("longtext"); + + b.HasKey("UserId"); + + b.HasIndex("LocationId"); + + b.ToTable("Users"); + }); + + 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.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.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.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 + } + } +} diff --git a/ProjectLighthouse/Migrations/20211106010424_AddCreatorToPhoto.cs b/ProjectLighthouse/Migrations/20211106010424_AddCreatorToPhoto.cs new file mode 100644 index 00000000..a87c9eb5 --- /dev/null +++ b/ProjectLighthouse/Migrations/20211106010424_AddCreatorToPhoto.cs @@ -0,0 +1,49 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace ProjectLighthouse.Migrations +{ + public partial class AddCreatorToPhoto : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + // Conflicts with old data. + migrationBuilder.Sql("DELETE FROM Photos;"); + migrationBuilder.Sql("DELETE FROM PhotoSubjects;"); // Also delete PhotoSubjects while we're at it. + + migrationBuilder.AddColumn( + name: "CreatorId", + table: "Photos", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.CreateIndex( + name: "IX_Photos_CreatorId", + table: "Photos", + column: "CreatorId"); + + migrationBuilder.AddForeignKey( + name: "FK_Photos_Users_CreatorId", + table: "Photos", + column: "CreatorId", + principalTable: "Users", + principalColumn: "UserId", + onDelete: ReferentialAction.Cascade); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Photos_Users_CreatorId", + table: "Photos"); + + migrationBuilder.DropIndex( + name: "IX_Photos_CreatorId", + table: "Photos"); + + migrationBuilder.DropColumn( + name: "CreatorId", + table: "Photos"); + } + } +} diff --git a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs index 8667b9da..0b131043 100644 --- a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs +++ b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs @@ -160,6 +160,9 @@ namespace ProjectLighthouse.Migrations .ValueGeneratedOnAdd() .HasColumnType("int"); + b.Property("CreatorId") + .HasColumnType("int"); + b.Property("LargeHash") .HasColumnType("longtext"); @@ -180,6 +183,8 @@ namespace ProjectLighthouse.Migrations b.HasKey("PhotoId"); + b.HasIndex("CreatorId"); + b.ToTable("Photos"); }); @@ -466,6 +471,17 @@ namespace ProjectLighthouse.Migrations b.Navigation("Location"); }); + 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") diff --git a/ProjectLighthouse/Types/Photo.cs b/ProjectLighthouse/Types/Photo.cs index 8f76675d..ed3af1fd 100644 --- a/ProjectLighthouse/Types/Photo.cs +++ b/ProjectLighthouse/Types/Photo.cs @@ -1,8 +1,11 @@ +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; using System.Xml.Serialization; using LBPUnion.ProjectLighthouse.Serialization; +using Microsoft.EntityFrameworkCore; namespace LBPUnion.ProjectLighthouse.Types { @@ -53,16 +56,45 @@ namespace LBPUnion.ProjectLighthouse.Types public string PhotoSubjectCollection { get; set; } + public int CreatorId { get; set; } + + [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 photo = LbpSerializer.StringElement("id", this.PhotoId) + LbpSerializer.StringElement("small", this.SmallHash) + LbpSerializer.StringElement("medium", this.MediumHash) + LbpSerializer.StringElement("large", this.LargeHash) + LbpSerializer.StringElement("plan", this.PlanHash) + - LbpSerializer.StringElement("author", "a43243221") + + LbpSerializer.StringElement("author", this.CreatorId) + + LbpSerializer.StringElement("subjects", subjects) + slot; return LbpSerializer.TaggedStringElement("photo", photo, "timestamp", Timestamp * 1000); diff --git a/ProjectLighthouse/Types/PhotoSubject.cs b/ProjectLighthouse/Types/PhotoSubject.cs index 74b09dbb..04512010 100644 --- a/ProjectLighthouse/Types/PhotoSubject.cs +++ b/ProjectLighthouse/Types/PhotoSubject.cs @@ -2,6 +2,7 @@ using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Xml.Serialization; +using LBPUnion.ProjectLighthouse.Serialization; namespace LBPUnion.ProjectLighthouse.Types { @@ -27,5 +28,14 @@ namespace LBPUnion.ProjectLighthouse.Types [XmlElement("bounds")] public string Bounds { get; set; } + + public string Serialize() + { + string response = LbpSerializer.StringElement("npHandle", User.Username) + + LbpSerializer.StringElement("displayName", User.Username) + + LbpSerializer.StringElement("bounds", Bounds); + + return LbpSerializer.StringElement("subject", response); + } } } \ No newline at end of file diff --git a/ProjectLighthouse/Types/User.cs b/ProjectLighthouse/Types/User.cs index f3c9c4f1..747964a7 100644 --- a/ProjectLighthouse/Types/User.cs +++ b/ProjectLighthouse/Types/User.cs @@ -27,7 +27,14 @@ namespace LBPUnion.ProjectLighthouse.Types public int ReviewCount { get; set; } public int CommentCount { get; set; } - public int PhotosByMeCount { get; set; } + + public int PhotosByMeCount { + get { + using Database database = new(); + return database.Photos.Count(p => p.CreatorId == this.UserId); + } + } + public int PhotosWithMeCount { get; set; } public bool CommentsEnabled { get; set; }