private static (long characterId, DestinyItemComponent item) FindItemToLock( DestinyProfileResponse profile) { string selectedCharacterId = default; DestinyItemComponent selectedItem = default; foreach (var(characterId, characterInventory) in profile.CharacterEquipment.Data) { foreach (var item in characterInventory.Items) { if (item.ItemInstanceId == 0 || (item.BucketHash != BucketShips && item.BucketHash != BucketSparrows)) { continue; } selectedCharacterId = characterId; selectedItem = item; break; } if (selectedCharacterId != null) { break; } } return(characterId : Convert.ToInt64(selectedCharacterId), item : selectedItem); }
private static async Task AddFakeItem(DestinyProfileResponse profile, uint itemHash, long itemInstanceId) { var random = new Random(unchecked ((int)itemHash)); var itemDef = await Definitions.GetInventoryItem(itemHash); var character = profile.Characters.Data.Values.First(v => v.ClassType == itemDef.ClassType); var characterId = character.CharacterId.ToString(); profile.CharacterInventories.Data[characterId].Items.Add(new DestinyItemComponent() { ItemHash = itemHash, BucketHash = itemDef.Inventory.BucketTypeHash, ItemInstanceId = itemInstanceId, }); profile.ItemComponents.Objectives.Data[itemInstanceId.ToString()] = new DestinyItemObjectivesComponent() { Objectives = new List <DestinyObjectiveProgress>() }; foreach (var objectiveHash in itemDef.Objectives.ObjectiveHashes) { var objectiveDef = await Definitions.GetObjective(objectiveHash); profile.ItemComponents.Objectives.Data[itemInstanceId.ToString()].Objectives.Add(new DestinyObjectiveProgress() { ObjectiveHash = objectiveHash, Progress = random.Next(0, Convert.ToInt32(objectiveDef.CompletionValue)), CompletionValue = objectiveDef.CompletionValue, }); } }
public async Task <DestinyProfileResponse> GetProfile() { if (currentProfile != null) { return(currentProfile); } var account = await GetAccount(); var profile = await Util.RequestAndRetry(() => destinyApi.GetProfile(oauthManager.currentToken.AccessToken, BungieMembershipType.TigerSteam, account.MembershipId)); currentProfile = profile; return(profile); }
public static async Task <CrucibleMapTrackable> CreateFromProfile(DestinyProfileResponse profile) { string activeCharacterId = ""; DateTime activityStart = DateTime.MinValue; DestinyCharacterActivitiesComponent currentActivitiesComponent = default; foreach (var(characterId, activitiesComponent) in profile.CharacterActivities.Data) { // TODO: validate dates are correct Log.Info("TODO: validate dates are correct: DateActivityStarted: {DateActivityStarted}, activityStart: {activityStart}", activitiesComponent.DateActivityStarted, activityStart); if (activitiesComponent.CurrentActivityHash != 0 && activitiesComponent.DateActivityStarted > activityStart) { activeCharacterId = characterId; currentActivitiesComponent = activitiesComponent; activityStart = activitiesComponent.DateActivityStarted; } } if (currentActivitiesComponent == null) { return(new CrucibleMapTrackable()); } var tracker = new CrucibleMapTrackable() { CurrentActivityHash = currentActivitiesComponent.CurrentActivityHash, CurrentActivityModeHash = currentActivitiesComponent.CurrentActivityModeHash, }; if (profile.Characters.Data.ContainsKey(activeCharacterId)) { tracker.OwnerCharacter = new Character { CharacterComponent = profile.Characters.Data[activeCharacterId] }; await tracker.OwnerCharacter.PopulateDefinition(); } await tracker.PopulateDefinitions(); return(tracker); }
public async Task CacheBust(DestinyProfileResponse profile) { var(characterId, item) = FindItemToLock(profile); var itemState = item?.State ?? 0; var itemIsLocked = itemState == ItemState.Locked; if (item == null) { return; } Log.Debug("Found item to toggle lock state, character ID {characterId}, {itemHash}:{itemInstanceId}. locked state:{locked}", characterId, item.ItemHash, item.ItemInstanceId, itemIsLocked); try { await SetLockState(itemIsLocked, item.ItemInstanceId, characterId, profile.Profile.Data.UserInfo.MembershipType); } catch (Exception err) { Log.Error("Error busting profile cache, silently ignoring {Error}", err); } }
public static DestinyPresentationNodeComponent FindProfilePresentationNode(long hash, DestinyProfileResponse profile) { var profilePresentationNodes = profile?.ProfilePresentationNodes?.Data?.Nodes; var characterPresentationNodes = profile?.CharacterPresentationNodes?.Data; var hashString = hash.ToString(); if (profilePresentationNodes != null && profilePresentationNodes.ContainsKey(hashString)) { return(profilePresentationNodes[hashString]); } if (characterPresentationNodes != null) { foreach (var(_, value) in characterPresentationNodes) { if (value.Nodes.ContainsKey(hashString)) { return(value.Nodes[hashString]); } } } return(default);
public void Test03_GetProfile(long destinyMembershipId) { DestinyProfileResponse profile = _client.Destiny2.GetProfile(BungieMembershipType.TigerPsn, destinyMembershipId, DestinyComponentTypes.Profile); }
public static async Task <Item> ItemFromItemComponent(DestinyItemComponent item, DestinyProfileResponse profile, Character ownerCharacter = default) { var uninstancedObjectivesData = ownerCharacter == null ? new Dictionary <string, DestinyItemObjectivesComponent>() : profile.CharacterUninstancedItemComponents[ownerCharacter.CharacterComponent.CharacterId.ToString()].Objectives.Data; var objectives = new List <DestinyObjectiveProgress>(); var itemInstanceId = item.ItemInstanceId.ToString(); var itemHash = item.ItemHash.ToString(); if (profile.ItemComponents.Objectives.Data.ContainsKey(itemInstanceId)) { objectives.AddRange(profile.ItemComponents.Objectives.Data[itemInstanceId]?.Objectives); } if (item.ItemInstanceId.Equals(0) && uninstancedObjectivesData.ContainsKey(itemHash)) { objectives.AddRange(uninstancedObjectivesData[itemHash].Objectives); } if (objectives.Count == 0) { return(new Item()); } var bounty = new Item() { ItemHash = item.ItemHash, ItemInstanceId = item.ItemInstanceId, BucketHash = item.BucketHash, OwnerCharacter = ownerCharacter, Objectives = new List <Objective>() }; await bounty.PopulateDefinition(); foreach (var destinyQuestsDestinyObjectiveProgress in objectives) { var obj = new Objective { Progress = destinyQuestsDestinyObjectiveProgress }; await obj.PopulateDefinition(); bounty.Objectives.Add(obj); } return(bounty); }
public static async Task <List <Item> > ItemsFromProfile(DestinyProfileResponse profile, Character activeCharacter) { var bounties = new List <Item>(); async Task EachInventoryItem(DestinyItemComponent inventoryItem, Character ownerCharacter = default)
/// <summary> /// Gets all current activities for all characters for all clan members. /// Only gets the latest page of activies for ScoredNightfall activities. /// Scores then get inserted into the collection. /// </summary> /// <returns></returns> private async Task GetBungieScores(int count) { // Get Clan ID from Environment Variables long clanID = Convert.ToInt64(Environment.GetEnvironmentVariable("NFLBOT_CLANID"), CultureInfo.InvariantCulture); WriteLog(LogSeverity.Info, "Loading Clan Information.."); // Get Members of Clan from Bungie SearchResultOfGroupMember clanResult = await bungieClient.GroupV2.GetMembersOfGroupAsync( groupId : clanID, currentpage : 0, memberType : RuntimeGroupMemberType.Member, nameSearch : string.Empty).ConfigureAwait(false); WriteLog(LogSeverity.Info, $"Clan Information loaded! {clanResult.Results.Length} members found."); // Loop through Members foreach (GroupMember clanMember in clanResult.Results) { // Get their Membership ID required for getting their Profile & Activity Information long membershipId = clanMember.DestinyUserInfo.MembershipId; // Get their Profile Information DestinyProfileResponse memberdata = await bungieClient.Destiny2.GetProfileAsync( membershipType : clanMember.DestinyUserInfo.MembershipType, destinyMembershipId : membershipId, components : new BungieNet.Destiny.DestinyComponentType[] { BungieNet.Destiny.DestinyComponentType.Characters }).ConfigureAwait(false); WriteLog(LogSeverity.Debug, $"Found {memberdata.Characters.Data.Count} characters for {clanMember.DestinyUserInfo.DisplayName}"); // Loop through Characters of Member foreach (var playerCharacter in memberdata.Characters.Data) { // Hold Character ID in seperate Variable for convienence long characterId = playerCharacter.Key; // Get Activity History of Character // Using a Try-Catch Block as players might opt-in to refuse API calls to their history DestinyActivityHistoryResults activityData = null; try { activityData = await bungieClient.Destiny2.GetActivityHistoryAsync( membershipType : playerCharacter.Value.MembershipType, destinyMembershipId : membershipId, characterId : characterId, count : count, mode : BungieNet.Destiny.HistoricalStats.Definitions.DestinyActivityModeType.ScoredNightfall, page : 0).ConfigureAwait(false); } catch (BungieException e) // Most likely to be privacy related exceptions. For now we just ignore those scores. { Console.WriteLine(e); continue; } // If we didn't get any data, skip if (activityData == null || activityData.Activities == null) { continue; } // Loop through Activities foreach (var activity in activityData.Activities) { // If we already collected that Nightfall, skip it. if (collection.Find(x => x.NightfallId == activity.ActivityDetails.InstanceId).Any()) { continue; } // If the Activity is before the start of the ranking period (usually a Season), skip the Score. var activityDate = activity.Period; if (activityDate <= currentSeasonStart) { continue; } // API might return aborted Nightfalls, so their Score is 0. We want to ignore those. var nightfallScore = activity.Values["teamScore"].Basic.Value; if (nightfallScore <= 0) { continue; } // Get the Director Hash required for finding the Nightfall Name uint directorHash = activity.ActivityDetails.DirectorActivityHash; // Get the Nightfall Name string activityName = GetNameFromHash(directorHash); if (activityName.Equals("INVALID", StringComparison.InvariantCulture)) { continue; } // Create new Score Entry ScoreEntry entry = new ScoreEntry( name: clanMember.DestinyUserInfo.DisplayName, accountId: membershipId, directorActivityHash: activity.ActivityDetails.DirectorActivityHash.ToString(), nightfallId: activity.ActivityDetails.InstanceId, activityName: activityName, activityDate: activityDate, score: nightfallScore); // Insert into Collection collection.InsertOne(entry); WriteLog(LogSeverity.Info, $"Added Score {nightfallScore} for Player {clanMember.DestinyUserInfo.DisplayName} from {activityDate} in {activityName}"); } } } }
private async Task <KeyValuePair <long, CharacterOverview> > CollectDataAboutCharacter(DestinyProfileResponse characters, KeyValuePair <long, CharacterComponent> character) { var curActivity = characters.Response.characterActivities.data.Where(x => x.Key == character.Key).Select(x => x.Value).First(); var characterEquipment = characters.Response.characterEquipment.data.Where(x => x.Key == character.Key).FirstOrDefault().Value.items.Select(x => new { x.itemHash, x.itemInstanceId }); var characterStats = characters.Response.characters.data.Where(x => x.Key == character.Key).FirstOrDefault(); var activityDisplay = (await DataEngine.GetDetailedInformationFromHash <dynamic>(DestinyTable.ActivityDefinition, curActivity.currentActivityHash)) .Select(x => x.Value.displayProperties).FirstOrDefault(); var className = (await DataEngine.GetDetailedInformationFromHash <dynamic>(DestinyTable.ClassDefinition, character.Value.classHash)) .Where(x => x.Key == character.Value.classHash) .Select(x => x.Value) .First().displayProperties.name; var raceName = (await DataEngine.GetDetailedInformationFromHash <dynamic>(DestinyTable.RaceDefinition, character.Value.raceHash)) .Where(x => x.Key == character.Value.raceHash) .Select(x => x.Value) .First().displayProperties.name; var genderName = (await DataEngine.GetDetailedInformationFromHash <dynamic>(DestinyTable.GenderDefinition, character.Value.genderHash)) .Where(x => x.Key == character.Value.genderHash) .Select(x => x.Value) .First().displayProperties.name; return(new KeyValuePair <long, CharacterOverview>(character.Key, new CharacterOverview() { Light = character.Value.light, LevelProgression = character.Value.levelProgression, Class = className, Race = raceName, Gender = genderName, Super = await GetItemInformation("Subclass", characterEquipment, characters.Response.itemComponents.instances), Helm = await GetItemInformation("Helmet", characterEquipment, characters.Response.itemComponents.instances), Arms = await GetItemInformation("Gauntlets", characterEquipment, characters.Response.itemComponents.instances), Chest = await GetItemInformation("Chest Armor", characterEquipment, characters.Response.itemComponents.instances), Feet = await GetItemInformation("Leg Armor", characterEquipment, characters.Response.itemComponents.instances), ClassGear = await GetItemInformation("Class Armor", characterEquipment, characters.Response.itemComponents.instances), Primary = await GetItemInformation("Kinetic Weapons", characterEquipment, characters.Response.itemComponents.instances), Secondary = await GetItemInformation("Energy Weapons", characterEquipment, characters.Response.itemComponents.instances), Heavy = await GetItemInformation("Power Weapons", characterEquipment, characters.Response.itemComponents.instances), Ghost = await GetItemInformation("Ghost", characterEquipment, characters.Response.itemComponents.instances), Emblem = await GetItemInformation("Emblems", characterEquipment, characters.Response.itemComponents.instances), CurrentActivity = activityDisplay == null ? null : JsonConvert.DeserializeObject <DestinyDisplayPropertiesDefinition>(JsonConvert.SerializeObject(activityDisplay)) })); }
public static DestinyRecordComponent FindRecordInProfileOrDefault(string triumphHash, DestinyProfileResponse profile) { var characterIds = profile?.Profile?.Data?.CharacterIds ?? new List <long>(); if (profile?.CharacterRecords?.Data == null) { return(default);