diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d369ebe..8ee41701 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,17 +36,10 @@ jobs: if: ${{ matrix.os.database }} run: mysql -u${{ env.DB_USER }} -p${{ env.DB_PASSWORD }} -h 127.0.0.1 -e "CREATE DATABASE ${{ env.DB_DATABASE }};"; - - name: Install .NET 5.0 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: "5.0.x" - include-prerelease: true - - - name: Install .NET 6.0 Preview + - name: Install .NET 6.0 uses: actions/setup-dotnet@v1 with: dotnet-version: "6.0.x" - include-prerelease: true - name: Compile run: dotnet build -c Debug diff --git a/ProjectLighthouse.Tests/ProjectLighthouse.Tests.csproj b/ProjectLighthouse.Tests/ProjectLighthouse.Tests.csproj index 11c5fc86..fdc17caa 100644 --- a/ProjectLighthouse.Tests/ProjectLighthouse.Tests.csproj +++ b/ProjectLighthouse.Tests/ProjectLighthouse.Tests.csproj @@ -5,7 +5,7 @@ false - net5.0;net6.0 + net6.0 LBPUnion.ProjectLighthouse.Tests diff --git a/ProjectLighthouse.sln.DotSettings b/ProjectLighthouse.sln.DotSettings index ab04bcc9..c935d98b 100644 --- a/ProjectLighthouse.sln.DotSettings +++ b/ProjectLighthouse.sln.DotSettings @@ -73,6 +73,7 @@ UseExplicitType LBP MM + NAT NP <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="aaBb" /></Policy> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> diff --git a/ProjectLighthouse/Controllers/ClientConfigurationController.cs b/ProjectLighthouse/Controllers/ClientConfigurationController.cs index fc12c2e7..d54d0c7d 100644 --- a/ProjectLighthouse/Controllers/ClientConfigurationController.cs +++ b/ProjectLighthouse/Controllers/ClientConfigurationController.cs @@ -17,7 +17,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers HostString hostname = this.Request.Host; return this.Ok ( - "ProbabilityOfPacketDelay 0.0\nMinPacketDelayFrames 0\nMaxPacketDelayFrames 3\nProbabilityOfPacketDrop 0.0\nEnableFakeConditionsForLoopback true\nNumberOfFramesPredictionAllowedForNonLocalPlayer 1000\nEnablePrediction true\nMinPredictedFrames 0\nMaxPredictedFrames 10\nAllowGameRendCameraSplit true\nFramesBeforeAgressiveCatchup 30\nPredictionPadSides 200\nPredictionPadTop 200\nPredictionPadBottom 200\nShowErrorNumbers true\nAllowModeratedLevels true\nAllowModeratedPoppetItems true\nShowLevelBoos true\nTIMEOUT_WAIT_FOR_JOIN_RESPONSE_FROM_PREV_PARTY_HOST 50.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_HOST 30.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_MEMBER 45.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN_FRIEND 15.0\nTIMEOUT_WAIT_FOR_CONNECTION_FROM_HOST 30.0\nTIMEOUT_WAIT_FOR_ROOM_ID_TO_JOIN 60.0\nTIMEOUT_WAIT_FOR_GET_NUM_PLAYERS_ONLINE 60.0\nTIMEOUT_WAIT_FOR_SIGNALLING_CONNECTIONS 120.0\nTIMEOUT_WAIT_FOR_PARTY_DATA 60.0\nTIME_TO_WAIT_FOR_LEAVE_MESSAGE_TO_COME_BACK 20.0\nTIME_TO_WAIT_FOR_FOLLOWING_REQUESTS_TO_ARRIVE 30.0\nTIMEOUT_WAIT_FOR_FINISHED_MIGRATING_HOST 30.0\nTIMEOUT_WAIT_FOR_PARTY_LEADER_FINISH_JOINING 45.0\nTIMEOUT_WAIT_FOR_QUICKPLAY_LEVEL 60.0\nTIMEOUT_WAIT_FOR_PLAYERS_TO_JOIN 30.0\nTIMEOUT_WAIT_FOR_DIVE_IN_PLAYERS 120.0\nTIMEOUT_WAIT_FOR_FIND_BEST_ROOM 30.0\nTIMEOUT_DIVE_IN_TOTAL 1000000.0\nTIMEOUT_WAIT_FOR_SOCKET_CONNECTION 120.0\nTIMEOUT_WAIT_FOR_REQUEST_RESOURCE_MESSAGE 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_GET_RESOURCE_LIST 120.0\nTIMEOUT_WAIT_FOR_CLIENT_TO_LOAD_RESOURCES 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_SAVE_GAME_STATE 30.0\nTIMEOUT_WAIT_FOR_ADD_PLAYERS_TO_TAKE 30.0\nTIMEOUT_WAIT_FOR_UPDATE_FROM_CLIENT 90.0\nTIMEOUT_WAIT_FOR_HOST_TO_GET_RESOURCE_LIST 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_SAVE_GAME_STATE 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_ADD_US 30.0\nTIMEOUT_WAIT_FOR_UPDATE 60.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN 50.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_PRESENCE 60.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_CONNECTION 120.0\nSECONDS_BETWEEN_PINS_AWARDED_UPLOADS 300.0\nEnableKeepAlive true\nAllowVoIPRecordingPlayback true\nCDNHostName localhost\nTelemetryServer localhost\nOverheatingThresholdDisallowMidgameJoin 0.95\nMaxCatchupFrames 3\nMaxLagBeforeShowLoading 23\nMinLagBeforeHideLoading 30\nLagImprovementInflectionPoint -1.0\nFlickerThreshold 2.0\nClosedDemo2014Version 1\nClosedDemo2014Expired false\nEnablePlayedFilter true\nEnableCommunityDecorations true\nGameStateUpdateRate 10.0\nGameStateUpdateRateWithConsumers 1.0\nDisableDLCPublishCheck false\nEnableDiveIn true\nEnableHackChecks false\n" + + "ProbabilityOfPacketDelay 0.0\nMinPacketDelayFrames 0\nMaxPacketDelayFrames 3\nProbabilityOfPacketDrop 0.0\nEnableFakeConditionsForLoopback true\nNumberOfFramesPredictionAllowedForNonLocalPlayer 1000\nEnablePrediction true\nMinPredictedFrames 0\nMaxPredictedFrames 10\nAllowGameRendCameraSplit true\nFramesBeforeAgressiveCatchup 30\nPredictionPadSides 200\nPredictionPadTop 200\nPredictionPadBottom 200\nShowErrorNumbers true\nAllowModeratedLevels true\nAllowModeratedPoppetItems true\nShowLevelBoos true\nTIMEOUT_WAIT_FOR_JOIN_RESPONSE_FROM_PREV_PARTY_HOST 50.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_HOST 30.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_MEMBER 45.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN_FRIEND 15.0\nTIMEOUT_WAIT_FOR_CONNECTION_FROM_HOST 30.0\nTIMEOUT_WAIT_FOR_ROOM_ID_TO_JOIN 60.0\nTIMEOUT_WAIT_FOR_GET_NUM_PLAYERS_ONLINE 60.0\nTIMEOUT_WAIT_FOR_SIGNALLING_CONNECTIONS 120.0\nTIMEOUT_WAIT_FOR_PARTY_DATA 60.0\nTIME_TO_WAIT_FOR_LEAVE_MESSAGE_TO_COME_BACK 20.0\nTIME_TO_WAIT_FOR_FOLLOWING_REQUESTS_TO_ARRIVE 30.0\nTIMEOUT_WAIT_FOR_FINISHED_MIGRATING_HOST 30.0\nTIMEOUT_WAIT_FOR_PARTY_LEADER_FINISH_JOINING 45.0\nTIMEOUT_WAIT_FOR_QUICKPLAY_LEVEL 60.0\nTIMEOUT_WAIT_FOR_PLAYERS_TO_JOIN 30.0\nTIMEOUT_WAIT_FOR_DIVE_IN_PLAYERS 240.0\nTIMEOUT_WAIT_FOR_FIND_BEST_ROOM 60.0\nTIMEOUT_DIVE_IN_TOTAL 300.0\nTIMEOUT_WAIT_FOR_SOCKET_CONNECTION 120.0\nTIMEOUT_WAIT_FOR_REQUEST_RESOURCE_MESSAGE 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_GET_RESOURCE_LIST 120.0\nTIMEOUT_WAIT_FOR_CLIENT_TO_LOAD_RESOURCES 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_SAVE_GAME_STATE 30.0\nTIMEOUT_WAIT_FOR_ADD_PLAYERS_TO_TAKE 30.0\nTIMEOUT_WAIT_FOR_UPDATE_FROM_CLIENT 90.0\nTIMEOUT_WAIT_FOR_HOST_TO_GET_RESOURCE_LIST 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_SAVE_GAME_STATE 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_ADD_US 30.0\nTIMEOUT_WAIT_FOR_UPDATE 60.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN 50.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_PRESENCE 60.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_CONNECTION 120.0\nSECONDS_BETWEEN_PINS_AWARDED_UPLOADS 300.0\nEnableKeepAlive true\nAllowVoIPRecordingPlayback true\nCDNHostName localhost\nTelemetryServer localhost\nOverheatingThresholdDisallowMidgameJoin 0.95\nMaxCatchupFrames 3\nMaxLagBeforeShowLoading 23\nMinLagBeforeHideLoading 30\nLagImprovementInflectionPoint -1.0\nFlickerThreshold 2.0\nClosedDemo2014Version 1\nClosedDemo2014Expired false\nEnablePlayedFilter true\nEnableCommunityDecorations true\nGameStateUpdateRate 10.0\nGameStateUpdateRateWithConsumers 1.0\nDisableDLCPublishCheck false\nEnableDiveIn true\nEnableHackChecks false\n" + $"TelemetryServer {hostname}\nCDNHostName {hostname}" ); } diff --git a/ProjectLighthouse/Controllers/FriendsController.cs b/ProjectLighthouse/Controllers/FriendsController.cs index 6cd14fce..aea7a0d2 100644 --- a/ProjectLighthouse/Controllers/FriendsController.cs +++ b/ProjectLighthouse/Controllers/FriendsController.cs @@ -74,7 +74,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers if (!FriendHelper.FriendIdsByUserId.TryGetValue(user.UserId, out int[]? friendIds) || friendIds == null) { - return this.NotFound(); + return this.Ok(LbpSerializer.BlankElement("myFriends")); } string friends = ""; diff --git a/ProjectLighthouse/Controllers/LoginController.cs b/ProjectLighthouse/Controllers/LoginController.cs index c0e88d38..420f8b17 100644 --- a/ProjectLighthouse/Controllers/LoginController.cs +++ b/ProjectLighthouse/Controllers/LoginController.cs @@ -1,5 +1,6 @@ #nullable enable using System.IO; +using System.Net; using System.Threading.Tasks; using Kettu; using LBPUnion.ProjectLighthouse.Logging; @@ -39,7 +40,12 @@ namespace LBPUnion.ProjectLighthouse.Controllers } if (loginData == null) return this.BadRequest(); - Token? token = await this.database.AuthenticateUser(loginData, titleId); + IPAddress? ipAddress = this.HttpContext.Connection.RemoteIpAddress; + if (ipAddress == null) return this.StatusCode(403, ""); // 403 probably isnt the best status code for this, but whatever + + string userLocation = ipAddress.ToString(); + + Token? token = await this.database.AuthenticateUser(loginData, userLocation, titleId); if (token == null) return this.StatusCode(403, ""); Logger.Log diff --git a/ProjectLighthouse/Controllers/MatchController.cs b/ProjectLighthouse/Controllers/MatchController.cs index e69f6311..dc62e6c9 100644 --- a/ProjectLighthouse/Controllers/MatchController.cs +++ b/ProjectLighthouse/Controllers/MatchController.cs @@ -2,11 +2,11 @@ using System; using System.IO; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Kettu; using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Types; -using LBPUnion.ProjectLighthouse.Types.Levels; using LBPUnion.ProjectLighthouse.Types.Match; using LBPUnion.ProjectLighthouse.Types.Profiles; using Microsoft.AspNetCore.Mvc; @@ -27,13 +27,16 @@ namespace LBPUnion.ProjectLighthouse.Controllers } [HttpPost("match")] - [Produces("text/json")] + [Produces("text/plain")] public async Task Match() { + (User, Token)? userAndToken = await this.database.UserAndTokenFromRequest(this.Request); - User? user = await this.database.UserFromRequest(this.Request); + if (userAndToken == null) return this.StatusCode(403, ""); - if (user == null) return this.StatusCode(403, ""); + // ReSharper disable once PossibleInvalidOperationException + User user = userAndToken.Value.Item1; + Token token = userAndToken.Value.Item2; #region Parse match data @@ -61,25 +64,30 @@ namespace LBPUnion.ProjectLighthouse.Controllers #endregion #region Process match data - /* - if (matchData is CreateRoom createRoom) + + if (matchData is UpdateMyPlayerData) MatchHelper.SetUserLocation(user.UserId, token.UserLocation); + + if (matchData is FindBestRoom && MatchHelper.UserLocations.Count > 1) { - if (createRoom.Slots.Count == 0) return this.BadRequest(); - if (createRoom.FirstSlot.Count != 2) return this.BadRequest(); - - int slotType = createRoom.FirstSlot[0]; - int slotId = createRoom.FirstSlot[1]; - - if (slotType == 1) + foreach ((int id, string? location) in MatchHelper.UserLocations) { - Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slotId); - if (slot == null) return this.BadRequest(); + if (id == user.UserId) continue; + if (location == null) continue; + if (MatchHelper.DidUserRecentlyDiveInWith(user.UserId, id)) continue; - slot.Plays++; - await this.database.SaveChangesAsync(); + User? otherUser = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == id); + if (otherUser == null) continue; + + FindBestRoomResponse response = MatchHelper.FindBestRoomResponse(user.Username, otherUser.Username, token.UserLocation, location); + + string serialized = JsonSerializer.Serialize(response, typeof(FindBestRoomResponse)); + + MatchHelper.AddUserRecentlyDivedIn(user.UserId, id); + + return new ObjectResult($"[{{\"StatusCode\":200}},{serialized}]"); } } - */ + #endregion #region Update LastMatch diff --git a/ProjectLighthouse/Controllers/PhotosController.cs b/ProjectLighthouse/Controllers/PhotosController.cs index af1c7622..d5559365 100644 --- a/ProjectLighthouse/Controllers/PhotosController.cs +++ b/ProjectLighthouse/Controllers/PhotosController.cs @@ -71,7 +71,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers [HttpGet("photos/user/{id:int}")] public async Task SlotPhotos(int id) { - List photos = await this.database.Photos.Take(10).ToListAsync(); + List photos = await this.database.Photos.Include(p => p.Creator).Take(10).ToListAsync(); string response = photos.Aggregate(string.Empty, (s, photo) => s + photo.Serialize(id)); return this.Ok(LbpSerializer.StringElement("photos", response)); } @@ -83,7 +83,9 @@ namespace LBPUnion.ProjectLighthouse.Controllers // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (user == null) return this.NotFound(); - List photos = await this.database.Photos.Where(p => p.CreatorId == userFromQuery.UserId) + List photos = await this.database.Photos.Include + (p => p.Creator) + .Where(p => p.CreatorId == userFromQuery.UserId) .OrderByDescending(s => s.Timestamp) .Skip(pageStart - 1) .Take(Math.Min(pageSize, 30)) @@ -100,7 +102,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers if (user == null) return this.NotFound(); List photos = new(); - foreach (Photo photo in this.database.Photos) + foreach (Photo photo in this.database.Photos.Include(p => p.Creator)) { photos.AddRange(photo.Subjects.Where(subject => subject.User.UserId == userFromQuery.UserId).Select(_ => photo)); } @@ -113,5 +115,20 @@ namespace LBPUnion.ProjectLighthouse.Controllers return this.Ok(LbpSerializer.StringElement("photos", response)); } + + [HttpPost("deletePhoto/{id:int}")] + public async Task DeletePhoto(int id) + { + User? user = await this.database.UserFromRequest(this.Request); + if (user == null) return this.StatusCode(403, ""); + + Photo? photo = await this.database.Photos.FirstOrDefaultAsync(p => p.PhotoId == id); + if (photo == null) return this.NotFound(); + if (photo.CreatorId != user.UserId) return this.StatusCode(401, ""); + + this.database.Photos.Remove(photo); + await this.database.SaveChangesAsync(); + return this.Ok(); + } } } \ No newline at end of file diff --git a/ProjectLighthouse/Database.cs b/ProjectLighthouse/Database.cs index fce30fd4..20898272 100644 --- a/ProjectLighthouse/Database.cs +++ b/ProjectLighthouse/Database.cs @@ -55,7 +55,7 @@ namespace LBPUnion.ProjectLighthouse } #nullable enable - public async Task AuthenticateUser(LoginData loginData, string titleId = "") + public async Task AuthenticateUser(LoginData loginData, string userLocation, string titleId = "") { // TODO: don't use psn name to authenticate User user = await this.Users.FirstOrDefaultAsync(u => u.Username == loginData.Username) ?? await this.CreateUser(loginData.Username); @@ -64,6 +64,7 @@ namespace LBPUnion.ProjectLighthouse { UserToken = HashHelper.GenerateAuthToken(), UserId = user.UserId, + UserLocation = userLocation, GameVersion = GameVersionHelper.FromTitleId(titleId), }; diff --git a/ProjectLighthouse/Helpers/FileHelper.cs b/ProjectLighthouse/Helpers/FileHelper.cs index 62d9f06b..f519effa 100644 --- a/ProjectLighthouse/Helpers/FileHelper.cs +++ b/ProjectLighthouse/Helpers/FileHelper.cs @@ -27,6 +27,7 @@ namespace LBPUnion.ProjectLighthouse.Helpers LbpFileType.Voice => true, LbpFileType.Plan => true, LbpFileType.Jpeg => true, + LbpFileType.Png => true, #if DEBUG _ => throw new ArgumentOutOfRangeException(nameof(file), $"Unhandled file type ({file.FileType}) in FileHelper.IsFileSafe()"), #else @@ -66,10 +67,11 @@ namespace LBPUnion.ProjectLighthouse.Helpers { reader.BaseStream.Position = 0; - // Determine if file is JPEG + // Determine if file is JPEG/PNG byte[] header = reader.ReadBytes(9); if (header[0] == 0xFF && header[1] == 0xD8 && header[2] == 0xFF && header[3] == 0xE0) return LbpFileType.Jpeg; + if (header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47) return LbpFileType.Png; return LbpFileType.Unknown; // Still unknown. } diff --git a/ProjectLighthouse/Helpers/MatchHelper.cs b/ProjectLighthouse/Helpers/MatchHelper.cs index b60a3891..b3017e2a 100644 --- a/ProjectLighthouse/Helpers/MatchHelper.cs +++ b/ProjectLighthouse/Helpers/MatchHelper.cs @@ -1,5 +1,7 @@ #nullable enable using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text.Json; using System.Text.RegularExpressions; @@ -9,6 +11,65 @@ namespace LBPUnion.ProjectLighthouse.Helpers { public static class MatchHelper { + public static readonly Dictionary UserLocations = new(); + public static readonly Dictionary?> UserRecentlyDivedIn = new(); + + public static void SetUserLocation(int userId, string location) + { + if (UserLocations.TryGetValue(userId, out string? _)) UserLocations.Remove(userId); + UserLocations.Add(userId, location); + } + + public static void AddUserRecentlyDivedIn(int userId, int otherUserId) + { + if (!UserRecentlyDivedIn.TryGetValue(userId, out List? recentlyDivedIn)) + { + UserRecentlyDivedIn.Add(userId, recentlyDivedIn = new List()); + } + + Debug.Assert(recentlyDivedIn != null, nameof(recentlyDivedIn) + " is null, somehow."); + + recentlyDivedIn.Add(otherUserId); + } + + public static bool DidUserRecentlyDiveInWith(int userId, int otherUserId) + { + if (!UserRecentlyDivedIn.TryGetValue(userId, out List? recentlyDivedIn) || recentlyDivedIn == null) return false; + + return recentlyDivedIn.Contains(otherUserId); + } + + public static FindBestRoomResponse FindBestRoomResponse(string username, string otherUsername, string location, string otherLocation) + => new() + { + Players = new List + { + new() + { + MatchingRes = 0, + PlayerId = otherUsername, + }, + new() + { + MatchingRes = 1, + PlayerId = username, + }, + }, + Locations = new List + { + location, + otherLocation, + }, + Slots = new List> + { + new() + { + 5, + 0, + }, + }, + }; + public static IMatchData? Deserialize(string data) { string matchType = ""; @@ -37,6 +98,7 @@ namespace LBPUnion.ProjectLighthouse.Helpers "UpdateMyPlayerData" => JsonSerializer.Deserialize(matchData), "UpdatePlayersInRoom" => JsonSerializer.Deserialize(matchData), "CreateRoom" => JsonSerializer.Deserialize(matchData), + "FindBestRoom" => JsonSerializer.Deserialize(matchData), _ => null, }; } diff --git a/ProjectLighthouse/Migrations/20211113091631_AddUserLocationToToken.Designer.cs b/ProjectLighthouse/Migrations/20211113091631_AddUserLocationToToken.Designer.cs new file mode 100644 index 00000000..76be44ce --- /dev/null +++ b/ProjectLighthouse/Migrations/20211113091631_AddUserLocationToToken.Designer.cs @@ -0,0 +1,638 @@ +// +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("20211113091631_AddUserLocationToToken")] + partial class AddUserLocationToToken + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 64) + .HasAnnotation("ProductVersion", "5.0.12"); + + 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.RatedLevel", b => + { + b.Property("RatedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Rating") + .HasColumnType("int"); + + b.Property("RatingLBP1") + .HasColumnType("double"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("RatedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("RatedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b => + { + b.Property("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("LevelType") + .HasColumnType("longtext"); + + 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("PlaysLBP1") + .HasColumnType("int"); + + b.Property("PlaysLBP1Complete") + .HasColumnType("int"); + + b.Property("PlaysLBP1Unique") + .HasColumnType("int"); + + b.Property("PlaysLBP2") + .HasColumnType("int"); + + b.Property("PlaysLBP2Complete") + .HasColumnType("int"); + + b.Property("PlaysLBP2Unique") + .HasColumnType("int"); + + b.Property("PlaysLBP3") + .HasColumnType("int"); + + b.Property("PlaysLBP3Complete") + .HasColumnType("int"); + + b.Property("PlaysLBP3Unique") + .HasColumnType("int"); + + 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.Levels.VisitedLevel", b => + { + b.Property("VisitedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("VisitedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("VisitedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b => + { + b.Property("PhotoId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatorId") + .HasColumnType("int"); + + b.Property("LargeHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MediumHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PhotoSubjectCollection") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PlanHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SmallHash") + .IsRequired() + .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("UserLocation") + .HasColumnType("longtext"); + + 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("Game") + .HasColumnType("int"); + + b.Property("IconHash") + .HasColumnType("longtext"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Pins") + .HasColumnType("longtext"); + + b.Property("PlanetHash") + .HasColumnType("longtext"); + + 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.RatedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster") + .WithMany() + .HasForeignKey("PosterUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target") + .WithMany() + .HasForeignKey("TargetUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Poster"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.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/20211113091631_AddUserLocationToToken.cs b/ProjectLighthouse/Migrations/20211113091631_AddUserLocationToToken.cs new file mode 100644 index 00000000..cf74125f --- /dev/null +++ b/ProjectLighthouse/Migrations/20211113091631_AddUserLocationToToken.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace ProjectLighthouse.Migrations +{ + public partial class AddUserLocationToToken : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UserLocation", + table: "Tokens", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UserLocation", + table: "Tokens"); + } + } +} diff --git a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs index 80cbef7e..a08c6227 100644 --- a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs +++ b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs @@ -394,6 +394,9 @@ namespace ProjectLighthouse.Migrations b.Property("UserId") .HasColumnType("int"); + b.Property("UserLocation") + .HasColumnType("longtext"); + b.Property("UserToken") .HasColumnType("longtext"); diff --git a/ProjectLighthouse/ProjectLighthouse.csproj b/ProjectLighthouse/ProjectLighthouse.csproj index b6275a8d..89eb6c44 100644 --- a/ProjectLighthouse/ProjectLighthouse.csproj +++ b/ProjectLighthouse/ProjectLighthouse.csproj @@ -2,7 +2,7 @@ Linux - net5.0;net6.0 + net6.0 LBPUnion.ProjectLighthouse LBPUnion.ProjectLighthouse diff --git a/ProjectLighthouse/Serialization/JsonOutputFormatter.cs b/ProjectLighthouse/Serialization/JsonOutputFormatter.cs new file mode 100644 index 00000000..1e5ea291 --- /dev/null +++ b/ProjectLighthouse/Serialization/JsonOutputFormatter.cs @@ -0,0 +1,13 @@ +using Microsoft.AspNetCore.Mvc.Formatters; + +namespace LBPUnion.ProjectLighthouse.Serialization +{ + public class JsonOutputFormatter : StringOutputFormatter + { + public JsonOutputFormatter() + { + this.SupportedMediaTypes.Add("text/json"); + this.SupportedMediaTypes.Add("application/json"); + } + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Startup.cs b/ProjectLighthouse/Startup.cs index 63befbb2..fe0cdd4a 100644 --- a/ProjectLighthouse/Startup.cs +++ b/ProjectLighthouse/Startup.cs @@ -8,6 +8,7 @@ using LBPUnion.ProjectLighthouse.Serialization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.HttpOverrides; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -29,9 +30,24 @@ namespace LBPUnion.ProjectLighthouse { services.AddControllers(); - services.AddMvc(options => options.OutputFormatters.Add(new XmlOutputFormatter())); + services.AddMvc + ( + options => + { + options.OutputFormatters.Add(new XmlOutputFormatter()); + options.OutputFormatters.Add(new JsonOutputFormatter()); + } + ); services.AddDbContext(); + + services.Configure + ( + options => + { + options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; + } + ); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -51,6 +67,8 @@ namespace LBPUnion.ProjectLighthouse if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); + app.UseForwardedHeaders(); + // Logs every request and the response to it // Example: "200, 13ms: GET /LITTLEBIGPLANETPS3_XML/news" // Example: "404, 127ms: GET /asdasd?query=osucookiezi727ppbluezenithtopplayhdhr" diff --git a/ProjectLighthouse/Types/Files/LbpFileType.cs b/ProjectLighthouse/Types/Files/LbpFileType.cs index abf4de65..69ba34e7 100644 --- a/ProjectLighthouse/Types/Files/LbpFileType.cs +++ b/ProjectLighthouse/Types/Files/LbpFileType.cs @@ -9,7 +9,8 @@ namespace LBPUnion.ProjectLighthouse.Types.Files Plan, // PLN, uploaded with levels Voice, // VOP, voice data Painting, // PTG, paintings - Jpeg, // JFIF / FIF, used in sticker switches + Jpeg, // JFIF / FIF, used in sticker switches, + Png, // used in LBP Vita Unknown, } } \ No newline at end of file diff --git a/ProjectLighthouse/Types/Levels/SlotType.cs b/ProjectLighthouse/Types/Levels/SlotType.cs new file mode 100644 index 00000000..83689c1a --- /dev/null +++ b/ProjectLighthouse/Types/Levels/SlotType.cs @@ -0,0 +1,13 @@ +namespace LBPUnion.ProjectLighthouse.Types.Levels +{ + public enum SlotType + { + Developer = 0, + User = 1, + Moon = 2, + Unknown = 3, + Unknown2 = 4, + Pod = 5, + DLC = 8, + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Types/Match/CreateRoom.cs b/ProjectLighthouse/Types/Match/CreateRoom.cs index 54c86276..371acad9 100644 --- a/ProjectLighthouse/Types/Match/CreateRoom.cs +++ b/ProjectLighthouse/Types/Match/CreateRoom.cs @@ -9,16 +9,20 @@ namespace LBPUnion.ProjectLighthouse.Types.Match { //[CreateRoom,["Players":["LumaLivy"],"Reservations":["0"],"NAT":[2],"Slots":[[1,3]],"RoomState":0,"HostMood":1,"PassedNoJoinPoint":0,"Location":[0x7f000001],"Language":1,"BuildVersion":289,"Search":""]] public List Players { get; set; } + public List Reservations { get; set; } + // v slot type, 1 = 2974 // "Slots":[[5,0]] // ^ slot id // no idea why this is an array, but we'll work with it i suppose public List> Slots { get; set; } + [JsonIgnore] - public List FirstSlot => this.Slots[0]; + public IEnumerable FirstSlot => this.Slots[0]; + public List NAT; - public int RoomState; + public RoomState RoomState; public int HostMood; public int PassedNoJoinPoint; public List Location; diff --git a/ProjectLighthouse/Types/Match/FindBestRoom.cs b/ProjectLighthouse/Types/Match/FindBestRoom.cs new file mode 100644 index 00000000..2b76de28 --- /dev/null +++ b/ProjectLighthouse/Types/Match/FindBestRoom.cs @@ -0,0 +1,5 @@ +namespace LBPUnion.ProjectLighthouse.Types.Match +{ + public class FindBestRoom : CreateRoom + {} +} \ No newline at end of file diff --git a/ProjectLighthouse/Types/Match/FindBestRoomResponse.cs b/ProjectLighthouse/Types/Match/FindBestRoomResponse.cs new file mode 100644 index 00000000..6c1e968f --- /dev/null +++ b/ProjectLighthouse/Types/Match/FindBestRoomResponse.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace LBPUnion.ProjectLighthouse.Types.Match +{ + public class FindBestRoomResponse + { + public List Players { get; set; } + + public List> Slots { get; set; } + + [JsonIgnore] + public IEnumerable FirstSlot => this.Slots[0]; + + [JsonPropertyName("Location")] + public List Locations { get; set; } + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Types/Match/Player.cs b/ProjectLighthouse/Types/Match/Player.cs new file mode 100644 index 00000000..ad2140fa --- /dev/null +++ b/ProjectLighthouse/Types/Match/Player.cs @@ -0,0 +1,14 @@ +using System; +using System.Text.Json.Serialization; + +namespace LBPUnion.ProjectLighthouse.Types.Match +{ + [Serializable] + public class Player + { + public string PlayerId { get; set; } + + [JsonPropertyName("matching_res")] + public int MatchingRes { get; set; } + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Types/Photo.cs b/ProjectLighthouse/Types/Photo.cs index 2bafa2bb..bbbf39ef 100644 --- a/ProjectLighthouse/Types/Photo.cs +++ b/ProjectLighthouse/Types/Photo.cs @@ -92,7 +92,7 @@ namespace LBPUnion.ProjectLighthouse.Types LbpSerializer.StringElement("medium", this.MediumHash) + LbpSerializer.StringElement("large", this.LargeHash) + LbpSerializer.StringElement("plan", this.PlanHash) + - LbpSerializer.StringElement("author", this.CreatorId) + + LbpSerializer.StringElement("author", this.Creator.Username) + LbpSerializer.StringElement("subjects", subjectsAggregate) + slot; diff --git a/ProjectLighthouse/Types/Token.cs b/ProjectLighthouse/Types/Token.cs index 84183870..fc448c8c 100644 --- a/ProjectLighthouse/Types/Token.cs +++ b/ProjectLighthouse/Types/Token.cs @@ -12,6 +12,8 @@ namespace LBPUnion.ProjectLighthouse.Types public string UserToken { get; set; } + public string UserLocation { get; set; } + public GameVersion GameVersion { get; set; } } } \ No newline at end of file