[NoResponseCache] //we don't want to cache this, if they are removed from a guild then we want this reflected immediately or they may be taking in a guild chat they aren't apart of due to a race condition public async Task <IActionResult> GetCharacterMembershipGuildStatus([FromRoute(Name = "id")] int characterId, [NotNull][FromServices] IGuildCharacterMembershipRepository guildCharacterMembershipRepository) { if (guildCharacterMembershipRepository == null) { throw new ArgumentNullException(nameof(guildCharacterMembershipRepository)); } //If guild membership repo doesn't have the character id as an entry then it means there is no guild associated with them. if (!(await guildCharacterMembershipRepository.ContainsAsync(characterId).ConfigureAwaitFalse())) { return(BuildFailedResponseModel(CharacterGuildMembershipStatusResponseCode.NoGuild)); } //TODO: There is technically a race condition here. They could have just been kicked from a guild but the cached model may say they are in a guild //this could result in incredibly rare cases of a kicked member joining at the perfect moment who can talk in guild chat but no longer be in the guild ProjectVersionStage.AssertBeta(); //Otherwise, they are in a guild try { return(BuildSuccessfulResponseModel(new CharacterGuildMembershipStatusResponse((await guildCharacterMembershipRepository.RetrieveAsync(characterId).ConfigureAwaitFalse()).GuildId))); } catch (Exception e) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Encountered error in expected guild membership status request. CharacterId: {characterId} Reason: {e.Message}\n\nStack: {e.StackTrace}"); } return(BuildFailedResponseModel(CharacterGuildMembershipStatusResponseCode.GeneralServerError)); } }
public async Task <IActionResult> GetCharacterGuildList([NotNull][FromServices] IGuildCharacterMembershipRepository guildCharacterMembershipRepository, [FromServices] ISocialServiceToGameServiceClient socialToGameClient) { if (guildCharacterMembershipRepository == null) { throw new ArgumentNullException(nameof(guildCharacterMembershipRepository)); } CharacterSessionDataResponse session = await socialToGameClient.GetCharacterSessionDataByAccount(ClaimsReader.GetAccountIdInt(User)); if (!session.isSuccessful) { return(BuildFailedResponseModel(CharacterGuildMembershipStatusResponseCode.GeneralServerError)); } //No guild check if (!await guildCharacterMembershipRepository.ContainsAsync(session.CharacterId)) { return(BuildFailedResponseModel(CharacterGuildMembershipStatusResponseCode.NoGuild)); } var playerGuildMembership = await guildCharacterMembershipRepository.RetrieveAsync(session.CharacterId); int[] roster = await guildCharacterMembershipRepository.GetEntireGuildRosterAsync(playerGuildMembership.GuildId); return(BuildSuccessfulResponseModel(new CharacterGuildListResponseModel(roster))); }
public async Task <IActionResult> JoinGuildChat([FromServices] ICharacterSessionRepository characterSessionRepository, [FromServices] IFactoryCreatable <VivoxTokenClaims, VivoxTokenClaimsCreationContext> claimsFactory, [FromServices] IGuildCharacterMembershipRepository guildMembershipRepository, [FromServices] IVivoxTokenSignService signService) { int accountId = this.ClaimsReader.GetAccountIdInt(User); //If the user doesn't actually have a claimed session in the game //then we shouldn't log them into Vivox. if (!await characterSessionRepository.AccountHasActiveSession(accountId)) { return(BuildFailedResponseModel(VivoxLoginResponseCode.NoActiveCharacterSession)); } int characterId = await RetrieveSessionCharacterIdAsync(characterSessionRepository, accountId); if (!await guildMembershipRepository.ContainsAsync(characterId)) { return(BuildFailedResponseModel(VivoxLoginResponseCode.ChannelUnavailable)); } int guildId = (await guildMembershipRepository.RetrieveAsync(characterId)).GuildId; //TODO: Use a factory for channel name generation maybe? VivoxTokenClaims claims = claimsFactory.Create(new VivoxTokenClaimsCreationContext(characterId, VivoxAction.JoinChannel, new VivoxChannelData(false, $"Guild-{guildId}"))); //We don't send it back in a JSON form even though it's technically a JSON object //because the client just needs it as a raw string anyway to put through the Vivox client API. return(BuildSuccessfulResponseModel(new VivoxChannelJoinResponse(signService.CreateSignature(claims), claims.DestinationSIPURI))); }