From 1fdff9d27be9b2d4d45d4a882728ee4550cb581c Mon Sep 17 00:00:00 2001 From: hictooth Date: Thu, 22 Jun 2023 10:39:06 +0100 Subject: [PATCH] fix dragons and images --- mitm-redirect.py | 5 +- src/Controllers/Common/ContentController.cs | 95 +++++++++++++++------ src/Controllers/Common/ImageController.cs | 34 ++++++++ src/Model/DBContext.cs | 8 ++ src/Model/Dragon.cs | 3 + src/Model/Viking.cs | 3 + 6 files changed, 122 insertions(+), 26 deletions(-) create mode 100644 src/Controllers/Common/ImageController.cs diff --git a/mitm-redirect.py b/mitm-redirect.py index ee0a843..9bd6c87 100644 --- a/mitm-redirect.py +++ b/mitm-redirect.py @@ -34,8 +34,11 @@ methods = [ 'SetTaskState', 'CreatePet', 'SetRaisedPet', + 'SetSelectedPet', + 'GetSelectedRaisedPet', 'SetImage', - 'GetImage' + 'GetImage', + 'GetImageByUserId' ] def routable(path): diff --git a/src/Controllers/Common/ContentController.cs b/src/Controllers/Common/ContentController.cs index 730909b..389984d 100644 --- a/src/Controllers/Common/ContentController.cs +++ b/src/Controllers/Common/ContentController.cs @@ -199,6 +199,7 @@ public class ContentController : Controller { [HttpPost] [Produces("application/xml")] [Route("V2/ContentWebService.asmx/CreatePet")] + [SignResponse] public IActionResult CreatePet([FromForm] string apiToken, [FromForm] string request) { Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking; if (viking is null) { @@ -225,23 +226,23 @@ public class ContentController : Controller { Viking = viking, RaisedPetData = XmlUtil.SerializeXml(raisedPetRequest.RaisedPetData), }; + + if (raisedPetRequest.SetAsSelectedPet == true) { + viking.SelectedDragon = dragon; + ctx.Update(viking); + } ctx.Dragons.Add(dragon); ctx.SaveChanges(); - // Now update the RaisedPetData with the dragon id - raisedPetRequest.RaisedPetData.RaisedPetID = dragon.Id; - dragon.RaisedPetData = XmlUtil.SerializeXml(raisedPetRequest.RaisedPetData); - ctx.Dragons.Update(dragon); - ctx.SaveChanges(); - return Ok(new CreatePetResponse { - RaisedPetData = raisedPetRequest.RaisedPetData + RaisedPetData = GetRaisedPetDataFromDragon(dragon) }); } [HttpPost] [Produces("application/xml")] [Route("v3/ContentWebService.asmx/SetRaisedPet")] + [SignResponse] public IActionResult SetRaisedPet([FromForm] string apiToken, [FromForm] string request) { Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking; if (viking is null) { @@ -260,6 +261,7 @@ public class ContentController : Controller { } dragon.RaisedPetData = XmlUtil.SerializeXml(raisedPetRequest.RaisedPetData); + ctx.Update(dragon); ctx.SaveChanges(); return Ok(new SetRaisedPetResponse { @@ -270,6 +272,7 @@ public class ContentController : Controller { [HttpPost] [Produces("application/xml")] [Route("ContentWebService.asmx/SetSelectedPet")] + [SignResponse] public IActionResult SetSelectedPet([FromForm] string apiToken, [FromForm] int raisedPetID) { Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking; if (viking is null) { @@ -286,13 +289,10 @@ public class ContentController : Controller { } // Set the dragon as selected - RaisedPetData dragonData = XmlUtil.DeserializeXml(dragon.RaisedPetData); - dragonData.IsSelected = true; - dragon.RaisedPetData = XmlUtil.SerializeXml(dragonData); + viking.SelectedDragon = dragon; + ctx.Update(viking); ctx.SaveChanges(); - // TODO: make all other dragons unselected - return Ok(new SetRaisedPetResponse { RaisedPetSetResult = RaisedPetSetResult.Success }); @@ -301,19 +301,16 @@ public class ContentController : Controller { [HttpPost] [Produces("application/xml")] [Route("V2/ContentWebService.asmx/GetAllActivePetsByuserId")] - [Route("ContentWebService.asmx/GetSelectedRaisedPet")] - public RaisedPetData[]? GetAllActivePetsByuserId([FromForm] string apiToken, [FromForm] string userId, [FromForm] bool active, [FromForm] bool isActive) { + [SignResponse] + public RaisedPetData[]? GetAllActivePetsByuserId([FromForm] string apiToken, [FromForm] string userId, [FromForm] bool active) { Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking; if (viking is null) { return null; } - // GetAllActivePetsByuserId uses active, and GetSelectedRaisedPet uses active, so OR them together - bool isActiveSet = active || isActive; - RaisedPetData[] dragons = viking.Dragons .Where(d => d.RaisedPetData is not null) - .Select(d => XmlUtil.DeserializeXml(d.RaisedPetData)) + .Select(GetRaisedPetDataFromDragon) .ToArray(); if (dragons.Length == 0) { @@ -322,6 +319,26 @@ public class ContentController : Controller { return dragons; } + [HttpPost] + [Produces("application/xml")] + [Route("ContentWebService.asmx/GetSelectedRaisedPet")] + [SignResponse] + public RaisedPetData[]? GetSelectedRaisedPet([FromForm] string apiToken, [FromForm] string userId, [FromForm] bool isActive) { + Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking; + if (viking is null) { + return null; + } + + Dragon? dragon = viking.SelectedDragon; + if (dragon is null) { + return null; + } + + return new RaisedPetData[] { + GetRaisedPetDataFromDragon(dragon) + }; + } + [HttpPost] [Produces("application/xml")] [Route("ContentWebService.asmx/SetImage")] @@ -342,6 +359,7 @@ public class ContentController : Controller { ImageSlot = ImageSlot, Viking = viking, }; + newImage = true; } // Save the image in the db @@ -367,16 +385,21 @@ public class ContentController : Controller { return null; } - Image? image = viking.Images.FirstOrDefault(e => e.ImageType == ImageType && e.ImageSlot == ImageSlot); - if (image is null) { + return GetImageData(viking, ImageType, ImageSlot); + } + + [HttpPost] + [Produces("application/xml")] + [Route("ContentWebService.asmx/GetImageByUserId")] + public ImageData? GetImageByUserId([FromForm] string userId, [FromForm] string ImageType, [FromForm] int ImageSlot) { + Viking? viking = ctx.Vikings.FirstOrDefault(e => e.Id == userId); + if (viking is null || viking.Images is null) { return null; } - // TODO: test this - return new ImageData { - ImageURL = image.ImageData, - TemplateName = image.TemplateName, - }; + // TODO: should we restrict images to only those the caller owns? + + return GetImageData(viking, ImageType, ImageSlot); } [HttpPost] @@ -464,4 +487,26 @@ public class ContentController : Controller { return Ok(new SetTaskStateResult { Success = true, Status = SetTaskStateStatus.TaskCanBeDone }); } + + private RaisedPetData GetRaisedPetDataFromDragon (Dragon dragon) { + RaisedPetData data = XmlUtil.DeserializeXml(dragon.RaisedPetData); + data.RaisedPetID = dragon.Id; + data.EntityID = Guid.Parse(dragon.EntityId); + data.IsSelected = dragon.SelectedViking is not null; + return data; + } + + private ImageData? GetImageData (Viking viking, String ImageType, int ImageSlot) { + Image? image = viking.Images.FirstOrDefault(e => e.ImageType == ImageType && e.ImageSlot == ImageSlot); + if (image is null) { + return null; + } + + string imageUrl = string.Format("{0}://{1}/RawImage/{2}/{3}/{4}", HttpContext.Request.Scheme, HttpContext.Request.Host, viking.Id, ImageType, ImageSlot); + + return new ImageData { + ImageURL = imageUrl, + TemplateName = image.TemplateName, + }; + } } diff --git a/src/Controllers/Common/ImageController.cs b/src/Controllers/Common/ImageController.cs new file mode 100644 index 0000000..bdfc0d8 --- /dev/null +++ b/src/Controllers/Common/ImageController.cs @@ -0,0 +1,34 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using sodoff.Attributes; +using sodoff.Model; +using sodoff.Schema; +using sodoff.Services; +using sodoff.Util; +using System; + +namespace sodoff.Controllers.Common; +public class ImageController : Controller { + + private readonly DBContext ctx; + private KeyValueService keyValueService; + public ImageController(DBContext ctx, KeyValueService keyValueService) { + this.ctx = ctx; + this.keyValueService = keyValueService; + } + + // SetImage and GetImage are defined in ContentController + + [HttpGet] + [Route("RawImage/{VikingId}/{ImageType}/{ImageSlot}")] + public IActionResult RawImage(String VikingId, String ImageType, int ImageSlot) { + Image? image = ctx.Images.FirstOrDefault(e => e.VikingId == VikingId && e.ImageType == ImageType && e.ImageSlot == ImageSlot); + if (image is null) { + return null; + } + + byte[] imageBytes = Convert.FromBase64String(image.ImageData); + var imageStream = new MemoryStream(imageBytes, 0, imageBytes.Length); + return File(imageStream, "image/jpeg"); + } +} diff --git a/src/Model/DBContext.cs b/src/Model/DBContext.cs index a0cd29d..75f713e 100644 --- a/src/Model/DBContext.cs +++ b/src/Model/DBContext.cs @@ -48,6 +48,14 @@ public class DBContext : DbContext { builder.Entity().HasMany(u => u.Dragons) .WithOne(e => e.Viking); + builder.Entity().HasOne(s => s.SelectedDragon) + .WithOne(e => e.SelectedViking) + .HasForeignKey(e => e.SelectedVikingId); + + builder.Entity().HasOne(s => s.SelectedViking) + .WithOne(e => e.SelectedDragon) + .HasForeignKey(e => e.SelectedDragonId); + builder.Entity().HasOne(s => s.Viking) .WithMany(e => e.Images) .HasForeignKey(e => e.VikingId); diff --git a/src/Model/Dragon.cs b/src/Model/Dragon.cs index 890ded5..1d80e8b 100644 --- a/src/Model/Dragon.cs +++ b/src/Model/Dragon.cs @@ -14,7 +14,10 @@ public class Dragon { [Required] public string VikingId { get; set; } = null!; + public string? SelectedVikingId { get; set; } + public string? RaisedPetData { get; set; } public virtual Viking Viking { get; set; } = null!; + public virtual Viking SelectedViking { get; set; } = null!; } diff --git a/src/Model/Viking.cs b/src/Model/Viking.cs index 4e43b61..8a40863 100644 --- a/src/Model/Viking.cs +++ b/src/Model/Viking.cs @@ -13,8 +13,11 @@ public class Viking { public string? AvatarSerialized { get; set; } + public int? SelectedDragonId { get; set; } + public virtual ICollection Sessions { get; set; } = null!; public virtual User User { get; set; } = null!; public virtual ICollection Dragons { get; set; } = null!; public virtual ICollection Images { get; set; } = null!; + public virtual Dragon? SelectedDragon { get; set; } }