using System.Reflection; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using sodoff.Attributes; using sodoff.Model; using sodoff.Schema; using sodoff.Services; using sodoff.Util; using sodoff.Configuration; namespace sodoff.Controllers.Common; public class ProfileController : Controller { private readonly DBContext ctx; private AchievementService achievementService; private ProfileService profileService; private readonly IOptions config; public ProfileController(DBContext ctx, AchievementService achievementService, ProfileService profileService, IOptions config) { this.ctx = ctx; this.achievementService = achievementService; this.profileService = profileService; this.config = config; } [HttpPost] [Produces("application/xml")] [Route("ProfileWebService.asmx/GetUserProfileByUserID")] public IActionResult GetUserProfileByUserID([FromForm] Guid userId, [FromForm] string apiKey) { // NOTE: this is public info (for mmo) - no session check Viking? viking = ctx.Vikings.FirstOrDefault(e => e.Uid == userId); if (viking is null) { return Ok(new UserProfileData()); // NOTE: do not return `Conflict("Viking not found")` due to client side error handling // (not Ok response cause soft-lock client - can't close error message) } return Ok(GetProfileDataFromViking(viking, apiKey)); } [HttpPost] [Produces("application/xml")] [Route("ProfileWebService.asmx/GetUserProfile")] [VikingSession(UseLock=false)] public IActionResult GetUserProfile(Viking viking, [FromForm] string apiKey) { return Ok(GetProfileDataFromViking(viking, apiKey)); } [HttpPost] [Produces("application/xml")] [Route("ProfileWebService.asmx/GetDetailedChildList")] [VikingSession(Mode=VikingSession.Modes.USER, ApiToken="parentApiToken", UseLock=false)] public Schema.UserProfileDataList? GetDetailedChildList(User user, [FromForm] string apiKey) { if (user.Vikings.Count <= 0) return null; UserProfileData[] profiles = user.Vikings.Select(v => GetProfileDataFromViking(v, apiKey)).ToArray(); return new UserProfileDataList { UserProfiles = profiles }; } [HttpPost] // [Produces("application/xml")] [Route("ProfileWebService.asmx/GetQuestions")] public IActionResult GetQuestions() { return Ok(XmlUtil.ReadResourceXmlString("questiondata")); } [HttpPost] [Produces("application/xml")] [Route("ProfileWebService.asmx/SetUserProfileAnswers")] [VikingSession] public IActionResult SetUserProfileAnswers(Viking viking, [FromForm] int profileAnswerIDs) { ProfileQuestion questionFromaId = profileService.GetQuestionFromAnswerId(profileAnswerIDs); return Ok(profileService.SetAnswer(viking, questionFromaId.ID, profileAnswerIDs)); } [HttpPost] //[Produces("application/xml")] [Route("ProfileWebService.asmx/GetProfileTagAll")] // used by Magic & Mythies public IActionResult GetProfileTagAll() { return Ok(XmlUtil.ReadResourceXmlString("profiletags")); } private UserProfileData GetProfileDataFromViking(Viking viking, [FromForm] string apiKey) { // Get the avatar data AvatarData avatarData = null; Gender? gender = null; if (viking.AvatarSerialized is not null) { avatarData = XmlUtil.DeserializeXml(viking.AvatarSerialized); avatarData.Id = viking.Id; if (gender is null) gender = avatarData.GenderType; } if (gender is null) gender = Gender.Unknown; if (avatarData != null && ClientVersion.GetVersion(apiKey) == 0xa3a12a0a) { // TODO adjust version number: we don't know for which versions it is required (for 3.12 it is, for 3.19 and 3.0 it's not) if (avatarData.Part.FirstOrDefault(e => e.PartType == "Sword") is null) { var extraParts = new AvatarDataPart[] { new AvatarDataPart { PartType = "Sword", Geometries = new string[] {"NULL"}, Textures = new string[] {"__EMPTY__"}, UserInventoryId = null, } }; avatarData.Part = extraParts.Concat(avatarData.Part).ToArray(); } } // Build the AvatarDisplayData AvatarDisplayData avatar = new AvatarDisplayData { AvatarData = avatarData, UserInfo = new UserInfo { MembershipID = "ef84db9-59c6-4950-b8ea-bbc1521f899b", // placeholder UserID = viking.Uid.ToString(), ParentUserID = viking.UserId.ToString(), Username = viking.Name, FirstName = viking.Name, MultiplayerEnabled = ClientVersion.GetVersion(apiKey) >= config.Value.MMOSupportMinVersion, Locale = "en-US", // placeholder GenderID = gender, OpenChatEnabled = true, IsApproved = true, RegistrationDate = viking.CreationDate, CreationDate = viking.CreationDate, FacebookUserID = 0, BirthDate = viking.BirthDate }, UserSubscriptionInfo = new UserSubscriptionInfo { UserID = viking.UserId.ToString(), MembershipID = 130687131, // placeholder SubscriptionTypeID = 1, // placeholder SubscriptionDisplayName = "Member", // placeholder SubscriptionPlanID = 41, // placeholder SubscriptionID = -3, // placeholder IsActive = true, // placeholder }, RankID = 0, // placeholder AchievementInfo = null, // placeholder Achievements = new UserAchievementInfo[] { achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.PlayerXP), achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.PlayerFarmingXP), achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.PlayerFishingXP), achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.UDTPoints), } }; UserGameCurrency currency = achievementService.GetUserCurrency(viking); return new UserProfileData { ID = viking.Uid.ToString(), AvatarInfo = avatar, AchievementCount = 0, MythieCount = 0, AnswerData = new UserAnswerData { UserID = viking.Uid.ToString(), Answers = profileService.GetUserAnswers(viking) }, GameCurrency = currency.GameCurrency, CashCurrency = currency.CashCurrency, ActivityCount = 0, BuddyCount = 0, UserGradeData = new UserGrade { UserGradeID = 0 }, UserProfileTag = new UserProfileTag() { CreateDate = new DateTime(DateTime.Now.Ticks), ProductGroupID = 1, ProfileTags = new List(), UserID = viking.Uid, UserProfileTagID = 1 } }; } }