From 24e88eea2f8027e9bccbee6c25d9aa61a63df72c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=80=92?= Date: Sat, 8 Oct 2022 23:49:32 +0300 Subject: [PATCH] 0.2.7 release. (#215) --- CHANGELOG.md | 12 +- aiobungie/_info.py | 2 +- aiobungie/client.py | 26 +- aiobungie/crates/activity.py | 13 +- aiobungie/crates/character.py | 4 +- aiobungie/crates/clans.py | 4 +- aiobungie/crates/entity.py | 30 +- aiobungie/crates/fireteams.py | 5 +- aiobungie/crates/profile.py | 28 +- aiobungie/crates/records.py | 17 +- aiobungie/crates/user.py | 2 +- aiobungie/interfaces/factory.py | 16 +- aiobungie/internal/enums.py | 31 +- aiobungie/internal/factory.py | 28 +- aiobungie/internal/iterators.py | 157 +- aiobungie/rest.py | 12 +- docs/aiobungie.html | 39010 ++++++++++------------- docs/aiobungie/builders.html | 817 +- docs/aiobungie/client.html | 136 +- docs/aiobungie/crates.html | 3476 +- docs/aiobungie/error.html | 23 +- docs/aiobungie/interfaces.html | 102 +- docs/aiobungie/internal.html | 12 +- docs/aiobungie/internal/_backoff.html | 12 +- docs/aiobungie/internal/assets.html | 102 +- docs/aiobungie/internal/enums.html | 9115 ++---- docs/aiobungie/internal/factory.html | 12734 ++++---- docs/aiobungie/internal/helpers.html | 12 +- docs/aiobungie/internal/iterators.html | 3140 +- docs/aiobungie/internal/time.html | 12 +- docs/aiobungie/rest.html | 11728 ++++--- docs/aiobungie/traits.html | 1193 +- docs/aiobungie/typedefs.html | 12 +- docs/aiobungie/undefined.html | 12 +- docs/aiobungie/url.html | 61 +- docs/search.js | 2 +- nix/clienttest-nox.py | 7 +- pyproject.toml | 2 +- tests/aiobungie/test_client.py | 6 +- 39 files changed, 35498 insertions(+), 46615 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18ae51fe..6595d08c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).All notable changes to this project will be documented in this file. -## [Unreleased](https://github.com/nxtlo/aiobungie/compare/0.2.6...HEAD) +## [Unreleased](https://github.com/nxtlo/aiobungie/compare/0.2.7...HEAD) + +## [0.2.7](https://github.com/nxtlo/aiobungie/compare/0.2.6...0.2.7) 10-08-2022 ## Breaking Changes - Base `Client` users now will need to open the REST client before making any requests. @@ -48,11 +50,17 @@ the state field from the URL. A fully generated URL can still be acquired via `. Example: ```py -await client.download_manifest(name='Destiny', path='G:/Files') # -> G:/Files/Destiny.sqlite3 +await client.download_manifest(name='Destiny', path='G:/Files' or pathlib.Path("Path/**/**")) # -> G:/Files/Destiny.sqlite3 ``` +## Added +- Enum fields `EPIC_GAMES_STORE` and `DEMON`. [#214](https://github.com/nxtlo/aiobungie/pull/214) + ## Changed - `FlatIterator` no longer support async iteration. +- Removed method `FlatIterator.discard` in favor of `FlatIterator.filter` mathod. +- `FlatIterator` class renamed to `Iterator`. +- Enum flags now uses bitwise `<<` for its fields instead of `=` numbers assign. ## Removed - `CharacterError` exception. This was supposed to be removed with `0.2.6`. diff --git a/aiobungie/_info.py b/aiobungie/_info.py index 5e3c5c79..f34e045f 100644 --- a/aiobungie/_info.py +++ b/aiobungie/_info.py @@ -36,7 +36,7 @@ import typing -__version__: typing.Final[str] = "0.2.6" +__version__: typing.Final[str] = "0.2.7" __about__: typing.Final[ str ] = "A Pythonic `async`/`await` framework / wrapper for interacting with the Bungie API." diff --git a/aiobungie/client.py b/aiobungie/client.py index efd2b253..05c41c00 100644 --- a/aiobungie/client.py +++ b/aiobungie/client.py @@ -214,7 +214,7 @@ async def fetch_bungie_user(self, id: int, /) -> user.BungieUser: async def search_users( self, name: str, / - ) -> iterators.FlatIterator[user.SearchableDestinyUser]: + ) -> iterators.Iterator[user.SearchableDestinyUser]: """Search for players and return all players that matches the same name. Parameters @@ -224,12 +224,12 @@ async def search_users( Returns ------- - `aiobungie.iterators.FlatIterator[aiobungie.crates.DestinyMembership]` + `aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]` A sequence of destiny memberships. """ payload = await self.rest.search_users(name) - return iterators.FlatIterator( + return iterators.Iterator( [ self.factory.deserialize_searched_user(user) for user in payload["searchResults"] @@ -544,7 +544,7 @@ async def fetch_activities( ] = enums.MembershipType.ALL, page: int = 0, limit: int = 250, - ) -> iterators.FlatIterator[activity.Activity]: + ) -> iterators.Iterator[activity.Activity]: """Fetch a Destiny 2 activity for the specified character id. Parameters @@ -567,7 +567,7 @@ async def fetch_activities( Returns ------- - `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]` + `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` An iterator of the player's activities. Raises @@ -608,7 +608,7 @@ async def fetch_aggregated_activity_stats( character_id: int, membership_id: int, membership_type: typedefs.IntAnd[enums.MembershipType], - ) -> iterators.FlatIterator[activity.AggregatedActivity]: + ) -> iterators.Iterator[activity.AggregatedActivity]: """Fetch aggregated activity stats for a character. Parameters @@ -622,7 +622,7 @@ async def fetch_aggregated_activity_stats( Returns ------- - `aiobungie.iterators.FlatIterator[aiobungie.crates.AggregatedActivity]` + `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]` An iterator of the player's activities. Raises @@ -726,7 +726,7 @@ async def fetch_clan_conversations( async def fetch_clan_admins( self, clan_id: int, / - ) -> iterators.FlatIterator[clans.ClanMember]: + ) -> iterators.Iterator[clans.ClanMember]: """Fetch the clan founder and admins. Parameters @@ -736,7 +736,7 @@ async def fetch_clan_admins( Returns ------- - `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]` + `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` An iterator over the found clan admins and founder. Raises @@ -833,7 +833,7 @@ async def fetch_clan_members( *, name: typing.Optional[str] = None, type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, - ) -> iterators.FlatIterator[clans.ClanMember]: + ) -> iterators.Iterator[clans.ClanMember]: """Fetch Bungie clan members. Parameters @@ -853,7 +853,7 @@ async def fetch_clan_members( Returns ------- - `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]` + `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` An iterator over the bungie clan members. Raises @@ -972,7 +972,7 @@ async def fetch_objective_entity(self, hash: int, /) -> entity.ObjectiveEntity: async def search_entities( self, name: str, entity_type: str, *, page: int = 0 - ) -> iterators.FlatIterator[entity.SearchableEntity]: + ) -> iterators.Iterator[entity.SearchableEntity]: """Search for Destiny2 entities given a name and its type. Parameters @@ -990,7 +990,7 @@ async def search_entities( Returns ------- - `aiobungie.iterators.FlatIterator[aiobungie.crates.SearchableEntity]` + `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]` An iterator over the found results matching the provided name. """ resp = await self.rest.search_entities(name, entity_type, page=page) diff --git a/aiobungie/crates/activity.py b/aiobungie/crates/activity.py index c0847d1f..20e09b15 100644 --- a/aiobungie/crates/activity.py +++ b/aiobungie/crates/activity.py @@ -55,7 +55,6 @@ import datetime from aiobungie import traits - from aiobungie import typedefs from aiobungie import undefined from aiobungie.crates import entity from aiobungie.crates import user @@ -163,7 +162,7 @@ class GuidedGame: class Location: """Represents information about an activity location.""" - hash: typing.Union[typedefs.IntAnd[enums.Place], typedefs.IntAnd[enums.Planet]] + hash: typing.Union[enums.Place, enums.Planet] """Location hash.""" activision_source: str @@ -192,12 +191,10 @@ class CharacterActivity: current_mode_hash: int """The current activity mode hash that the player is now playing.""" - current_mode: typing.Optional[typedefs.IntAnd[enums.GameMode]] + current_mode: typing.Optional[enums.GameMode] """The current activity mode presented an an enum.""" - current_mode_types: typing.Optional[ - collections.Sequence[typedefs.IntAnd[enums.GameMode]] - ] + current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] """A sequence of the current activity game-mode types presented as an enum.""" current_mode_hashes: typing.Optional[collections.Sequence[int]] @@ -241,10 +238,10 @@ class AvailableActivity: recommended_light: typing.Optional[int] """The recommended light power to enter this activity.""" - difficulty: typedefs.IntAnd[Difficulty] + difficulty: Difficulty """Activity's difficulty tier.""" - @helpers.unimplemented(available_in="0.2.7") + @helpers.unimplemented() async def fetch_self(self) -> entity.ActivityEntity: """Fetch the definition of this activity.""" ... diff --git a/aiobungie/crates/character.py b/aiobungie/crates/character.py index b47a191f..a8f8d48d 100644 --- a/aiobungie/crates/character.py +++ b/aiobungie/crates/character.py @@ -244,7 +244,7 @@ async def fetch_activities( *, page: int = 0, limit: int = 250, - ) -> iterators.FlatIterator[activity.Activity]: + ) -> iterators.Iterator[activity.Activity]: """Fetch Destiny 2 activities for this character. Parameters @@ -261,7 +261,7 @@ async def fetch_activities( Returns ------- - `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]` + `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` A iterator over the character's activities. Raises diff --git a/aiobungie/crates/clans.py b/aiobungie/crates/clans.py index ca71d19d..72f8083e 100644 --- a/aiobungie/crates/clans.py +++ b/aiobungie/crates/clans.py @@ -731,7 +731,7 @@ async def fetch_members( *, name: typing.Optional[str] = None, type: enums.MembershipType = enums.MembershipType.NONE, - ) -> iterators.FlatIterator[ClanMember]: + ) -> iterators.Iterator[ClanMember]: """Fetch the members of the clan. Parameters @@ -744,7 +744,7 @@ async def fetch_members( Returns -------- - `aiobungie.FlatIterator[ClanMember]` + `aiobungie.Iterator[ClanMember]` An iterator over the clan members found in this clan. Raises diff --git a/aiobungie/crates/entity.py b/aiobungie/crates/entity.py index 720fd78b..3cf67058 100644 --- a/aiobungie/crates/entity.py +++ b/aiobungie/crates/entity.py @@ -474,7 +474,7 @@ class ObjectiveEntity(Entity): completion_value: int - scope: typedefs.IntAnd[GatingScope] + scope: GatingScope location_hash: int @@ -486,15 +486,15 @@ class ObjectiveEntity(Entity): display_only_objective: bool - value_style: typedefs.IntAnd[ValueUIStyle] + value_style: ValueUIStyle - complete_value_style: typedefs.IntAnd[ValueUIStyle] + complete_value_style: ValueUIStyle - progress_value_style: typedefs.IntAnd[ValueUIStyle] + progress_value_style: ValueUIStyle allow_over_completion: bool - show_value_style: typedefs.IntAnd[ValueUIStyle] + show_value_style: ValueUIStyle progress_description: str @@ -526,13 +526,13 @@ class ActivityEntity(Entity): light_level: int """Activity's light level.""" - place: typedefs.IntAnd[enums.Place] + place: enums.Place """The place of this activity.""" type_hash: int """The activity's type hash. This bounds to activity types such as Strikes, Crucible, Raids, etc.""" - tier: typedefs.IntAnd[activity.Difficulty] + tier: activity.Difficulty """Activity's difficulty tier.""" image: assets.Image @@ -567,20 +567,16 @@ class ActivityEntity(Entity): guided_game: typing.Optional[activity.GuidedGame] """Information about activity's guided game mode, If exists otherwise `None`.""" - mode: typing.Optional[typedefs.IntAnd[enums.GameMode]] + mode: typing.Optional[enums.GameMode] """If this activity had an activity mode directly defined on it, this will be the hash of that mode.""" mode_hash: typing.Optional[int] """If the activity had an activity mode directly defined on it, this will be the enum value of that mode.""" - mode_hashes: collections.Sequence[typedefs.IntAnd[enums.GameMode]] = attrs.field( - repr=False - ) + mode_hashes: collections.Sequence[enums.GameMode] = attrs.field(repr=False) """The hash identifiers for Activity Modes relevant to this entry.""" - mode_types: collections.Sequence[typedefs.IntAnd[enums.GameMode]] = attrs.field( - repr=False - ) + mode_types: collections.Sequence[enums.GameMode] = attrs.field(repr=False) """A sequence of the activity gamemode types.""" loadouts: collections.Sequence[int] @@ -615,16 +611,16 @@ class PlaylistActivityEntity: mode_hash: typing.Optional[int] """If this activity had an activity mode directly defined on it, this will be the hash of that mode.""" - mode: typing.Optional[typedefs.IntAnd[enums.GameMode]] + mode: typing.Optional[enums.GameMode] """If the activity had an activity mode directly defined on it, this will be the enum value of that mode.""" mode_hashes: collections.Sequence[int] """The hash identifiers for Activity Modes relevant to this entry.""" - mode_types: collections.Sequence[typedefs.IntAnd[enums.GameMode]] + mode_types: collections.Sequence[enums.GameMode] """A sequence of the activity gamemode types.""" - @helpers.unimplemented(available_in="0.2.7") + @helpers.unimplemented() async def fetch_self(self) -> ActivityEntity: """Fetch the definition of this activity.""" ... diff --git a/aiobungie/crates/fireteams.py b/aiobungie/crates/fireteams.py index d9b1329f..e9991dd4 100644 --- a/aiobungie/crates/fireteams.py +++ b/aiobungie/crates/fireteams.py @@ -47,7 +47,6 @@ import collections.abc as collections import datetime - from aiobungie import typedefs from aiobungie import undefined @@ -168,7 +167,7 @@ class FireteamPartyMember: display_name: undefined.UndefinedOr[str] """Party member's display name. `UNDEFINED` if not set.""" - status: typedefs.IntAnd[FireteamPartyMemberState] + status: FireteamPartyMemberState """A Flags Enumeration value indicating the states that the player is in relevant to being on a fireteam.""" def __str__(self) -> str: @@ -211,7 +210,7 @@ class FireteamPartySettings: privacy_setting: enums.PrivacySetting """Fireteam leader's fireteam privacy setting.""" - closed_reasons: typedefs.IntAnd[enums.ClosedReasons] + closed_reasons: enums.ClosedReasons """Reasons why a person can't join this person's fireteam.""" diff --git a/aiobungie/crates/profile.py b/aiobungie/crates/profile.py index 3d7cea85..8bbbda7a 100644 --- a/aiobungie/crates/profile.py +++ b/aiobungie/crates/profile.py @@ -45,7 +45,6 @@ import collections.abc as collections from aiobungie import traits - from aiobungie import typedefs from aiobungie.crates import components from aiobungie.crates import season @@ -107,7 +106,7 @@ class ProfileItemImpl: bucket: int """The item bucket hash.""" - transfer_status: typedefs.IntAnd[enums.TransferStatus] + transfer_status: enums.TransferStatus """The item's transfer status.""" lockable: bool @@ -185,18 +184,6 @@ class Profile: power_cap: int """The profile's current season power cap.""" - async def _await_all_chars( - self, components: list[enums.ComponentType], auth: typing.Optional[str] = None - ) -> collections.Sequence[components.CharacterComponent]: - return await helpers.awaits( - *[ - self.net.request.fetch_character( - self.id, self.type, char_id, components, auth - ) - for char_id in self.character_ids - ] - ) - async def collect_characters( self, components: list[enums.ComponentType], auth: typing.Optional[str] = None ) -> collections.Sequence[components.CharacterComponent]: @@ -205,12 +192,12 @@ async def collect_characters( Parameters ---------- components: `list[aiobungie.ComponentType]` - Multiple arguments of character components to collect and return. + A sequence of character components to collect and return. Other Parameters ---------------- auth : `typing.Optional[str]` - A passed kwarg Bearer access_token to make the request with. + A Bearer access_token to make the request with. This is optional and limited to components that only requires an Authorization token. Returns @@ -218,7 +205,14 @@ async def collect_characters( `collections.Sequence[aiobungie.crates.CharacterComponent]` A sequence of the characters components. """ - return await self._await_all_chars(components, auth) + return await helpers.awaits( + *[ + self.net.request.fetch_character( + self.id, self.type, char_id, components, auth + ) + for char_id in self.character_ids + ] + ) def __str__(self) -> str: return self.name diff --git a/aiobungie/crates/records.py b/aiobungie/crates/records.py index f2fa7b47..fa31267b 100644 --- a/aiobungie/crates/records.py +++ b/aiobungie/crates/records.py @@ -41,7 +41,6 @@ if typing.TYPE_CHECKING: from aiobungie import traits - from aiobungie import typedefs from aiobungie.crates import entity @@ -50,13 +49,13 @@ class RecordState(enums.Flag): """An enum for records component states.""" NONE = 0 - REDEEMED = 1 - UNAVAILABLE = 2 - OBJECTIVE_NOT_COMPLETED = 4 - OBSCURED = 8 - INVISIBLE = 16 - ENTITLEMENT_UNOWNED = 32 - CAN_EQUIP_TITLE = 64 + REDEEMED = 1 << 0 + UNAVAILABLE = 1 << 1 + OBJECTIVE_NOT_COMPLETED = 1 << 2 + OBSCURED = 1 << 3 + INVISIBLE = 1 << 4 + ENTITLEMENT_UNOWNED = 1 << 5 + CAN_EQUIP_TITLE = 1 << 6 @attrs.define(kw_only=True) @@ -155,7 +154,7 @@ class Record: This will be `UNDEFINED` if not found. """ - state: typedefs.IntAnd[RecordState] + state: RecordState """Record's state. This will be an int if the state is a sum of multiple states.""" objectives: typing.Optional[list[Objective]] diff --git a/aiobungie/crates/user.py b/aiobungie/crates/user.py index 46e12bd9..143c1645 100644 --- a/aiobungie/crates/user.py +++ b/aiobungie/crates/user.py @@ -357,7 +357,7 @@ class UserCredentials: Those credentials should be the linked profiles such as Twitch, Steam, Blizzard, etc. """ - type: typedefs.IntAnd[enums.CredentialType] + type: enums.CredentialType """The credential type.""" display_name: str diff --git a/aiobungie/interfaces/factory.py b/aiobungie/interfaces/factory.py index 27b92ed5..a1b2bdbd 100644 --- a/aiobungie/interfaces/factory.py +++ b/aiobungie/interfaces/factory.py @@ -252,7 +252,7 @@ def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMem @abc.abstractmethod def deserialize_clan_members( self, data: typedefs.JSONObject, / - ) -> iterators.FlatIterator[clans.ClanMember]: + ) -> iterators.Iterator[clans.ClanMember]: """Deserialize a JSON payload of a clan members information. Parameters @@ -262,7 +262,7 @@ def deserialize_clan_members( Returns ------- - `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]` + `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` An iterator of clan members of the deserialized payload. """ @@ -679,7 +679,7 @@ def deserialize_inventory_entity( @abc.abstractmethod def deserialize_inventory_results( self, payload: typedefs.JSONObject - ) -> iterators.FlatIterator[entity.SearchableEntity]: + ) -> iterators.Iterator[entity.SearchableEntity]: """Deserialize results of searched Destiny2 entities. Parameters @@ -689,7 +689,7 @@ def deserialize_inventory_results( Returns ------- - `aiobungie.iterators.FlatIterator[aiobungie.crates.SearchableEntity]` + `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]` An iterator over the found searched entities. """ @@ -732,7 +732,7 @@ def deserialize_activity( @abc.abstractmethod def deserialize_activities( self, payload: typedefs.JSONObject, / - ) -> iterators.FlatIterator[activity.Activity]: + ) -> iterators.Iterator[activity.Activity]: """Deserialize a JSON payload of an array of activity history information. Parameters @@ -742,7 +742,7 @@ def deserialize_activities( Returns ------- - `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]` + `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` Am iterator over activity objects of the deserialized payload. """ @@ -819,7 +819,7 @@ def deserialize_aggregated_activity( @abc.abstractmethod def deserialize_aggregated_activities( self, payload: typedefs.JSONObject - ) -> iterators.FlatIterator[activity.AggregatedActivity]: + ) -> iterators.Iterator[activity.AggregatedActivity]: """Deserialize a JSON payload of an array of aggregated activities. Parameters @@ -829,7 +829,7 @@ def deserialize_aggregated_activities( Returns ------- - `aiobungie.iterators.FlatIterator[aiobungie.crates.AggregatedActivity]` + `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]` An iterator over aggregated activities objects. """ diff --git a/aiobungie/internal/enums.py b/aiobungie/internal/enums.py index 5b051e36..afbec294 100644 --- a/aiobungie/internal/enums.py +++ b/aiobungie/internal/enums.py @@ -67,11 +67,6 @@ _ITERABLE = (set, list, tuple) -if typing.TYPE_CHECKING: - _T = typing.TypeVar("_T") - -# TODO = Use Flags for bitwised fields? - class Enum(__enum.Enum): """Builtin Python enum with extra handlings.""" @@ -747,11 +742,11 @@ class TransferStatus(Flag): CAN_TRANSFER = 0 """The item can be transferred.""" - IS_EQUIPPED = 1 + IS_EQUIPPED = 1 << 0 """You can't transfer since the item is equipped.""" - NOT_TRASNFERRABLE = 2 + NOT_TRASNFERRABLE = 1 << 1 """This item can not be transferred.""" - COULD_BE_TRANSFERRED = 4 + COULD_BE_TRANSFERRED = 1 << 2 """You can trasnfer the item. But the place you're trying to put it at has no space for it.""" @@ -760,12 +755,12 @@ class ItemState(Flag): """An enum for Destiny 2 item states.""" NONE = 0 - LOCKED = 1 - TRACKED = 2 - MASTERWORKED = 4 - CRAFTED = 8 + LOCKED = 1 << 0 + TRACKED = 1 << 1 + MASTERWORKED = 1 << 2 + CRAFTED = 1 << 3 """If this bit is set, the item has been 'crafted' by the player.""" - HIGHLITED_OBJECTIVE = 16 + HIGHLITED_OBJECTIVE = 1 << 4 """If this bit is set, the item is a 'highlighted' objective.""" @@ -785,17 +780,17 @@ class ClosedReasons(Flag): """A Flags enumeration representing the reasons why a person can't join this user's fireteam.""" NONE = 0 - MATCHMAKING = 1 - LOADING = 2 - SOLO = 4 + MATCHMAKING = 1 << 0 + LOADING = 1 << 1 + SOLO = 1 << 2 """The activity is required to be played solo.""" - INTERNAL_REASONS = 8 + INTERNAL_REASONS = 1 << 3 """ The user can't be joined for one of a variety of internal reasons. Basically, the game can't let you join at this time, but for reasons that aren't under the control of this user """ - DISALLOWED_BY_GAME_STATE = 16 + DISALLOWED_BY_GAME_STATE = 1 << 4 """The user's current activity/quest/other transitory game state is preventing joining.""" OFFLINE = 32768 """The user appears offline.""" diff --git a/aiobungie/internal/factory.py b/aiobungie/internal/factory.py index 474408c0..dd327cc2 100644 --- a/aiobungie/internal/factory.py +++ b/aiobungie/internal/factory.py @@ -193,10 +193,9 @@ def deserialize_user_credentials( for creds in payload ] - @staticmethod - def set_themese_attrs( - payload: typedefs.JSONArray, / - ) -> typing.Collection[user.UserThemes]: + def deserialize_user_themes( + self, payload: typedefs.JSONArray + ) -> collections.Sequence[user.UserThemes]: return [ user.UserThemes( id=int(entry["userThemeId"]), @@ -210,11 +209,6 @@ def set_themese_attrs( for entry in payload ] - def deserialize_user_themes( - self, payload: typedefs.JSONArray - ) -> collections.Sequence[user.UserThemes]: - return list(self.set_themese_attrs(payload)) - def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan: # This is kinda redundant @@ -319,8 +313,8 @@ def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMem def deserialize_clan_members( self, data: typedefs.JSONObject, / - ) -> iterators.FlatIterator[clans.ClanMember]: - return iterators.FlatIterator( + ) -> iterators.Iterator[clans.ClanMember]: + return iterators.Iterator( [self.deserialize_clan_member(member) for member in data["results"]] ) @@ -1494,13 +1488,13 @@ def _set_entity_attrs( def deserialize_inventory_results( self, payload: typedefs.JSONObject - ) -> iterators.FlatIterator[entity.SearchableEntity]: + ) -> iterators.Iterator[entity.SearchableEntity]: suggested_words: list[str] = payload["suggestedWords"] def _check_unknown(s: str) -> undefined.UndefinedOr[str]: return s if not typedefs.is_unknown(s) else undefined.Undefined - return iterators.FlatIterator( + return iterators.Iterator( [ entity.SearchableEntity( net=self._net, @@ -1817,8 +1811,8 @@ def deserialize_activity( def deserialize_activities( self, payload: typedefs.JSONObject - ) -> iterators.FlatIterator[activity.Activity]: - return iterators.FlatIterator( + ) -> iterators.Iterator[activity.Activity]: + return iterators.Iterator( [ self.deserialize_activity(activity_) for activity_ in payload["activities"] @@ -2003,8 +1997,8 @@ def deserialize_aggregated_activity( def deserialize_aggregated_activities( self, payload: typedefs.JSONObject - ) -> iterators.FlatIterator[activity.AggregatedActivity]: - return iterators.FlatIterator( + ) -> iterators.Iterator[activity.AggregatedActivity]: + return iterators.Iterator( [ self.deserialize_aggregated_activity(activity) for activity in payload["activities"] diff --git a/aiobungie/internal/iterators.py b/aiobungie/internal/iterators.py index 3c46656b..b8ac9746 100644 --- a/aiobungie/internal/iterators.py +++ b/aiobungie/internal/iterators.py @@ -23,7 +23,7 @@ from __future__ import annotations -__all__: tuple[str, ...] = ("FlatIterator", "into_iter") +__all__: tuple[str, ...] = ("Iterator", "into_iter") import collections.abc as collections import itertools @@ -41,13 +41,13 @@ _B = typing.TypeVar("_B", bound=collections.Callable[..., typing.Any]) -class FlatIterator(typing.Generic[Item]): +class Iterator(typing.Generic[Item]): """A Flat, In-Memory iterator for sequenced based data. Example ------- ```py - iterator = FlatIterator([1, 2, 3]) + iterator = Iterator([1, 2, 3]) # Map the results. for item in iterator.map(lambda item: item * 2): @@ -67,9 +67,9 @@ class FlatIterator(typing.Generic[Item]): # 3 # Union two iterators. - iterator2 = FlatIterator([4, 5, 6]) + iterator2 = Iterator([4, 5, 6]) final = iterator | iterator2 - # + # ``` Parameters @@ -98,7 +98,7 @@ def collect( Example ------- - >>> iterator = FlatIterator([1, 2, 3]) + >>> iterator = Iterator([1, 2, 3]) >>> iterator.collect(casting=str) ["1", "2", "3"] @@ -123,7 +123,7 @@ def next(self) -> Item: Example ------- ```py - iterator = FlatIterator(["1", "2", "3"]) + iterator = Iterator(["1", "2", "3"]) item = iterator.next() assert item == "1" item = iterator.next() @@ -142,15 +142,15 @@ def next(self) -> Item: def map( self, predicate: collections.Callable[[Item], OtherItem] - ) -> FlatIterator[OtherItem]: + ) -> Iterator[OtherItem]: """Maps each item in the iterator to its predicated value. Example ------- ```py - iterator = FlatIterator(["1", "2", "3"]).map(lambda value: int(value)) + iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value)) print(iterator) - # + # ``` Parameters @@ -160,7 +160,7 @@ def map( Returns ------- - `FlatIterator[OtherItem]` + `Iterator[OtherItem]` The mapped iterator. Raises @@ -168,18 +168,18 @@ def map( `StopIteration` If no elements are left in the iterator. """ - return FlatIterator(map(predicate, self._items)) + return Iterator(map(predicate, self._items)) - def take(self, n: int) -> FlatIterator[Item]: + def take(self, n: int) -> Iterator[Item]: """Take the first number of items until the number of items are yielded or the end of the iterator is reached. Example ------- ```py - iterator = FlatIterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT]) + iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT]) print(iterator.take(2)) - # + # ``` Parameters @@ -192,19 +192,19 @@ def take(self, n: int) -> FlatIterator[Item]: `StopIteration` If no elements are left in the iterator. """ - return FlatIterator(itertools.islice(self._items, n)) + return Iterator(itertools.islice(self._items, n)) def take_while( self, predicate: collections.Callable[[Item], bool] - ) -> FlatIterator[Item]: + ) -> Iterator[Item]: """Yields items from the iterator while predicate returns `True`. Example ------- ```py - iterator = FlatIterator([STEAM, XBOX, STADIA]) + iterator = Iterator([STEAM, XBOX, STADIA]) print(iterator.take_while(lambda platform: platform is not XBOX)) - # + # ``` Parameters @@ -217,19 +217,19 @@ def take_while( `StopIteration` If no elements are left in the iterator. """ - return FlatIterator(itertools.takewhile(predicate, self._items)) + return Iterator(itertools.takewhile(predicate, self._items)) def drop_while( self, predicate: collections.Callable[[Item], bool] - ) -> FlatIterator[Item]: + ) -> Iterator[Item]: """Yields items from the iterator while predicate returns `False`. Example ------- ```py - iterator = FlatIterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")]) + iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")]) print(iterator.drop_while(lambda membership: membership.name is not "Jim")) - # + # ``` Parameters @@ -242,79 +242,50 @@ def drop_while( `StopIteration` If no elements are left in the iterator. """ - return FlatIterator(itertools.dropwhile(predicate, self._items)) + return Iterator(itertools.dropwhile(predicate, self._items)) - def filter( - self, predicate: collections.Callable[[Item], bool] - ) -> FlatIterator[Item]: + def filter(self, predicate: collections.Callable[[Item], bool]) -> Iterator[Item]: """Filters the iterator to only yield items that match the predicate. Example ------- ```py - names = FlatIterator(["Jim", "Bob", "Mike", "Jess"]) + names = Iterator(["Jim", "Bob", "Mike", "Jess"]) print(names.filter(lambda n: n != "Jim")) - # + # ``` """ - return FlatIterator(filter(predicate, self._items)) + return Iterator(filter(predicate, self._items)) - def skip(self, n: int) -> FlatIterator[Item]: + def skip(self, n: int) -> Iterator[Item]: """Skips the first number of items in the iterator. Example ------- ```py - iterator = FlatIterator([STEAM, XBOX, STADIA]) + iterator = Iterator([STEAM, XBOX, STADIA]) print(iterator.skip(1)) - # - ``` - """ - return FlatIterator(itertools.islice(self._items, n, None)) - - def discard( - self, predicate: collections.Callable[[Item], bool] - ) -> FlatIterator[Item]: - """Discards all elements in the iterator for which the predicate function returns true. - - Example - ------- - ```py - iterator = FlatIterator(['A', 'B', 'C']) - print(iterator.discard(lambda x: x == 'B')) - # + # ``` - - Parameters - ---------- - predicate: `collections.Callable[[Item], bool]` - The function to test each item in the iterator. - - Raises - ------ - `StopIteration` - If no elements are left in the iterator. """ - return FlatIterator(filter(lambda x: not predicate(x), self._items)) + return Iterator(itertools.islice(self._items, n, None)) - def zip( - self, other: FlatIterator[OtherItem] - ) -> FlatIterator[tuple[Item, OtherItem]]: + def zip(self, other: Iterator[OtherItem]) -> Iterator[tuple[Item, OtherItem]]: """Zips the iterator with another iterable. Example ------- ```py - iterator = FlatIterator([1, 3, 5]) - other = FlatIterator([2, 4, 6]) + iterator = Iterator([1, 3, 5]) + other = Iterator([2, 4, 6]) for item, other_item in iterator.zip(other): print(item, other_item) - # + # ``` Parameters ---------- - other: `FlatIterator[OtherItem]` + other: `Iterator[OtherItem]` The iterable to zip with. Raises @@ -322,7 +293,7 @@ def zip( `StopIteration` If no elements are left in the iterator. """ - return FlatIterator(zip(self._items, other)) + return Iterator(zip(self._items, other)) def all(self, predicate: collections.Callable[[Item], bool]) -> bool: """`True` if all items in the iterator match the predicate. @@ -330,7 +301,7 @@ def all(self, predicate: collections.Callable[[Item], bool]) -> bool: Example ------- ```py - iterator = FlatIterator([1, 2, 3]) + iterator = Iterator([1, 2, 3]) while iterator.all(lambda item: isinstance(item, int)): print("Still all integers") continue @@ -355,7 +326,7 @@ def any(self, predicate: collections.Callable[[Item], bool]) -> bool: Example ------- ```py - iterator = FlatIterator([1, 2, 3]) + iterator = Iterator([1, 2, 3]) if iterator.any(lambda item: isinstance(item, int)): print("At least one item is an int.") # At least one item is an int. @@ -378,15 +349,15 @@ def sort( *, key: collections.Callable[[Item], typeshed.SupportsRichComparison], reverse: bool = False, - ) -> FlatIterator[Item]: + ) -> Iterator[Item]: """Sorts the iterator. Example ------- ```py - iterator = FlatIterator([3, 1, 6, 7]) + iterator = Iterator([3, 1, 6, 7]) print(iterator.sort(key=lambda item: item)) - # + # ``` Parameters @@ -401,7 +372,7 @@ def sort( `StopIteration` If no elements are left in the iterator. """ - return FlatIterator(sorted(self._items, key=key, reverse=reverse)) + return Iterator(sorted(self._items, key=key, reverse=reverse)) def first(self) -> Item: """Returns the first item in the iterator. @@ -409,7 +380,7 @@ def first(self) -> Item: Example ------- ```py - iterator = FlatIterator([3, 1, 6, 7]) + iterator = Iterator([3, 1, 6, 7]) print(iterator.first()) 3 ``` @@ -421,15 +392,15 @@ def first(self) -> Item: """ return self.take(1).next() - def reversed(self) -> FlatIterator[Item]: + def reversed(self) -> Iterator[Item]: """Returns a new iterator that yields the items in the iterator in reverse order. Example ------- ```py - iterator = FlatIterator([3, 1, 6, 7]) + iterator = Iterator([3, 1, 6, 7]) print(iterator.reversed()) - # + # ``` Raises @@ -437,7 +408,7 @@ def reversed(self) -> FlatIterator[Item]: `StopIteration` If no elements are left in the iterator. """ - return FlatIterator(reversed(self.collect())) + return Iterator(reversed(self.collect())) def count(self) -> int: """Returns the number of items in the iterator. @@ -445,7 +416,7 @@ def count(self) -> int: Example ------- ```py - iterator = FlatIterator([3, 1, 6, 7]) + iterator = Iterator([3, 1, 6, 7]) print(iterator.count()) 4 ``` @@ -456,21 +427,21 @@ def count(self) -> int: return count - def union(self, other: FlatIterator[Item]) -> FlatIterator[Item]: + def union(self, other: Iterator[Item]) -> Iterator[Item]: """Returns a new iterator that yields all items from both iterators. Example ------- ```py - iterator = FlatIterator([1, 2, 3]) - other = FlatIterator([4, 5, 6]) + iterator = Iterator([1, 2, 3]) + other = Iterator([4, 5, 6]) print(iterator.union(other)) - # + # ``` Parameters ---------- - other: `FlatIterator[Item]` + other: `Iterator[Item]` The iterable to union with. Raises @@ -478,7 +449,7 @@ def union(self, other: FlatIterator[Item]) -> FlatIterator[Item]: `StopIteration` If no elements are left in the iterator. """ - return FlatIterator(itertools.chain(self._items, other)) + return Iterator(itertools.chain(self._items, other)) def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None: """Calls the function on each item in the iterator. @@ -486,7 +457,7 @@ def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None: Example ------- ```py - iterator = FlatIterator([1, 2, 3]) + iterator = Iterator([1, 2, 3]) iterator.for_each(lambda item: print(item)) # 1 # 2 @@ -527,13 +498,13 @@ async def main(): """ await _helpers.awaits(*(func(item) for item in self)) - def enumerate(self, *, start: int = 0) -> FlatIterator[tuple[int, Item]]: + def enumerate(self, *, start: int = 0) -> Iterator[tuple[int, Item]]: """Returns a new iterator that yields tuples of the index and item. Example ------- ```py - iterator = FlatIterator([1, 2, 3]) + iterator = Iterator([1, 2, 3]) for index, item in iterator.enumerate(): print(index, item) # 0 1 @@ -546,7 +517,7 @@ def enumerate(self, *, start: int = 0) -> FlatIterator[tuple[int, Item]]: `StopIteration` If no elements are left in the iterator. """ - return FlatIterator(enumerate(self._items, start=start)) + return Iterator(enumerate(self._items, start=start)) def _ok(self) -> typing.NoReturn: raise StopIteration("No more items in the iterator.") from None @@ -557,7 +528,7 @@ def __getitem__(self, index: int) -> Item: except IndexError: self._ok() - def __or__(self, other: FlatIterator[Item]) -> FlatIterator[Item]: + def __or__(self, other: Iterator[Item]) -> Iterator[Item]: return self.union(other) # This is a never. @@ -572,7 +543,7 @@ def __repr__(self) -> str: def __len__(self) -> int: return self.count() - def __iter__(self) -> FlatIterator[Item]: + def __iter__(self) -> Iterator[Item]: return self def __next__(self) -> Item: @@ -586,7 +557,7 @@ def __next__(self) -> Item: def into_iter( iterable: collections.Iterable[Item], -) -> FlatIterator[Item]: +) -> Iterator[Item]: """Transform an iterable into an flat iterator. Example @@ -610,4 +581,4 @@ def into_iter( `StopIteration` If no elements are left in the iterator. """ - return FlatIterator(iterable) + return Iterator(iterable) diff --git a/aiobungie/rest.py b/aiobungie/rest.py index 4f2aebb1..f57e0edc 100644 --- a/aiobungie/rest.py +++ b/aiobungie/rest.py @@ -195,11 +195,10 @@ def create( connect: typing.Optional[float] = None, socket_read: typing.Optional[float] = None, socket_connect: typing.Optional[float] = None, - **kwargs: typing.Any, ) -> _Session: """Creates a new TCP connection client session.""" session = aiohttp.ClientSession( - connector=aiohttp.TCPConnector(ssl=False, **kwargs), + connector=aiohttp.TCPConnector(ssl=False), connector_owner=owner, raise_for_status=raise_status, timeout=aiohttp.ClientTimeout( @@ -217,7 +216,6 @@ async def close(self) -> None: _LOG.debug("Closing session...") if self.client_session.connector is not None: await self.client_session.connector.close() - await asyncio.sleep(0.025) _LOG.debug("Session closed.") @@ -467,13 +465,7 @@ def open(self) -> None: if self.is_alive: raise RuntimeError("Cannot open a new session while it's already open.") - self._session = _Session.create( - owner=False, - raise_status=False, - connect=None, - socket_read=None, - socket_connect=None, - ) + self._session = _Session.create(owner=False, raise_status=False) @typing.final def enable_debugging( diff --git a/docs/aiobungie.html b/docs/aiobungie.html index 020ee621..5297d3a5 100644 --- a/docs/aiobungie.html +++ b/docs/aiobungie.html @@ -3,7 +3,7 @@ - + aiobungie API documentation @@ -51,18 +51,6 @@

API Documentation

  • AmmoType
  • @@ -90,42 +78,12 @@

    API Documentation

  • ClanMemberType
  • Class
  • @@ -264,15 +222,6 @@

    API Documentation

  • ClosedReasons - - - - - built with pdocpdoc logo - - - -
    -
    -

    -aiobungie

    - -

    A Pythonic async/await wrapper for interacting with the Bungie API.

    - -

    Base client.

    - -
    Example
    - -
    import aiobungie
    -
    -client = aiobungie.Client('YOUR_API_KEY')
    -
    -# Search for Destiny2 users.
    -async def main() -> None:
    -    users = await client.search_users('Crit')
    -
    -    # Iterate over the users and take the first 5 results.
    -    for user in users.take(5):
    -        print(f'{user.name} ({user.code})')
    -
    -        # Iterate through the users memberships.
    -        for membership in user.memberships:
    -            print(membership.type, membership.id)
    -
    -client.run(main()) # or asyncio.run(main())
    -
    - -

    Single RESTClient instance.

    - -

    The difference between base client and the REST clients:

    - -
      -
    • No Hight-Level concepts.
    • -
    • All returned data are pure JSON objects from the API.
    • -
    • No object creation.
    • -
    - -
    Example
    - -
    import aiobungie
    -
    -async def main() -> None:
    -    # Using `async with` context manager to close the session properly.
    -    async with aiobungie.RESTClient("TOKEN") as rest:
    -        payload = await rest.fetch_player('Fateꀒ', 4275)
    -
    -        for membership in payload:
    -            print(membership['membershipId'], membership['iconPath'])
    -
    -import asyncio
    -asyncio.run(main())
    -
    - -

    REST client pool.

    - -

    A REST client pool allows you to acquire multiple RESTClient instances that shares the same connection.

    - -
    Example
    - -
    import aiobungie
    -import asyncio
    -
    -pool = aiobungie.RESTPool("token")
    -
    -async def func1() -> None:
    -    async with pool.acquire() as instance:
    -        tokens = await instance.fetch_oauth2_tokens('code')
    -        pool.metadata['tokens'] = tokens
    -
    -# Other instance may access the tokens from pool since its shared.
    -
    -async def func2() -> None:
    -    async with pool.acquire() as instance:
    -        tokens = pool.metadata['tokens']
    -        tokens = await instance.refresh_access_token(tokens.refresh_token)
    -
    -async def main() -> None:
    -    await asyncio.gather(func1(), func2())
    -
    -asyncio.run(main())
    -
    - -

    Should you use the base client or the REST client? -This returns to you. For an example if you're building a website.

    - -

    You can use python as a REST API in the backend with the RESTClient since all returned object are JSON objects. -Which gives you the freedom to deserialize it and implement your own logic in the front-end.

    - -

    Or of you're building a Discord bot for an example or something simple. The base client is the way to go.

    -
    - - - - - -
      1# MIT License
    -  2#
    -  3# Copyright (c) 2020 - Present nxtlo
    -  4#
    -  5# Permission is hereby granted, free of charge, to any person obtaining a copy
    -  6# of this software and associated documentation files (the "Software"), to deal
    -  7# in the Software without restriction, including without limitation the rights
    -  8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -  9# copies of the Software, and to permit persons to whom the Software is
    - 10# furnished to do so, subject to the following conditions:
    - 11#
    - 12# The above copyright notice and this permission notice shall be included in all
    - 13# copies or substantial portions of the Software.
    - 14#
    - 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    - 16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    - 17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    - 18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    - 19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    - 20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    - 21# SOFTWARE.
    - 22
    - 23"""A Pythonic `async`/`await` wrapper for interacting with the Bungie API.
    - 24
    - 25Base client.
    - 26
    - 27Example
    - 28-------
    - 29```py
    - 30import aiobungie
    - 31
    - 32client = aiobungie.Client('YOUR_API_KEY')
    - 33
    - 34# Search for Destiny2 users.
    - 35async def main() -> None:
    - 36    users = await client.search_users('Crit')
    - 37
    - 38    # Iterate over the users and take the first 5 results.
    - 39    for user in users.take(5):
    - 40        print(f'{user.name} ({user.code})')
    - 41
    - 42        # Iterate through the users memberships.
    - 43        for membership in user.memberships:
    - 44            print(membership.type, membership.id)
    - 45
    - 46client.run(main()) # or asyncio.run(main())
    - 47```
    - 48
    - 49Single RESTClient instance.
    - 50
    - 51The difference between base client and the REST clients:
    - 52
    - 53* No Hight-Level concepts.
    - 54* All returned data are pure JSON objects from the API.
    - 55* No object creation.
    - 56
    - 57Example
    - 58-------
    - 59```py
    - 60import aiobungie
    - 61
    - 62async def main() -> None:
    - 63    # Using `async with` context manager to close the session properly.
    - 64    async with aiobungie.RESTClient("TOKEN") as rest:
    - 65        payload = await rest.fetch_player('Fateꀒ', 4275)
    - 66
    - 67        for membership in payload:
    - 68            print(membership['membershipId'], membership['iconPath'])
    - 69
    - 70import asyncio
    - 71asyncio.run(main())
    - 72```
    - 73
    - 74REST client pool.
    - 75
    - 76A REST client pool allows you to acquire multiple `RESTClient` instances that shares the same connection.
    - 77
    - 78Example
    - 79-------
    - 80```py
    - 81import aiobungie
    - 82import asyncio
    - 83
    - 84pool = aiobungie.RESTPool("token")
    - 85
    - 86async def func1() -> None:
    - 87    async with pool.acquire() as instance:
    - 88        tokens = await instance.fetch_oauth2_tokens('code')
    - 89        pool.metadata['tokens'] = tokens
    - 90
    - 91# Other instance may access the tokens from pool since its shared.
    - 92
    - 93async def func2() -> None:
    - 94    async with pool.acquire() as instance:
    - 95        tokens = pool.metadata['tokens']
    - 96        tokens = await instance.refresh_access_token(tokens.refresh_token)
    - 97
    - 98async def main() -> None:
    - 99    await asyncio.gather(func1(), func2())
    -100
    -101asyncio.run(main())
    -102```
    -103
    -104Should you use the base client or the REST client?
    -105This returns to you. For an example if you're building a website.
    -106
    -107You can use python as a REST API in the backend with the RESTClient since all returned object are JSON objects.
    -108Which gives you the freedom to deserialize it and implement your own logic in the front-end.
    -109
    -110Or of you're building a Discord bot for an example or something simple. The base client is the way to go.
    -111"""
    -112
    -113
    -114from __future__ import annotations
    -115
    -116from aiobungie import builders
    -117from aiobungie import crates
    -118from aiobungie import interfaces
    -119from aiobungie import traits
    -120from aiobungie import typedefs
    -121from aiobungie import url
    -122from aiobungie.client import Client
    -123from aiobungie.error import *
    -124from aiobungie.internal import iterators
    -125from aiobungie.internal.assets import Image
    -126from aiobungie.internal.enums import *
    -127from aiobungie.internal.factory import Factory
    -128from aiobungie.internal.iterators import *
    -129from aiobungie.rest import *
    -130from aiobungie.undefined import Undefined
    -131from aiobungie.undefined import UndefinedOr
    -132from aiobungie.undefined import UndefinedType
    -133
    -134from ._info import __about__
    -135from ._info import __author__
    -136from ._info import __docs__
    -137from ._info import __email__
    -138from ._info import __license__
    -139from ._info import __url__
    -140from ._info import __version__
    -141
    -142# Alias for crate for backwards compatibility.
    -143crate = crates
    -144
    -145# Activity enums
    -146from .crates.activity import Difficulty
    -147
    -148# Components enums
    -149from .crates.components import ComponentFields
    -150from .crates.components import ComponentPrivacy
    -151
    -152# Entity enums
    -153from .crates.entity import GatingScope
    -154from .crates.entity import ObjectiveUIStyle
    -155from .crates.entity import ValueUIStyle
    -156
    -157# Fireteam enums.
    -158from .crates.fireteams import FireteamActivity
    -159from .crates.fireteams import FireteamDate
    -160from .crates.fireteams import FireteamLanguage
    -161from .crates.fireteams import FireteamPlatform
    -162
    -163# Records enums
    -164from .crates.records import RecordState
    -165
    -166__all__ = [mod for mod in dir() if not mod.startswith("_")]  # type: ignore
    -
    - - -
    -
    - -
    -
    @attrs.define(auto_exc=True)
    - - class - AiobungieError(builtins.RuntimeError): - - - -
    - -
    57@attrs.define(auto_exc=True)
    -58class AiobungieError(RuntimeError):
    -59    """Base exception class that all other errors inherit from."""
    -
    - - -

    Base exception class that all other errors inherit from.

    -
    - - -
    - -
    - - AiobungieError() - - - -
    - -
    2def __init__(self, ):
    -3    BaseException.__init__(self, )
    -
    - - -

    Method generated by attrs for class AiobungieError.

    -
    - - -
    -
    -
    Inherited Members
    -
    -
    builtins.BaseException
    -
    with_traceback
    -
    args
    - -
    -
    -
    -
    -
    - -
    -
    @typing.final
    - - class - AmmoType(builtins.int, aiobungie.Enum): - - - -
    - -
    646@typing.final
    -647class AmmoType(int, Enum):
    -648    """AN enum for Detyiny 2 ammo types."""
    -649
    -650    NONE = 0
    -651    PRIMARY = 1
    -652    SPECIAL = 2
    -653    HEAVY = 3
    -
    - - -

    AN enum for Detyiny 2 ammo types.

    -
    - - -
    -
    - NONE = <AmmoType.NONE: 0> - - -
    - - - - -
    -
    -
    - PRIMARY = <AmmoType.PRIMARY: 1> - - -
    - - - - -
    -
    -
    - SPECIAL = <AmmoType.SPECIAL: 2> - - -
    - - - - -
    -
    -
    - HEAVY = <AmmoType.HEAVY: 3> - - -
    - - - - -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    - -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    - -
    -
    -
    -
    -
    - -
    -
    @attrs.define(auto_exc=True)
    - - class - BadRequest(aiobungie.HTTPError): - - - -
    - -
    147@attrs.define(auto_exc=True)
    -148class BadRequest(HTTPError):
    -149    """Bad requests exceptions."""
    -150
    -151    url: typing.Optional[typedefs.StrOrURL]
    -152    """The URL/endpoint caused this error."""
    -153
    -154    body: typing.Any
    -155    """The response body."""
    -156
    -157    headers: multidict.CIMultiDictProxy[str]
    -158    """The response headers."""
    -159
    -160    http_status: http.HTTPStatus = attrs.field(default=http.HTTPStatus.BAD_REQUEST)
    -
    - - -

    Bad requests exceptions.

    -
    - - -
    - -
    - - BadRequest( message: str, url: Union[str, yarl.URL, NoneType], body: Any, headers: multidict._multidict.CIMultiDictProxy[str], http_status: http.HTTPStatus = <HTTPStatus.BAD_REQUEST: 400>) - - - -
    - -
    2def __init__(self, message, url, body, headers, http_status=attr_dict['http_status'].default):
    -3    self.message = message
    -4    self.url = url
    -5    self.body = body
    -6    self.headers = headers
    -7    self.http_status = http_status
    -8    BaseException.__init__(self, self.message,self.url,self.body,self.headers,self.http_status)
    -
    - - -

    Method generated by attrs for class BadRequest.

    -
    - - -
    -
    -
    - url: Union[str, yarl.URL, NoneType] - - -
    - - -

    The URL/endpoint caused this error.

    -
    - - -
    -
    -
    - body: Any - - -
    - - -

    The response body.

    -
    - - -
    -
    -
    - headers: multidict._multidict.CIMultiDictProxy[str] - - -
    - - -

    The response headers.

    -
    - - -
    -
    -
    - http_status: http.HTTPStatus - - -
    - - -

    The response status.

    -
    - - -
    -
    -
    Inherited Members
    -
    - -
    builtins.BaseException
    -
    with_traceback
    -
    args
    - -
    -
    -
    -
    -
    - -
    -
    @typing.final
    - - class - ClanMemberType(builtins.int, aiobungie.Enum): - - - -
    - -
    701@typing.final
    -702class ClanMemberType(int, Enum):
    -703    """An enum for bungie clan member types."""
    -704
    -705    NONE = 0
    -706    BEGINNER = 1
    -707    MEMBER = 2
    -708    ADMIN = 3
    -709    ACTING_FOUNDER = 4
    -710    FOUNDER = 5
    -
    - - -

    An enum for bungie clan member types.

    -
    - - -
    -
    - NONE = <ClanMemberType.NONE: 0> - - -
    - - - - -
    -
    -
    - BEGINNER = <ClanMemberType.BEGINNER: 1> - - -
    - - - - -
    -
    -
    - MEMBER = <ClanMemberType.MEMBER: 2> - - -
    - - - - -
    -
    -
    - ADMIN = <ClanMemberType.ADMIN: 3> - - -
    - - - - -
    -
    -
    - ACTING_FOUNDER = <ClanMemberType.ACTING_FOUNDER: 4> - - -
    - - - - -
    -
    -
    - FOUNDER = <ClanMemberType.FOUNDER: 5> - - -
    - - - - -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    - -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    - -
    -
    -
    -
    -
    - -
    -
    @typing.final
    - - class - Class(builtins.int, aiobungie.Enum): - - - -
    - -
    477@typing.final
    -478class Class(int, Enum):
    -479    """An Enum for Destiny character classes."""
    -480
    -481    TITAN = 0
    -482    HUNTER = 1
    -483    WARLOCK = 2
    -484    UNKNOWN = 3
    -
    - - -

    An Enum for Destiny character classes.

    -
    - - -
    -
    - TITAN = <Class.TITAN: 0> - - -
    - - - - -
    -
    -
    - HUNTER = <Class.HUNTER: 1> - - -
    - - - - -
    -
    -
    - WARLOCK = <Class.WARLOCK: 2> - - -
    - - - - -
    -
    -
    - UNKNOWN = <Class.UNKNOWN: 3> - - -
    - - - - -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    - -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    - -
    -
    -
    -
    -
    - -
    - - class - Client(aiobungie.traits.ClientApp): - - - -
    - -
      61class Client(traits.ClientApp):
    -  62    """Standard Bungie API client application.
    -  63
    -  64    This client deserialize the REST JSON responses using `aiobungie.internal.factory.Factory`
    -  65    and returns `aiobungie.crates` Python object implementations of the responses.
    -  66
    -  67    A `aiobungie.RESTClient` REST client can also be used alone for low-level concepts.
    -  68
    -  69    Example
    -  70    -------
    -  71    ```py
    -  72    import aiobungie
    -  73
    -  74    client = aiobungie.Client('...')
    -  75
    -  76    async def main():
    -  77        async with client.rest:
    -  78            user = await client.fetch_current_user_memberships('...')
    -  79            print(user)
    -  80    ```
    -  81
    -  82    Parameters
    -  83    -----------
    -  84    token: `str`
    -  85        Your Bungie's API key or Token from the developer's portal.
    -  86
    -  87    Other Parameters
    -  88    ----------------
    -  89    rest_client: `aiobungie.interfaces.RESTInterface | None`
    -  90        An optional rest client instance you can pass.
    -  91        If set to `None` then the client will use the default instance.
    -  92
    -  93    max_retries : `int`
    -  94        The max retries number to retry if the request hit a `5xx` status code.
    -  95    max_ratelimit_retries : `int`
    -  96        The max retries number to retry if the request hit a `429` status code. Defaults to `3`.
    -  97    client_secret : `str | None`
    -  98        An optional application client secret,
    -  99        This is only needed if you're fetching OAuth2 tokens with this client.
    - 100    client_id : `int | None`
    - 101        An optional application client id,
    - 102        This is only needed if you're fetching OAuth2 tokens with this client.
    - 103    """
    - 104
    - 105    __slots__ = ("_rest", "_factory", "_client_secret", "_client_id")
    - 106
    - 107    def __init__(
    - 108        self,
    - 109        token: str,
    - 110        /,
    - 111        client_secret: typing.Optional[str] = None,
    - 112        client_id: typing.Optional[int] = None,
    - 113        *,
    - 114        rest_client: typing.Optional[interfaces.RESTInterface] = None,
    - 115        max_retries: int = 4,
    - 116        max_ratelimit_retries: int = 3,
    - 117    ) -> None:
    - 118
    - 119        self._client_secret = client_secret
    - 120        self._client_id = client_id
    - 121
    - 122        self._rest = (
    - 123            rest_client
    - 124            if rest_client is not None
    - 125            else rest_.RESTClient(
    - 126                token,
    - 127                client_secret,
    - 128                client_id,
    - 129                max_retries=max_retries,
    - 130                max_ratelimit_retries=max_ratelimit_retries,
    - 131            )
    - 132        )
    - 133
    - 134        self._factory = factory_.Factory(self)
    - 135
    - 136    @property
    - 137    def factory(self) -> factory_.Factory:
    - 138        return self._factory
    - 139
    - 140    @property
    - 141    def rest(self) -> interfaces.RESTInterface:
    - 142        return self._rest
    - 143
    - 144    @property
    - 145    def request(self) -> Client:
    - 146        return copy.copy(self)
    - 147
    - 148    @property
    - 149    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    - 150        return self._rest.metadata
    - 151
    - 152    def run(
    - 153        self, future: collections.Coroutine[typing.Any, None, None], debug: bool = False
    - 154    ) -> None:
    - 155        loop: typing.Final[asyncio.AbstractEventLoop] = helpers.get_or_make_loop()
    - 156        try:
    - 157            if not loop.is_running():
    - 158                loop.set_debug(debug)
    - 159                loop.run_until_complete(future)
    - 160
    - 161        except Exception as exc:
    - 162            raise RuntimeError(f"Failed to run {future.__qualname__}") from exc
    - 163
    - 164        except KeyboardInterrupt:
    - 165            _LOG.warn("Unexpected Keyboard interrupt. Exiting.")
    - 166            return
    - 167
    - 168    # * User methods.
    - 169
    - 170    async def fetch_current_user_memberships(self, access_token: str, /) -> user.User:
    - 171        """Fetch and return a user object of the bungie net user associated with account.
    - 172
    - 173        .. warning::
    - 174            This method requires OAuth2 scope and a Bearer access token.
    - 175
    - 176        Parameters
    - 177        ----------
    - 178        access_token : `str`
    - 179            A valid Bearer access token for the authorization.
    - 180
    - 181        Returns
    - 182        -------
    - 183        `aiobungie.crates.user.User`
    - 184            A user object includes the Destiny memberships and Bungie.net user.
    - 185        """
    - 186        resp = await self.rest.fetch_current_user_memberships(access_token)
    - 187
    - 188        return self.factory.deserialize_user(resp)
    - 189
    - 190    async def fetch_bungie_user(self, id: int, /) -> user.BungieUser:
    - 191        """Fetch a Bungie user by their BungieNet id.
    - 192
    - 193        .. note::
    - 194            This returns a Bungie user membership only. Take a look at `Client.fetch_membership_from_id`
    - 195            for other memberships.
    - 196
    - 197        Parameters
    - 198        ----------
    - 199        id: `int`
    - 200            The user id.
    - 201
    - 202        Returns
    - 203        -------
    - 204        `aiobungie.crates.user.BungieUser`
    - 205            A Bungie user.
    - 206
    - 207        Raises
    - 208        ------
    - 209        `aiobungie.error.NotFound`
    - 210            The user was not found.
    - 211        """
    - 212        payload = await self.rest.fetch_bungie_user(id)
    - 213
    - 214        return self.factory.deserialize_bungie_user(payload)
    - 215
    - 216    async def search_users(
    - 217        self, name: str, /
    - 218    ) -> iterators.FlatIterator[user.SearchableDestinyUser]:
    - 219        """Search for players and return all players that matches the same name.
    - 220
    - 221        Parameters
    - 222        ----------
    - 223        name : `buildins.str`
    - 224            The user name.
    - 225
    - 226        Returns
    - 227        -------
    - 228        `aiobungie.iterators.FlatIterator[aiobungie.crates.DestinyMembership]`
    - 229            A sequence of destiny memberships.
    - 230        """
    - 231        payload = await self.rest.search_users(name)
    - 232
    - 233        return iterators.FlatIterator(
    - 234            [
    - 235                self.factory.deserialize_searched_user(user)
    - 236                for user in payload["searchResults"]
    - 237            ]
    - 238        )
    - 239
    - 240    async def fetch_user_themes(self) -> collections.Sequence[user.UserThemes]:
    - 241        """Fetch all available user themes.
    - 242
    - 243        Returns
    - 244        -------
    - 245        `collections.Sequence[aiobungie.crates.user.UserThemes]`
    - 246            A sequence of user themes.
    - 247        """
    - 248        data = await self.rest.fetch_user_themes()
    - 249
    - 250        return self.factory.deserialize_user_themes(data)
    - 251
    - 252    async def fetch_hard_types(
    - 253        self,
    - 254        credential: int,
    - 255        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
    - 256        /,
    - 257    ) -> user.HardLinkedMembership:
    - 258        """Gets any hard linked membership given a credential.
    - 259        Only works for credentials that are public just `aiobungie.CredentialType.STEAMID` right now.
    - 260        Cross Save aware.
    - 261
    - 262        Parameters
    - 263        ----------
    - 264        credential: `int`
    - 265            A valid SteamID64
    - 266        type: `aiobungie.CredentialType`
    - 267            The credential type. This must not be changed
    - 268            Since its only credential that works "currently"
    - 269
    - 270        Returns
    - 271        -------
    - 272        `aiobungie.crates.user.HardLinkedMembership`
    - 273            Information about the hard linked data.
    - 274        """
    - 275
    - 276        payload = await self.rest.fetch_hardlinked_credentials(credential, type)
    - 277
    - 278        return user.HardLinkedMembership(
    - 279            id=int(payload["membershipId"]),
    - 280            type=enums.MembershipType(payload["membershipType"]),
    - 281            cross_save_type=enums.MembershipType(payload["CrossSaveOverriddenType"]),
    - 282        )
    - 283
    - 284    async def fetch_membership_from_id(
    - 285        self,
    - 286        id: int,
    - 287        /,
    - 288        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    - 289    ) -> user.User:
    - 290        """Fetch Bungie user's memberships from their id.
    - 291
    - 292        Notes
    - 293        -----
    - 294        * This returns both BungieNet membership and a sequence of the player's DestinyMemberships
    - 295        Which includes Stadia, Xbox, Steam and PSN memberships if the player has them,
    - 296        see `aiobungie.crates.user.DestinyMembership` for more details.
    - 297        * If you only want the bungie user. Consider using `Client.fetch_user` method.
    - 298
    - 299        Parameters
    - 300        ----------
    - 301        id : `int`
    - 302            The user's id.
    - 303        type : `aiobungie.MembershipType`
    - 304            The user's membership type.
    - 305
    - 306        Returns
    - 307        -------
    - 308        `aiobungie.crates.User`
    - 309            A Bungie user with their membership types.
    - 310
    - 311        Raises
    - 312        ------
    - 313        aiobungie.NotFound
    - 314            The requested user was not found.
    - 315        """
    - 316        payload = await self.rest.fetch_membership_from_id(id, type)
    - 317
    - 318        return self.factory.deserialize_user(payload)
    - 319
    - 320    async def fetch_user_credentials(
    - 321        self, access_token: str, membership_id: int, /
    - 322    ) -> collections.Sequence[user.UserCredentials]:
    - 323        """Fetch an array of credential types attached to the requested account.
    - 324
    - 325        .. note::
    - 326            This method require OAuth2 Bearer access token.
    - 327
    - 328        Parameters
    - 329        ----------
    - 330        access_token : `str`
    - 331            The bearer access token associated with the bungie account.
    - 332        membership_id : `int`
    - 333            The id of the membership to return.
    - 334
    - 335        Returns
    - 336        -------
    - 337        `collections.Sequence[aiobungie.crates.UserCredentials]`
    - 338            A sequence of the attached user credentials.
    - 339
    - 340        Raises
    - 341        ------
    - 342        `aiobungie.Unauthorized`
    - 343            The access token was wrong or no access token passed.
    - 344        """
    - 345        resp = await self.rest.fetch_user_credentials(access_token, membership_id)
    - 346
    - 347        return self.factory.deserialize_user_credentials(resp)
    - 348
    - 349    # * Destiny 2.
    - 350
    - 351    async def fetch_profile(
    - 352        self,
    - 353        member_id: int,
    - 354        type: typedefs.IntAnd[enums.MembershipType],
    - 355        components: list[enums.ComponentType],
    - 356        auth: typing.Optional[str] = None,
    - 357    ) -> components.Component:
    - 358        """
    - 359        Fetch a bungie profile passing components to the request.
    - 360
    - 361        Parameters
    - 362        ----------
    - 363        member_id: `int`
    - 364            The member's id.
    - 365        type: `aiobungie.MembershipType`
    - 366            A valid membership type.
    - 367        components : `list[aiobungie.ComponentType]`
    - 368            List of profile components to collect and return.
    - 369
    - 370        Other Parameters
    - 371        ----------------
    - 372        auth : `typing.Optional[str]`
    - 373            A Bearer access_token to make the request with.
    - 374            This is optional and limited to components that only requires an Authorization token.
    - 375
    - 376        Returns
    - 377        --------
    - 378        `aiobungie.crates.Component`
    - 379            A Destiny 2 player profile with its components.
    - 380            Only passed components will be available if they exists. Otherwise they will be `None`
    - 381
    - 382        Raises
    - 383        ------
    - 384        `aiobungie.MembershipTypeError`
    - 385            The provided membership type was invalid.
    - 386        """
    - 387        data = await self.rest.fetch_profile(member_id, type, components, auth)
    - 388        return self.factory.deserialize_components(data)
    - 389
    - 390    async def fetch_linked_profiles(
    - 391        self,
    - 392        member_id: int,
    - 393        member_type: typedefs.IntAnd[enums.MembershipType],
    - 394        /,
    - 395        *,
    - 396        all: bool = False,
    - 397    ) -> profile.LinkedProfile:
    - 398        """Returns a summary information about all profiles linked to the requested member.
    - 399
    - 400        The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships.
    - 401
    - 402        .. note::
    - 403            It will only return linked accounts whose linkages you are allowed to view.
    - 404
    - 405        Parameters
    - 406        ----------
    - 407        member_id : `int`
    - 408            The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID.
    - 409        member_type : `aiobungie.MembershipType`
    - 410            The type for the membership whose linked Destiny account you want to return.
    - 411
    - 412        Other Parameters
    - 413        ----------------
    - 414        all : `bool`
    - 415            If provided and set to `True`, All memberships regardless
    - 416            of whether they're obscured by overrides will be returned,
    - 417
    - 418            If provided and set to `False`, Only available memberships will be returned.
    - 419            The default for this is `False`.
    - 420
    - 421        Returns
    - 422        -------
    - 423        `aiobungie.crates.profile.LinkedProfile`
    - 424            A linked profile object.
    - 425        """
    - 426        resp = await self.rest.fetch_linked_profiles(member_id, member_type, all=all)
    - 427
    - 428        return self.factory.deserialize_linked_profiles(resp)
    - 429
    - 430    async def fetch_player(
    - 431        self,
    - 432        name: str,
    - 433        code: int,
    - 434        /,
    - 435        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
    - 436    ) -> collections.Sequence[user.DestinyMembership]:
    - 437        """Fetch a Destiny 2 player's memberships.
    - 438
    - 439        Parameters
    - 440        -----------
    - 441        name: `str`
    - 442            The unique Bungie player name.
    - 443        code : `int`
    - 444            The unique Bungie display name code.
    - 445        type: `aiobungie.internal.enums.MembershipType`
    - 446            The player's membership type, e,g. XBOX, STEAM, PSN
    - 447
    - 448        Returns
    - 449        --------
    - 450        `collections.Sequence[aiobungie.crates.DestinyMembership]`
    - 451            A sequence of the found Destiny 2 player memberships.
    - 452            An empty sequence will be returned if no one found.
    - 453
    - 454        Raises
    - 455        ------
    - 456        `aiobungie.MembershipTypeError`
    - 457            The provided membership type was invalid.
    - 458        """
    - 459        resp = await self.rest.fetch_player(name, code, type)
    - 460
    - 461        return self.factory.deserialize_destiny_memberships(resp)
    - 462
    - 463    async def fetch_character(
    - 464        self,
    - 465        member_id: int,
    - 466        membership_type: typedefs.IntAnd[enums.MembershipType],
    - 467        character_id: int,
    - 468        components: list[enums.ComponentType],
    - 469        auth: typing.Optional[str] = None,
    - 470    ) -> components.CharacterComponent:
    - 471        """Fetch a Destiny 2 character.
    - 472
    - 473        Parameters
    - 474        ----------
    - 475        member_id: `int`
    - 476            A valid bungie member id.
    - 477        character_id: `int`
    - 478            The Destiny character id to retrieve.
    - 479        membership_type: `aiobungie.internal.enums.MembershipType`
    - 480            The member's membership type.
    - 481        components: `list[aiobungie.ComponentType]`
    - 482            Multiple arguments of character components to collect and return.
    - 483
    - 484        Other Parameters
    - 485        ----------------
    - 486        auth : `typing.Optional[str]`
    - 487            A Bearer access_token to make the request with.
    - 488            This is optional and limited to components that only requires an Authorization token.
    - 489
    - 490        Returns
    - 491        -------
    - 492        `aiobungie.crates.CharacterComponent`
    - 493            A Bungie character component.
    - 494
    - 495        `aiobungie.MembershipTypeError`
    - 496            The provided membership type was invalid.
    - 497        """
    - 498        resp = await self.rest.fetch_character(
    - 499            member_id, membership_type, character_id, components, auth
    - 500        )
    - 501
    - 502        return self.factory.deserialize_character_component(resp)
    - 503
    - 504    async def fetch_unique_weapon_history(
    - 505        self,
    - 506        membership_id: int,
    - 507        character_id: int,
    - 508        membership_type: typedefs.IntAnd[enums.MembershipType],
    - 509    ) -> collections.Sequence[activity.ExtendedWeaponValues]:
    - 510        """Fetch details about unique weapon usage for a character. Includes all exotics.
    - 511
    - 512        Parameters
    - 513        ----------
    - 514        membership_id : `int`
    - 515            The Destiny user membership id.
    - 516        character_id : `int`
    - 517            The character id to retrieve.
    - 518        membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    - 519            The Destiny user's membership type.
    - 520
    - 521        Returns
    - 522        -------
    - 523        `collections.Sequence[aiobungie.crates.ExtendedWeaponValues]`
    - 524            A sequence of the weapon's extended values.
    - 525        """
    - 526        resp = await self._rest.fetch_unique_weapon_history(
    - 527            membership_id, character_id, membership_type
    - 528        )
    - 529
    - 530        return [
    - 531            self._factory.deserialize_extended_weapon_values(weapon)
    - 532            for weapon in resp["weapons"]
    - 533        ]
    - 534
    - 535    # * Destiny 2 Activities.
    - 536
    - 537    async def fetch_activities(
    - 538        self,
    - 539        member_id: int,
    - 540        character_id: int,
    - 541        mode: typedefs.IntAnd[enums.GameMode],
    - 542        *,
    - 543        membership_type: typedefs.IntAnd[
    - 544            enums.MembershipType
    - 545        ] = enums.MembershipType.ALL,
    - 546        page: int = 0,
    - 547        limit: int = 250,
    - 548    ) -> iterators.FlatIterator[activity.Activity]:
    - 549        """Fetch a Destiny 2 activity for the specified character id.
    - 550
    - 551        Parameters
    - 552        ----------
    - 553        member_id: `int`
    - 554            The user id that starts with `4611`.
    - 555        character_id: `int`
    - 556            The id of the character to retrieve the activities for.
    - 557        mode: `aiobungie.typedefs.IntAnd[aiobungie.internal.enums.GameMode]`
    - 558            This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc.
    - 559
    - 560        Other Parameters
    - 561        ----------------
    - 562        membership_type: `aiobungie.internal.enums.MembershipType`
    - 563            The Member ship type, if nothing was passed than it will return all.
    - 564        page: int
    - 565            The page number. Default is `0`
    - 566        limit: int
    - 567            Limit the returned result. Default is `250`.
    - 568
    - 569        Returns
    - 570        -------
    - 571        `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]`
    - 572            An iterator of the player's activities.
    - 573
    - 574        Raises
    - 575        ------
    - 576        `aiobungie.MembershipTypeError`
    - 577            The provided membership type was invalid.
    - 578        """
    - 579        resp = await self.rest.fetch_activities(
    - 580            member_id,
    - 581            character_id,
    - 582            mode,
    - 583            membership_type=membership_type,
    - 584            page=page,
    - 585            limit=limit,
    - 586        )
    - 587
    - 588        return self.factory.deserialize_activities(resp)
    - 589
    - 590    async def fetch_post_activity(self, instance_id: int, /) -> activity.PostActivity:
    - 591        """Fetch a post activity details.
    - 592
    - 593        Parameters
    - 594        ----------
    - 595        instance_id: `int`
    - 596            The activity instance id.
    - 597
    - 598        Returns
    - 599        -------
    - 600        `aiobungie.crates.PostActivity`
    - 601           A post activity object.
    - 602        """
    - 603        resp = await self.rest.fetch_post_activity(instance_id)
    - 604
    - 605        return self.factory.deserialize_post_activity(resp)
    - 606
    - 607    async def fetch_aggregated_activity_stats(
    - 608        self,
    - 609        character_id: int,
    - 610        membership_id: int,
    - 611        membership_type: typedefs.IntAnd[enums.MembershipType],
    - 612    ) -> iterators.FlatIterator[activity.AggregatedActivity]:
    - 613        """Fetch aggregated activity stats for a character.
    - 614
    - 615        Parameters
    - 616        ----------
    - 617        character_id: `int`
    - 618            The id of the character to retrieve the activities for.
    - 619        membership_id: `int`
    - 620            The id of the user that started with `4611`.
    - 621        membership_type: `aiobungie.internal.enums.MembershipType`
    - 622            The Member ship type.
    - 623
    - 624        Returns
    - 625        -------
    - 626        `aiobungie.iterators.FlatIterator[aiobungie.crates.AggregatedActivity]`
    - 627            An iterator of the player's activities.
    - 628
    - 629        Raises
    - 630        ------
    - 631        `aiobungie.MembershipTypeError`
    - 632            The provided membership type was invalid.
    - 633        """
    - 634        resp = await self.rest.fetch_aggregated_activity_stats(
    - 635            character_id, membership_id, membership_type
    - 636        )
    - 637
    - 638        return self.factory.deserialize_aggregated_activities(resp)
    - 639
    - 640    # * Destiny 2 Clans or GroupsV2.
    - 641
    - 642    async def fetch_clan_from_id(
    - 643        self,
    - 644        id: int,
    - 645        /,
    - 646        access_token: typing.Optional[str] = None,
    - 647    ) -> clans.Clan:
    - 648        """Fetch a Bungie Clan by its id.
    - 649
    - 650        Parameters
    - 651        -----------
    - 652        id: `int`
    - 653            The clan id.
    - 654
    - 655        Returns
    - 656        --------
    - 657        `aiobungie.crates.Clan`
    - 658            An Bungie clan.
    - 659
    - 660        Raises
    - 661        ------
    - 662        `aiobungie.NotFound`
    - 663            The clan was not found.
    - 664        """
    - 665        resp = await self.rest.fetch_clan_from_id(id, access_token)
    - 666
    - 667        return self.factory.deserialize_clan(resp)
    - 668
    - 669    async def fetch_clan(
    - 670        self,
    - 671        name: str,
    - 672        /,
    - 673        access_token: typing.Optional[str] = None,
    - 674        *,
    - 675        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    - 676    ) -> clans.Clan:
    - 677        """Fetch a Clan by its name.
    - 678        This method will return the first clan found with given name.
    - 679
    - 680        Parameters
    - 681        ----------
    - 682        name: `str`
    - 683            The clan name
    - 684
    - 685        Other Parameters
    - 686        ----------------
    - 687        access_token : `typing.Optional[str]`
    - 688            An optional access token to make the request with.
    - 689
    - 690            If the token was bound to a member of the clan,
    - 691            This field `aiobungie.crates.Clan.current_user_membership` will be available
    - 692            and will return the membership of the user who made this request.
    - 693        type : `aiobungie.GroupType`
    - 694            The group type, Default is aiobungie.GroupType.CLAN.
    - 695
    - 696        Returns
    - 697        -------
    - 698        `aiobungie.crates.Clan`
    - 699            A Bungie clan.
    - 700
    - 701        Raises
    - 702        ------
    - 703        `aiobungie.NotFound`
    - 704            The clan was not found.
    - 705        """
    - 706        resp = await self.rest.fetch_clan(name, access_token, type=type)
    - 707
    - 708        return self.factory.deserialize_clan(resp)
    - 709
    - 710    async def fetch_clan_conversations(
    - 711        self, clan_id: int, /
    - 712    ) -> collections.Sequence[clans.ClanConversation]:
    - 713        """Fetch the conversations/chat channels of the given clan id.
    - 714
    - 715        Parameters
    - 716        ----------
    - 717        clan_id : `int`
    - 718            The clan id.
    - 719
    - 720        Returns
    - 721        `collections.Sequence[aiobungie.crates.ClanConversation]`
    - 722            A sequence of the clan chat channels.
    - 723        """
    - 724        resp = await self.rest.fetch_clan_conversations(clan_id)
    - 725
    - 726        return self.factory.deserialize_clan_conversations(resp)
    - 727
    - 728    async def fetch_clan_admins(
    - 729        self, clan_id: int, /
    - 730    ) -> iterators.FlatIterator[clans.ClanMember]:
    - 731        """Fetch the clan founder and admins.
    - 732
    - 733        Parameters
    - 734        ----------
    - 735        clan_id : `int`
    - 736            The clan id.
    - 737
    - 738        Returns
    - 739        -------
    - 740        `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]`
    - 741            An iterator over the found clan admins and founder.
    - 742
    - 743        Raises
    - 744        ------
    - 745        `aiobungie.NotFound`
    - 746            The requested clan was not found.
    - 747        """
    - 748        resp = await self.rest.fetch_clan_admins(clan_id)
    - 749
    - 750        return self.factory.deserialize_clan_members(resp)
    - 751
    - 752    async def fetch_groups_for_member(
    - 753        self,
    - 754        member_id: int,
    - 755        member_type: typedefs.IntAnd[enums.MembershipType],
    - 756        /,
    - 757        *,
    - 758        filter: int = 0,
    - 759        group_type: enums.GroupType = enums.GroupType.CLAN,
    - 760    ) -> collections.Sequence[clans.GroupMember]:
    - 761        """Fetch information about the groups that a given member has joined.
    - 762
    - 763        Parameters
    - 764        ----------
    - 765        member_id : `int`
    - 766            The member's id
    - 767        member_type : `aiobungie.MembershipType`
    - 768            The member's membership type.
    - 769
    - 770        Other Parameters
    - 771        ----------------
    - 772        filter : `int`
    - 773            Filter apply to list of joined groups. This Default to `0`
    - 774        group_type : `aiobungie.GroupType`
    - 775            The group's type.
    - 776            This is always set to `aiobungie.GroupType.CLAN` and should not be changed.
    - 777
    - 778        Returns
    - 779        -------
    - 780        `collections.Sequence[aiobungie.crates.GroupMember]`
    - 781            A sequence of joined groups for the fetched member.
    - 782        """
    - 783        resp = await self.rest.fetch_groups_for_member(
    - 784            member_id, member_type, filter=filter, group_type=group_type
    - 785        )
    - 786
    - 787        return [
    - 788            self.factory.deserialize_group_member(group) for group in resp["results"]
    - 789        ]
    - 790
    - 791    async def fetch_potential_groups_for_member(
    - 792        self,
    - 793        member_id: int,
    - 794        member_type: typedefs.IntAnd[enums.MembershipType],
    - 795        /,
    - 796        *,
    - 797        filter: int = 0,
    - 798        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    - 799    ) -> collections.Sequence[clans.GroupMember]:
    - 800        """Fetch the potential groups for a clan member.
    - 801
    - 802        Parameters
    - 803        ----------
    - 804        member_id : `int`
    - 805            The member's id
    - 806        member_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    - 807            The member's membership type.
    - 808
    - 809        Other Parameters
    - 810        ----------------
    - 811        filter : `int`
    - 812            Filter apply to list of joined groups. This Default to `0`
    - 813        group_type : `aiobungie.typedefs.IntAnd[aiobungie.GroupType]`
    - 814            The group's type.
    - 815            This is always set to `aiobungie.GroupType.CLAN` and should not be changed.
    - 816
    - 817        Returns
    - 818        -------
    - 819        `collections.Sequence[aiobungie.crates.GroupMember]`
    - 820            A sequence of joined potential groups for the fetched member.
    - 821        """
    - 822        resp = await self.rest.fetch_potential_groups_for_member(
    - 823            member_id, member_type, filter=filter, group_type=group_type
    - 824        )
    - 825
    - 826        return [
    - 827            self.factory.deserialize_group_member(group) for group in resp["results"]
    - 828        ]
    - 829
    - 830    async def fetch_clan_members(
    - 831        self,
    - 832        clan_id: int,
    - 833        /,
    - 834        *,
    - 835        name: typing.Optional[str] = None,
    - 836        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    - 837    ) -> iterators.FlatIterator[clans.ClanMember]:
    - 838        """Fetch Bungie clan members.
    - 839
    - 840        Parameters
    - 841        ----------
    - 842        clan_id : `int`
    - 843            The clans id
    - 844
    - 845        Other Parameters
    - 846        ----------------
    - 847        name : `typing.Optional[str]`
    - 848            If provided, Only players matching this name will be returned.
    - 849        type : `aiobungie.MembershipType`
    - 850            An optional clan member's membership type.
    - 851            This parameter is used to filter the returned results
    - 852            by the provided membership, For an example XBox memberships only,
    - 853            Otherwise will return all memberships.
    - 854
    - 855        Returns
    - 856        -------
    - 857        `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]`
    - 858            An iterator over the bungie clan members.
    - 859
    - 860        Raises
    - 861        ------
    - 862        `aiobungie.NotFound`
    - 863            The clan was not found.
    - 864        """
    - 865        resp = await self.rest.fetch_clan_members(clan_id, type=type, name=name)
    - 866
    - 867        return self.factory.deserialize_clan_members(resp)
    - 868
    - 869    async def fetch_clan_banners(self) -> collections.Sequence[clans.ClanBanner]:
    - 870        """Fetch the clan banners.
    - 871
    - 872        Returns
    - 873        -------
    - 874        `collections.Sequence[aiobungie.crates.ClanBanner]`
    - 875            A sequence of the clan banners.
    - 876        """
    - 877        resp = await self.rest.fetch_clan_banners()
    - 878
    - 879        return self.factory.deserialize_clan_banners(resp)
    - 880
    - 881    # This method is required to be here since it deserialize the clan.
    - 882    async def kick_clan_member(
    - 883        self,
    - 884        access_token: str,
    - 885        /,
    - 886        group_id: int,
    - 887        membership_id: int,
    - 888        membership_type: typedefs.IntAnd[enums.MembershipType],
    - 889    ) -> clans.Clan:
    - 890        """Kick a member from the clan.
    - 891
    - 892        .. note::
    - 893            This request requires OAuth2: oauth2: `AdminGroups` scope.
    - 894
    - 895        Parameters
    - 896        ----------
    - 897        access_token : `str`
    - 898            The bearer access token associated with the bungie account.
    - 899        group_id: `int`
    - 900            The group id.
    - 901        membership_id : `int`
    - 902            The member id to kick.
    - 903        membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    - 904            The member's membership type.
    - 905
    - 906        Returns
    - 907        -------
    - 908        `aiobungie.crates.clan.Clan`
    - 909            The clan that the member was kicked from.
    - 910        """
    - 911        resp = await self.rest.kick_clan_member(
    - 912            access_token,
    - 913            group_id=group_id,
    - 914            membership_id=membership_id,
    - 915            membership_type=membership_type,
    - 916        )
    - 917
    - 918        return self.factory.deserialize_clan(resp)
    - 919
    - 920    async def fetch_clan_weekly_rewards(self, clan_id: int) -> milestones.Milestone:
    - 921        """Fetch a Bungie clan's weekly reward state.
    - 922
    - 923        Parameters
    - 924        ----------
    - 925        clan_id : `int`
    - 926            The clan's id.
    - 927
    - 928        Returns
    - 929        -------
    - 930        `aiobungie.crates.Milestone`
    - 931            A runtime status of the clan's milestone data.
    - 932        """
    - 933
    - 934        resp = await self.rest.fetch_clan_weekly_rewards(clan_id)
    - 935
    - 936        return self.factory.deserialize_milestone(resp)
    - 937
    - 938    # * Destiny 2 Entities aka Definitions.
    - 939
    - 940    async def fetch_inventory_item(self, hash: int, /) -> entity.InventoryEntity:
    - 941        """Fetch a static inventory item entity given a its hash.
    - 942
    - 943        Parameters
    - 944        ----------
    - 945        hash: `int`
    - 946            Inventory item's hash.
    - 947
    - 948        Returns
    - 949        -------
    - 950        `aiobungie.crates.InventoryEntity`
    - 951            A bungie inventory item.
    - 952        """
    - 953        resp = await self.rest.fetch_inventory_item(hash)
    - 954
    - 955        return self.factory.deserialize_inventory_entity(resp)
    - 956
    - 957    async def fetch_objective_entity(self, hash: int, /) -> entity.ObjectiveEntity:
    - 958        """Fetch a Destiny objective entity given a its hash.
    - 959
    - 960        Parameters
    - 961        ----------
    - 962        hash: `int`
    - 963            objective's hash.
    - 964
    - 965        Returns
    - 966        -------
    - 967        `aiobungie.crates.ObjectiveEntity`
    - 968            An objective entity item.
    - 969        """
    - 970        resp = await self.rest.fetch_objective_entity(hash)
    - 971
    - 972        return self.factory.deserialize_objective_entity(resp)
    - 973
    - 974    async def search_entities(
    - 975        self, name: str, entity_type: str, *, page: int = 0
    - 976    ) -> iterators.FlatIterator[entity.SearchableEntity]:
    - 977        """Search for Destiny2 entities given a name and its type.
    - 978
    - 979        Parameters
    - 980        ----------
    - 981        name : `str`
    - 982            The name of the entity, i.e., Thunderlord, One thousand voices.
    - 983        entity_type : `str`
    - 984            The type of the entity, AKA Definition,
    - 985            For an example `DestinyInventoryItemDefinition` for emblems, weapons, and other inventory items.
    - 986
    - 987        Other Parameters
    - 988        ----------------
    - 989        page : `int`
    - 990            An optional page to return. Default to 0.
    - 991
    - 992        Returns
    - 993        -------
    - 994        `aiobungie.iterators.FlatIterator[aiobungie.crates.SearchableEntity]`
    - 995            An iterator over the found results matching the provided name.
    - 996        """
    - 997        resp = await self.rest.search_entities(name, entity_type, page=page)
    - 998
    - 999        return self.factory.deserialize_inventory_results(resp)
    -1000
    -1001    # Fireteams
    -1002
    -1003    async def fetch_fireteams(
    -1004        self,
    -1005        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    -1006        *,
    -1007        platform: typedefs.IntAnd[
    -1008            fireteams.FireteamPlatform
    -1009        ] = fireteams.FireteamPlatform.ANY,
    -1010        language: typing.Union[
    -1011            fireteams.FireteamLanguage, str
    -1012        ] = fireteams.FireteamLanguage.ALL,
    -1013        date_range: int = 0,
    -1014        page: int = 0,
    -1015        slots_filter: int = 0,
    -1016    ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]:
    -1017        """Fetch public Bungie fireteams with open slots.
    -1018
    -1019        Parameters
    -1020        ----------
    -1021        activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]`
    -1022            The fireteam activity type.
    -1023
    -1024        Other Parameters
    -1025        ----------------
    -1026        platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]`
    -1027            If this is provided. Then the results will be filtered with the given platform.
    -1028            Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms.
    -1029        language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]`
    -1030            A locale language to filter the used language in that fireteam.
    -1031            Defaults to `aiobungie.crates.FireteamLanguage.ALL`
    -1032        date_range : `int`
    -1033            An integer to filter the date range of the returned fireteams. Defaults to `aiobungie.FireteamDate.ALL`.
    -1034        page : `int`
    -1035            The page number. By default its `0` which returns all available activities.
    -1036        slots_filter : `int`
    -1037            Filter the returned fireteams based on available slots. Default is `0`
    -1038
    -1039        Returns
    -1040        -------
    -1041        `typing.Optional[collections.Sequence[fireteams.Fireteam]]`
    -1042            A sequence of `aiobungie.crates.Fireteam` or `None`.
    -1043        """
    -1044
    -1045        resp = await self.rest.fetch_fireteams(
    -1046            activity_type,
    -1047            platform=platform,
    -1048            language=language,
    -1049            date_range=date_range,
    -1050            page=page,
    -1051            slots_filter=slots_filter,
    -1052        )
    -1053
    -1054        return self.factory.deserialize_fireteams(resp)
    -1055
    -1056    async def fetch_avaliable_clan_fireteams(
    -1057        self,
    -1058        access_token: str,
    -1059        group_id: int,
    -1060        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    -1061        *,
    -1062        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    -1063        language: typing.Union[fireteams.FireteamLanguage, str],
    -1064        date_range: int = 0,
    -1065        page: int = 0,
    -1066        public_only: bool = False,
    -1067        slots_filter: int = 0,
    -1068    ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]:
    -1069        """Fetch a clan's fireteams with open slots.
    -1070
    -1071        .. note::
    -1072            This method requires OAuth2: ReadGroups scope.
    -1073
    -1074        Parameters
    -1075        ----------
    -1076        access_token : `str`
    -1077            The bearer access token associated with the bungie account.
    -1078        group_id : `int`
    -1079            The group/clan id of the fireteam.
    -1080        activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]`
    -1081            The fireteam activity type.
    -1082
    -1083        Other Parameters
    -1084        ----------------
    -1085        platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]`
    -1086            If this is provided. Then the results will be filtered with the given platform.
    -1087            Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms.
    -1088        language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]`
    -1089            A locale language to filter the used language in that fireteam.
    -1090            Defaults to `aiobungie.crates.FireteamLanguage.ALL`
    -1091        date_range : `int`
    -1092            An integer to filter the date range of the returned fireteams. Defaults to `0`.
    -1093        page : `int`
    -1094            The page number. By default its `0` which returns all available activities.
    -1095        public_only: `bool`
    -1096            If set to True, Then only public fireteams will be returned.
    -1097        slots_filter : `int`
    -1098            Filter the returned fireteams based on available slots. Default is `0`
    -1099
    -1100        Returns
    -1101        -------
    -1102        `typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]`
    -1103            A sequence of  fireteams found in the clan.
    -1104            `None` will be returned if nothing was found.
    -1105        """
    -1106        resp = await self.rest.fetch_avaliable_clan_fireteams(
    -1107            access_token,
    -1108            group_id,
    -1109            activity_type,
    -1110            platform=platform,
    -1111            language=language,
    -1112            date_range=date_range,
    -1113            page=page,
    -1114            public_only=public_only,
    -1115            slots_filter=slots_filter,
    -1116        )
    -1117
    -1118        return self.factory.deserialize_fireteams(resp)
    -1119
    -1120    async def fetch_clan_fireteam(
    -1121        self, access_token: str, fireteam_id: int, group_id: int
    -1122    ) -> fireteams.AvailableFireteam:
    -1123        """Fetch a specific clan fireteam.
    -1124
    -1125        .. note::
    -1126            This method requires OAuth2: ReadGroups scope.
    -1127
    -1128        Parameters
    -1129        ----------
    -1130        access_token : `str`
    -1131            The bearer access token associated with the bungie account.
    -1132        group_id : `int`
    -1133            The group/clan id to fetch the fireteam from.
    -1134        fireteam_id : `int`
    -1135            The fireteam id to fetch.
    -1136
    -1137        Returns
    -1138        -------
    -1139        `typing.Optional[aiobungie.crates.AvailableFireteam]`
    -1140            A sequence of available fireteams objects if exists. else `None` will be returned.
    -1141        """
    -1142        resp = await self.rest.fetch_clan_fireteam(access_token, fireteam_id, group_id)
    -1143
    -1144        return self.factory.deserialize_available_fireteams(
    -1145            resp, no_results=True
    -1146        )  # type: ignore[return-value]
    -1147
    -1148    async def fetch_my_clan_fireteams(
    -1149        self,
    -1150        access_token: str,
    -1151        group_id: int,
    -1152        *,
    -1153        include_closed: bool = True,
    -1154        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    -1155        language: typing.Union[fireteams.FireteamLanguage, str],
    -1156        filtered: bool = True,
    -1157        page: int = 0,
    -1158    ) -> collections.Sequence[fireteams.AvailableFireteam]:
    -1159        """A method that's similar to `fetch_fireteams` but requires OAuth2.
    -1160
    -1161        .. note::
    -1162            This method requires OAuth2: ReadGroups scope.
    -1163
    -1164        Parameters
    -1165        ----------
    -1166        access_token : str
    -1167            The bearer access token associated with the bungie account.
    -1168        group_id : int
    -1169            The group/clan id to fetch.
    -1170
    -1171        Other Parameters
    -1172        ----------------
    -1173        include_closed : bool
    -1174            If provided and set to True, It will also return closed fireteams.
    -1175            If provided and set to False, It will only return public fireteams. Default is True.
    -1176        platform : aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]
    -1177            If this is provided. Then the results will be filtered with the given platform.
    -1178            Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
    -1179        language : typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]
    -1180            A locale language to filter the used language in that fireteam.
    -1181            Defaults to aiobungie.crates.FireteamLanguage.ALL
    -1182        filtered : bool
    -1183            If set to True, it will filter by clan. Otherwise not. Default is True.
    -1184        page : int
    -1185            The page number. By default its 0 which returns all available activities.
    -1186
    -1187        Returns
    -1188        -------
    -1189        `collections.Sequence[aiobungie.crates.AvailableFireteam]`
    -1190            A sequence of available fireteams objects if exists. else `None` will be returned.
    -1191        """
    -1192        resp = await self.rest.fetch_my_clan_fireteams(
    -1193            access_token,
    -1194            group_id,
    -1195            include_closed=include_closed,
    -1196            platform=platform,
    -1197            language=language,
    -1198            filtered=filtered,
    -1199            page=page,
    -1200        )
    -1201
    -1202        return self.factory.deserialize_available_fireteams(resp)  # type: ignore[return-value]
    -1203
    -1204    # Friends and social.
    -1205
    -1206    async def fetch_friends(
    -1207        self, access_token: str, /
    -1208    ) -> collections.Sequence[friends.Friend]:
    -1209        """Fetch bungie friend list.
    -1210
    -1211        .. note::
    -1212            This requests OAuth2: ReadUserData scope.
    -1213
    -1214        Parameters
    -1215        -----------
    -1216        access_token : `str`
    -1217            The bearer access token associated with the bungie account.
    -1218
    -1219        Returns
    -1220        -------
    -1221        `collections.Sequence[aiobungie.crates.Friend]`
    -1222            A sequence of the friends associated with that access token.
    -1223        """
    -1224
    -1225        resp = await self.rest.fetch_friends(access_token)
    -1226
    -1227        return self.factory.deserialize_friends(resp)
    -1228
    -1229    async def fetch_friend_requests(
    -1230        self, access_token: str, /
    -1231    ) -> friends.FriendRequestView:
    -1232        """Fetch pending bungie friend requests queue.
    -1233
    -1234        .. note::
    -1235            This requests OAuth2: ReadUserData scope.
    -1236
    -1237        Parameters
    -1238        -----------
    -1239        access_token : `str`
    -1240            The bearer access token associated with the bungie account.
    -1241
    -1242        Returns
    -1243        -------
    -1244        `aiobungie.crates.FriendRequestView`
    -1245            A friend requests view of that associated access token.
    -1246        """
    -1247
    -1248        resp = await self.rest.fetch_friend_requests(access_token)
    -1249
    -1250        return self.factory.deserialize_friend_requests(resp)
    -1251
    -1252    # Applications and Developer portal.
    -1253
    -1254    async def fetch_application(self, appid: int, /) -> application.Application:
    -1255        """Fetch a Bungie application.
    -1256
    -1257        Parameters
    -1258        -----------
    -1259        appid: `int`
    -1260            The application id.
    -1261
    -1262        Returns
    -1263        --------
    -1264        `aiobungie.crates.Application`
    -1265            A Bungie application.
    -1266        """
    -1267        resp = await self.rest.fetch_application(appid)
    -1268
    -1269        return self.factory.deserialize_app(resp)
    -1270
    -1271    # Milestones
    -1272
    -1273    async def fetch_public_milestone_content(
    -1274        self, milestone_hash: int, /
    -1275    ) -> milestones.MilestoneContent:
    -1276        """Fetch the milestone content given its hash.
    -1277
    -1278        Parameters
    -1279        ----------
    -1280        milestone_hash : `int`
    -1281            The milestone hash.
    -1282
    -1283        Returns
    -1284        -------
    -1285        `aiobungie.crates.milestones.MilestoneContent`
    -1286            A milestone content object.
    -1287        """
    -1288        resp = await self.rest.fetch_public_milestone_content(milestone_hash)
    -1289
    -1290        return self.factory.deserialize_public_milestone_content(resp)
    -
    - - -

    Standard Bungie API client application.

    - -

    This client deserialize the REST JSON responses using aiobungie.Factory -and returns aiobungie.crates Python object implementations of the responses.

    - -

    A aiobungie.RESTClient REST client can also be used alone for low-level concepts.

    - -
    Example
    - -
    import aiobungie
    -
    -client = aiobungie.Client('...')
    -
    -async def main():
    -    async with client.rest:
    -        user = await client.fetch_current_user_memberships('...')
    -        print(user)
    -
    - -
    Parameters
    - -
      -
    • token (str): -Your Bungie's API key or Token from the developer's portal.
    • -
    - -
    Other Parameters
    - -
      -
    • rest_client (aiobungie.interfaces.RESTInterface | None): -An optional rest client instance you can pass. -If set to None then the client will use the default instance.
    • -
    • max_retries (int): -The max retries number to retry if the request hit a 5xx status code.
    • -
    • max_ratelimit_retries (int): -The max retries number to retry if the request hit a 429 status code. Defaults to 3.
    • -
    • client_secret (str | None): -An optional application client secret, -This is only needed if you're fetching OAuth2 tokens with this client.
    • -
    • client_id (int | None): -An optional application client id, -This is only needed if you're fetching OAuth2 tokens with this client.
    • -
    -
    - - -
    - -
    - - Client( token: str, /, client_secret: Optional[str] = None, client_id: Optional[int] = None, *, rest_client: Optional[aiobungie.interfaces.rest.RESTInterface] = None, max_retries: int = 4, max_ratelimit_retries: int = 3) - - - -
    - -
    107    def __init__(
    -108        self,
    -109        token: str,
    -110        /,
    -111        client_secret: typing.Optional[str] = None,
    -112        client_id: typing.Optional[int] = None,
    -113        *,
    -114        rest_client: typing.Optional[interfaces.RESTInterface] = None,
    -115        max_retries: int = 4,
    -116        max_ratelimit_retries: int = 3,
    -117    ) -> None:
    -118
    -119        self._client_secret = client_secret
    -120        self._client_id = client_id
    -121
    -122        self._rest = (
    -123            rest_client
    -124            if rest_client is not None
    -125            else rest_.RESTClient(
    -126                token,
    -127                client_secret,
    -128                client_id,
    -129                max_retries=max_retries,
    -130                max_ratelimit_retries=max_ratelimit_retries,
    -131            )
    -132        )
    -133
    -134        self._factory = factory_.Factory(self)
    -
    - - - - -
    -
    -
    - factory: aiobungie.Factory - - -
    - - -

    Returns the marshalling factory for the client.

    -
    - - -
    -
    -
    - rest: aiobungie.interfaces.rest.RESTInterface - - -
    - - -

    Returns the REST client for the this client.

    -
    - - -
    -
    -
    - request: aiobungie.Client - - -
    - - -

    A readonly ClientApp instance used for external requests.

    -
    - - -
    -
    -
    - metadata: collections.abc.MutableMapping[typing.Any, typing.Any] - - -
    - - -

    A mutable mapping storage for the user's needs.

    -
    - - -
    -
    - -
    - - def - run( self, future: collections.abc.Coroutine[typing.Any, None, None], debug: bool = False) -> None: - - - -
    - -
    152    def run(
    -153        self, future: collections.Coroutine[typing.Any, None, None], debug: bool = False
    -154    ) -> None:
    -155        loop: typing.Final[asyncio.AbstractEventLoop] = helpers.get_or_make_loop()
    -156        try:
    -157            if not loop.is_running():
    -158                loop.set_debug(debug)
    -159                loop.run_until_complete(future)
    -160
    -161        except Exception as exc:
    -162            raise RuntimeError(f"Failed to run {future.__qualname__}") from exc
    -163
    -164        except KeyboardInterrupt:
    -165            _LOG.warn("Unexpected Keyboard interrupt. Exiting.")
    -166            return
    -
    - - -

    Runs a coroutine function until its complete.

    - -

    This is equivalent to asyncio.get_event_loop().run_until_complete(...)

    - -
    Parameters
    - -
      -
    • future (collections.Coroutine[None, None, None]): -A coroutine object.
    • -
    • debug (bool): -Either to enable asyncio debug or not. Disabled by default.
    • -
    - -
    Example
    - -
    async def main() -> None:
    -    await fetch(...)
    -
    -# Run the coroutine.
    -client.run(main())
    -
    -
    - - -
    -
    - -
    - - async def - fetch_current_user_memberships(self, access_token: str, /) -> aiobungie.crates.user.User: - - - -
    - -
    170    async def fetch_current_user_memberships(self, access_token: str, /) -> user.User:
    -171        """Fetch and return a user object of the bungie net user associated with account.
    -172
    -173        .. warning::
    -174            This method requires OAuth2 scope and a Bearer access token.
    -175
    -176        Parameters
    -177        ----------
    -178        access_token : `str`
    -179            A valid Bearer access token for the authorization.
    -180
    -181        Returns
    -182        -------
    -183        `aiobungie.crates.user.User`
    -184            A user object includes the Destiny memberships and Bungie.net user.
    -185        """
    -186        resp = await self.rest.fetch_current_user_memberships(access_token)
    -187
    -188        return self.factory.deserialize_user(resp)
    -
    - - -

    Fetch and return a user object of the bungie net user associated with account.

    - -
    - -

    This method requires OAuth2 scope and a Bearer access token.

    - -
    - -
    Parameters
    - -
      -
    • access_token (str): -A valid Bearer access token for the authorization.
    • -
    - -
    Returns
    - -
      -
    • aiobungie.crates.user.User: A user object includes the Destiny memberships and Bungie.net user.
    • -
    -
    - - -
    -
    - -
    - - async def - fetch_bungie_user(self, id: int, /) -> aiobungie.crates.user.BungieUser: - - - -
    - -
    190    async def fetch_bungie_user(self, id: int, /) -> user.BungieUser:
    -191        """Fetch a Bungie user by their BungieNet id.
    -192
    -193        .. note::
    -194            This returns a Bungie user membership only. Take a look at `Client.fetch_membership_from_id`
    -195            for other memberships.
    -196
    -197        Parameters
    -198        ----------
    -199        id: `int`
    -200            The user id.
    -201
    -202        Returns
    -203        -------
    -204        `aiobungie.crates.user.BungieUser`
    -205            A Bungie user.
    -206
    -207        Raises
    -208        ------
    -209        `aiobungie.error.NotFound`
    -210            The user was not found.
    -211        """
    -212        payload = await self.rest.fetch_bungie_user(id)
    -213
    -214        return self.factory.deserialize_bungie_user(payload)
    -
    - - -

    Fetch a Bungie user by their BungieNet id.

    - -
    - -

    This returns a Bungie user membership only. Take a look at Client.fetch_membership_from_id -for other memberships.

    - -
    - -
    Parameters
    - -
      -
    • id (int): -The user id.
    • -
    - -
    Returns
    - -
      -
    • aiobungie.crates.user.BungieUser: A Bungie user.
    • -
    - -
    Raises
    - - -
    - - -
    -
    - -
    - - async def - search_users( self, name: str, /) -> aiobungie.FlatIterator[aiobungie.crates.user.SearchableDestinyUser]: - - - -
    - -
    216    async def search_users(
    -217        self, name: str, /
    -218    ) -> iterators.FlatIterator[user.SearchableDestinyUser]:
    -219        """Search for players and return all players that matches the same name.
    -220
    -221        Parameters
    -222        ----------
    -223        name : `buildins.str`
    -224            The user name.
    -225
    -226        Returns
    -227        -------
    -228        `aiobungie.iterators.FlatIterator[aiobungie.crates.DestinyMembership]`
    -229            A sequence of destiny memberships.
    -230        """
    -231        payload = await self.rest.search_users(name)
    -232
    -233        return iterators.FlatIterator(
    -234            [
    -235                self.factory.deserialize_searched_user(user)
    -236                for user in payload["searchResults"]
    -237            ]
    -238        )
    -
    - - -

    Search for players and return all players that matches the same name.

    - -
    Parameters
    - -
      -
    • name (buildins.str): -The user name.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_user_themes(self) -> collections.abc.Sequence[aiobungie.crates.user.UserThemes]: - - - -
    - -
    240    async def fetch_user_themes(self) -> collections.Sequence[user.UserThemes]:
    -241        """Fetch all available user themes.
    -242
    -243        Returns
    -244        -------
    -245        `collections.Sequence[aiobungie.crates.user.UserThemes]`
    -246            A sequence of user themes.
    -247        """
    -248        data = await self.rest.fetch_user_themes()
    -249
    -250        return self.factory.deserialize_user_themes(data)
    -
    - - -

    Fetch all available user themes.

    - -
    Returns
    - -
      -
    • collections.Sequence[aiobungie.crates.user.UserThemes]: A sequence of user themes.
    • -
    -
    - - -
    -
    - -
    - - async def - fetch_hard_types( self, credential: int, type: Union[int, aiobungie.CredentialType] = <CredentialType.STEAMID: 12>, /) -> aiobungie.crates.user.HardLinkedMembership: - - - -
    - -
    252    async def fetch_hard_types(
    -253        self,
    -254        credential: int,
    -255        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
    -256        /,
    -257    ) -> user.HardLinkedMembership:
    -258        """Gets any hard linked membership given a credential.
    -259        Only works for credentials that are public just `aiobungie.CredentialType.STEAMID` right now.
    -260        Cross Save aware.
    -261
    -262        Parameters
    -263        ----------
    -264        credential: `int`
    -265            A valid SteamID64
    -266        type: `aiobungie.CredentialType`
    -267            The credential type. This must not be changed
    -268            Since its only credential that works "currently"
    -269
    -270        Returns
    -271        -------
    -272        `aiobungie.crates.user.HardLinkedMembership`
    -273            Information about the hard linked data.
    -274        """
    -275
    -276        payload = await self.rest.fetch_hardlinked_credentials(credential, type)
    -277
    -278        return user.HardLinkedMembership(
    -279            id=int(payload["membershipId"]),
    -280            type=enums.MembershipType(payload["membershipType"]),
    -281            cross_save_type=enums.MembershipType(payload["CrossSaveOverriddenType"]),
    -282        )
    -
    - - -

    Gets any hard linked membership given a credential. -Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now. -Cross Save aware.

    - -
    Parameters
    - -
      -
    • credential (int): -A valid SteamID64
    • -
    • type (aiobungie.CredentialType): -The credential type. This must not be changed -Since its only credential that works "currently"
    • -
    - -
    Returns
    - -
      -
    • aiobungie.crates.user.HardLinkedMembership: Information about the hard linked data.
    • -
    -
    - - -
    -
    - -
    - - async def - fetch_membership_from_id( self, id: int, /, type: Union[int, aiobungie.MembershipType] = <MembershipType.NONE: 0>) -> aiobungie.crates.user.User: - - - -
    - -
    284    async def fetch_membership_from_id(
    -285        self,
    -286        id: int,
    -287        /,
    -288        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    -289    ) -> user.User:
    -290        """Fetch Bungie user's memberships from their id.
    -291
    -292        Notes
    -293        -----
    -294        * This returns both BungieNet membership and a sequence of the player's DestinyMemberships
    -295        Which includes Stadia, Xbox, Steam and PSN memberships if the player has them,
    -296        see `aiobungie.crates.user.DestinyMembership` for more details.
    -297        * If you only want the bungie user. Consider using `Client.fetch_user` method.
    -298
    -299        Parameters
    -300        ----------
    -301        id : `int`
    -302            The user's id.
    -303        type : `aiobungie.MembershipType`
    -304            The user's membership type.
    -305
    -306        Returns
    -307        -------
    -308        `aiobungie.crates.User`
    -309            A Bungie user with their membership types.
    -310
    -311        Raises
    -312        ------
    -313        aiobungie.NotFound
    -314            The requested user was not found.
    -315        """
    -316        payload = await self.rest.fetch_membership_from_id(id, type)
    -317
    -318        return self.factory.deserialize_user(payload)
    -
    - - -

    Fetch Bungie user's memberships from their id.

    - -
    Notes
    - -
      -
    • This returns both BungieNet membership and a sequence of the player's DestinyMemberships -Which includes Stadia, Xbox, Steam and PSN memberships if the player has them, -see aiobungie.crates.user.DestinyMembership for more details.
    • -
    • If you only want the bungie user. Consider using Client.fetch_user method.
    • -
    - -
    Parameters
    - - - -
    Returns
    - - - -
    Raises
    - - -
    - - -
    -
    - -
    - - async def - fetch_user_credentials( self, access_token: str, membership_id: int, /) -> collections.abc.Sequence[aiobungie.crates.user.UserCredentials]: - - - -
    - -
    320    async def fetch_user_credentials(
    -321        self, access_token: str, membership_id: int, /
    -322    ) -> collections.Sequence[user.UserCredentials]:
    -323        """Fetch an array of credential types attached to the requested account.
    -324
    -325        .. note::
    -326            This method require OAuth2 Bearer access token.
    -327
    -328        Parameters
    -329        ----------
    -330        access_token : `str`
    -331            The bearer access token associated with the bungie account.
    -332        membership_id : `int`
    -333            The id of the membership to return.
    -334
    -335        Returns
    -336        -------
    -337        `collections.Sequence[aiobungie.crates.UserCredentials]`
    -338            A sequence of the attached user credentials.
    -339
    -340        Raises
    -341        ------
    -342        `aiobungie.Unauthorized`
    -343            The access token was wrong or no access token passed.
    -344        """
    -345        resp = await self.rest.fetch_user_credentials(access_token, membership_id)
    -346
    -347        return self.factory.deserialize_user_credentials(resp)
    -
    - - -

    Fetch an array of credential types attached to the requested account.

    - -
    - -

    This method require OAuth2 Bearer access token.

    - -
    - -
    Parameters
    - -
      -
    • access_token (str): -The bearer access token associated with the bungie account.
    • -
    • membership_id (int): -The id of the membership to return.
    • -
    - -
    Returns
    - - - -
    Raises
    - - -
    - - -
    -
    - -
    - - async def - fetch_profile( self, member_id: int, type: Union[int, aiobungie.MembershipType], components: list[aiobungie.ComponentType], auth: Optional[str] = None) -> aiobungie.crates.components.Component: - - - -
    - -
    351    async def fetch_profile(
    -352        self,
    -353        member_id: int,
    -354        type: typedefs.IntAnd[enums.MembershipType],
    -355        components: list[enums.ComponentType],
    -356        auth: typing.Optional[str] = None,
    -357    ) -> components.Component:
    -358        """
    -359        Fetch a bungie profile passing components to the request.
    -360
    -361        Parameters
    -362        ----------
    -363        member_id: `int`
    -364            The member's id.
    -365        type: `aiobungie.MembershipType`
    -366            A valid membership type.
    -367        components : `list[aiobungie.ComponentType]`
    -368            List of profile components to collect and return.
    -369
    -370        Other Parameters
    -371        ----------------
    -372        auth : `typing.Optional[str]`
    -373            A Bearer access_token to make the request with.
    -374            This is optional and limited to components that only requires an Authorization token.
    -375
    -376        Returns
    -377        --------
    -378        `aiobungie.crates.Component`
    -379            A Destiny 2 player profile with its components.
    -380            Only passed components will be available if they exists. Otherwise they will be `None`
    -381
    -382        Raises
    -383        ------
    -384        `aiobungie.MembershipTypeError`
    -385            The provided membership type was invalid.
    -386        """
    -387        data = await self.rest.fetch_profile(member_id, type, components, auth)
    -388        return self.factory.deserialize_components(data)
    -
    - - -

    Fetch a bungie profile passing components to the request.

    - -
    Parameters
    - - - -
    Other Parameters
    - -
      -
    • auth (typing.Optional[str]): -A Bearer access_token to make the request with. -This is optional and limited to components that only requires an Authorization token.
    • -
    - -
    Returns
    - -
      -
    • aiobungie.crates.Component: A Destiny 2 player profile with its components. -Only passed components will be available if they exists. Otherwise they will be None
    • -
    - -
    Raises
    - - -
    - - -
    -
    - -
    - - async def - fetch_linked_profiles( self, member_id: int, member_type: Union[int, aiobungie.MembershipType], /, *, all: bool = False) -> aiobungie.crates.profile.LinkedProfile: - - - -
    - -
    390    async def fetch_linked_profiles(
    -391        self,
    -392        member_id: int,
    -393        member_type: typedefs.IntAnd[enums.MembershipType],
    -394        /,
    -395        *,
    -396        all: bool = False,
    -397    ) -> profile.LinkedProfile:
    -398        """Returns a summary information about all profiles linked to the requested member.
    -399
    -400        The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships.
    -401
    -402        .. note::
    -403            It will only return linked accounts whose linkages you are allowed to view.
    -404
    -405        Parameters
    -406        ----------
    -407        member_id : `int`
    -408            The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID.
    -409        member_type : `aiobungie.MembershipType`
    -410            The type for the membership whose linked Destiny account you want to return.
    -411
    -412        Other Parameters
    -413        ----------------
    -414        all : `bool`
    -415            If provided and set to `True`, All memberships regardless
    -416            of whether they're obscured by overrides will be returned,
    -417
    -418            If provided and set to `False`, Only available memberships will be returned.
    -419            The default for this is `False`.
    -420
    -421        Returns
    -422        -------
    -423        `aiobungie.crates.profile.LinkedProfile`
    -424            A linked profile object.
    -425        """
    -426        resp = await self.rest.fetch_linked_profiles(member_id, member_type, all=all)
    -427
    -428        return self.factory.deserialize_linked_profiles(resp)
    -
    - - -

    Returns a summary information about all profiles linked to the requested member.

    - -

    The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships.

    - -
    - -

    It will only return linked accounts whose linkages you are allowed to view.

    - -
    - -
    Parameters
    - -
      -
    • member_id (int): -The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID.
    • -
    • member_type (aiobungie.MembershipType): -The type for the membership whose linked Destiny account you want to return.
    • -
    - -
    Other Parameters
    - -
      -
    • all (bool): -If provided and set to True, All memberships regardless -of whether they're obscured by overrides will be returned,

      - -

      If provided and set to False, Only available memberships will be returned. -The default for this is False.

    • -
    - -
    Returns
    - -
      -
    • aiobungie.crates.profile.LinkedProfile: A linked profile object.
    • -
    -
    - - -
    -
    - -
    - - async def - fetch_player( self, name: str, code: int, /, type: Union[int, aiobungie.MembershipType] = <MembershipType.ALL: -1>) -> collections.abc.Sequence[aiobungie.crates.user.DestinyMembership]: - - - -
    - -
    430    async def fetch_player(
    -431        self,
    -432        name: str,
    -433        code: int,
    -434        /,
    -435        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
    -436    ) -> collections.Sequence[user.DestinyMembership]:
    -437        """Fetch a Destiny 2 player's memberships.
    -438
    -439        Parameters
    -440        -----------
    -441        name: `str`
    -442            The unique Bungie player name.
    -443        code : `int`
    -444            The unique Bungie display name code.
    -445        type: `aiobungie.internal.enums.MembershipType`
    -446            The player's membership type, e,g. XBOX, STEAM, PSN
    -447
    -448        Returns
    -449        --------
    -450        `collections.Sequence[aiobungie.crates.DestinyMembership]`
    -451            A sequence of the found Destiny 2 player memberships.
    -452            An empty sequence will be returned if no one found.
    -453
    -454        Raises
    -455        ------
    -456        `aiobungie.MembershipTypeError`
    -457            The provided membership type was invalid.
    -458        """
    -459        resp = await self.rest.fetch_player(name, code, type)
    -460
    -461        return self.factory.deserialize_destiny_memberships(resp)
    -
    - - -

    Fetch a Destiny 2 player's memberships.

    - -
    Parameters
    - -
      -
    • name (str): -The unique Bungie player name.
    • -
    • code (int): -The unique Bungie display name code.
    • -
    • type (aiobungie.MembershipType): -The player's membership type, e,g. XBOX, STEAM, PSN
    • -
    - -
    Returns
    - - - -
    Raises
    - - -
    - - -
    -
    - -
    - - async def - fetch_character( self, member_id: int, membership_type: Union[int, aiobungie.MembershipType], character_id: int, components: list[aiobungie.ComponentType], auth: Optional[str] = None) -> aiobungie.crates.components.CharacterComponent: - - - -
    - -
    463    async def fetch_character(
    -464        self,
    -465        member_id: int,
    -466        membership_type: typedefs.IntAnd[enums.MembershipType],
    -467        character_id: int,
    -468        components: list[enums.ComponentType],
    -469        auth: typing.Optional[str] = None,
    -470    ) -> components.CharacterComponent:
    -471        """Fetch a Destiny 2 character.
    -472
    -473        Parameters
    -474        ----------
    -475        member_id: `int`
    -476            A valid bungie member id.
    -477        character_id: `int`
    -478            The Destiny character id to retrieve.
    -479        membership_type: `aiobungie.internal.enums.MembershipType`
    -480            The member's membership type.
    -481        components: `list[aiobungie.ComponentType]`
    -482            Multiple arguments of character components to collect and return.
    -483
    -484        Other Parameters
    -485        ----------------
    -486        auth : `typing.Optional[str]`
    -487            A Bearer access_token to make the request with.
    -488            This is optional and limited to components that only requires an Authorization token.
    -489
    -490        Returns
    -491        -------
    -492        `aiobungie.crates.CharacterComponent`
    -493            A Bungie character component.
    -494
    -495        `aiobungie.MembershipTypeError`
    -496            The provided membership type was invalid.
    -497        """
    -498        resp = await self.rest.fetch_character(
    -499            member_id, membership_type, character_id, components, auth
    -500        )
    -501
    -502        return self.factory.deserialize_character_component(resp)
    -
    - - -

    Fetch a Destiny 2 character.

    - -
    Parameters
    - -
      -
    • member_id (int): -A valid bungie member id.
    • -
    • character_id (int): -The Destiny character id to retrieve.
    • -
    • membership_type (aiobungie.MembershipType): -The member's membership type.
    • -
    • components (list[aiobungie.ComponentType]): -Multiple arguments of character components to collect and return.
    • -
    - -
    Other Parameters
    - -
      -
    • auth (typing.Optional[str]): -A Bearer access_token to make the request with. -This is optional and limited to components that only requires an Authorization token.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_unique_weapon_history( self, membership_id: int, character_id: int, membership_type: Union[int, aiobungie.MembershipType]) -> collections.abc.Sequence[aiobungie.crates.activity.ExtendedWeaponValues]: - - - -
    - -
    504    async def fetch_unique_weapon_history(
    -505        self,
    -506        membership_id: int,
    -507        character_id: int,
    -508        membership_type: typedefs.IntAnd[enums.MembershipType],
    -509    ) -> collections.Sequence[activity.ExtendedWeaponValues]:
    -510        """Fetch details about unique weapon usage for a character. Includes all exotics.
    -511
    -512        Parameters
    -513        ----------
    -514        membership_id : `int`
    -515            The Destiny user membership id.
    -516        character_id : `int`
    -517            The character id to retrieve.
    -518        membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    -519            The Destiny user's membership type.
    -520
    -521        Returns
    -522        -------
    -523        `collections.Sequence[aiobungie.crates.ExtendedWeaponValues]`
    -524            A sequence of the weapon's extended values.
    -525        """
    -526        resp = await self._rest.fetch_unique_weapon_history(
    -527            membership_id, character_id, membership_type
    -528        )
    -529
    -530        return [
    -531            self._factory.deserialize_extended_weapon_values(weapon)
    -532            for weapon in resp["weapons"]
    -533        ]
    -
    - - -

    Fetch details about unique weapon usage for a character. Includes all exotics.

    - -
    Parameters
    - - - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_activities( self, member_id: int, character_id: int, mode: Union[int, aiobungie.GameMode], *, membership_type: Union[int, aiobungie.MembershipType] = <MembershipType.ALL: -1>, page: int = 0, limit: int = 250) -> aiobungie.FlatIterator[aiobungie.crates.activity.Activity]: - - - -
    - -
    537    async def fetch_activities(
    -538        self,
    -539        member_id: int,
    -540        character_id: int,
    -541        mode: typedefs.IntAnd[enums.GameMode],
    -542        *,
    -543        membership_type: typedefs.IntAnd[
    -544            enums.MembershipType
    -545        ] = enums.MembershipType.ALL,
    -546        page: int = 0,
    -547        limit: int = 250,
    -548    ) -> iterators.FlatIterator[activity.Activity]:
    -549        """Fetch a Destiny 2 activity for the specified character id.
    -550
    -551        Parameters
    -552        ----------
    -553        member_id: `int`
    -554            The user id that starts with `4611`.
    -555        character_id: `int`
    -556            The id of the character to retrieve the activities for.
    -557        mode: `aiobungie.typedefs.IntAnd[aiobungie.internal.enums.GameMode]`
    -558            This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc.
    -559
    -560        Other Parameters
    -561        ----------------
    -562        membership_type: `aiobungie.internal.enums.MembershipType`
    -563            The Member ship type, if nothing was passed than it will return all.
    -564        page: int
    -565            The page number. Default is `0`
    -566        limit: int
    -567            Limit the returned result. Default is `250`.
    -568
    -569        Returns
    -570        -------
    -571        `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]`
    -572            An iterator of the player's activities.
    -573
    -574        Raises
    -575        ------
    -576        `aiobungie.MembershipTypeError`
    -577            The provided membership type was invalid.
    -578        """
    -579        resp = await self.rest.fetch_activities(
    -580            member_id,
    -581            character_id,
    -582            mode,
    -583            membership_type=membership_type,
    -584            page=page,
    -585            limit=limit,
    -586        )
    -587
    -588        return self.factory.deserialize_activities(resp)
    -
    - - -

    Fetch a Destiny 2 activity for the specified character id.

    - -
    Parameters
    - -
      -
    • member_id (int): -The user id that starts with 4611.
    • -
    • character_id (int): -The id of the character to retrieve the activities for.
    • -
    • mode (aiobungie.typedefs.IntAnd[aiobungie.GameMode]): -This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc.
    • -
    - -
    Other Parameters
    - -
      -
    • membership_type (aiobungie.MembershipType): -The Member ship type, if nothing was passed than it will return all.
    • -
    • page (int): -The page number. Default is 0
    • -
    • limit (int): -Limit the returned result. Default is 250.
    • -
    - -
    Returns
    - - - -
    Raises
    - - -
    - - -
    -
    - -
    - - async def - fetch_post_activity(self, instance_id: int, /) -> aiobungie.crates.activity.PostActivity: - - - -
    - -
    590    async def fetch_post_activity(self, instance_id: int, /) -> activity.PostActivity:
    -591        """Fetch a post activity details.
    -592
    -593        Parameters
    -594        ----------
    -595        instance_id: `int`
    -596            The activity instance id.
    -597
    -598        Returns
    -599        -------
    -600        `aiobungie.crates.PostActivity`
    -601           A post activity object.
    -602        """
    -603        resp = await self.rest.fetch_post_activity(instance_id)
    -604
    -605        return self.factory.deserialize_post_activity(resp)
    -
    - - -

    Fetch a post activity details.

    - -
    Parameters
    - -
      -
    • instance_id (int): -The activity instance id.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_aggregated_activity_stats( self, character_id: int, membership_id: int, membership_type: Union[int, aiobungie.MembershipType]) -> aiobungie.FlatIterator[aiobungie.crates.activity.AggregatedActivity]: - - - -
    - -
    607    async def fetch_aggregated_activity_stats(
    -608        self,
    -609        character_id: int,
    -610        membership_id: int,
    -611        membership_type: typedefs.IntAnd[enums.MembershipType],
    -612    ) -> iterators.FlatIterator[activity.AggregatedActivity]:
    -613        """Fetch aggregated activity stats for a character.
    -614
    -615        Parameters
    -616        ----------
    -617        character_id: `int`
    -618            The id of the character to retrieve the activities for.
    -619        membership_id: `int`
    -620            The id of the user that started with `4611`.
    -621        membership_type: `aiobungie.internal.enums.MembershipType`
    -622            The Member ship type.
    -623
    -624        Returns
    -625        -------
    -626        `aiobungie.iterators.FlatIterator[aiobungie.crates.AggregatedActivity]`
    -627            An iterator of the player's activities.
    -628
    -629        Raises
    -630        ------
    -631        `aiobungie.MembershipTypeError`
    -632            The provided membership type was invalid.
    -633        """
    -634        resp = await self.rest.fetch_aggregated_activity_stats(
    -635            character_id, membership_id, membership_type
    -636        )
    -637
    -638        return self.factory.deserialize_aggregated_activities(resp)
    -
    - - -

    Fetch aggregated activity stats for a character.

    - -
    Parameters
    - -
      -
    • character_id (int): -The id of the character to retrieve the activities for.
    • -
    • membership_id (int): -The id of the user that started with 4611.
    • -
    • membership_type (aiobungie.MembershipType): -The Member ship type.
    • -
    - -
    Returns
    - - - -
    Raises
    - - -
    - - -
    -
    - -
    - - async def - fetch_clan_from_id( self, id: int, /, access_token: Optional[str] = None) -> aiobungie.crates.clans.Clan: - - - -
    - -
    642    async def fetch_clan_from_id(
    -643        self,
    -644        id: int,
    -645        /,
    -646        access_token: typing.Optional[str] = None,
    -647    ) -> clans.Clan:
    -648        """Fetch a Bungie Clan by its id.
    -649
    -650        Parameters
    -651        -----------
    -652        id: `int`
    -653            The clan id.
    -654
    -655        Returns
    -656        --------
    -657        `aiobungie.crates.Clan`
    -658            An Bungie clan.
    -659
    -660        Raises
    -661        ------
    -662        `aiobungie.NotFound`
    -663            The clan was not found.
    -664        """
    -665        resp = await self.rest.fetch_clan_from_id(id, access_token)
    -666
    -667        return self.factory.deserialize_clan(resp)
    -
    - - -

    Fetch a Bungie Clan by its id.

    - -
    Parameters
    - -
      -
    • id (int): -The clan id.
    • -
    - -
    Returns
    - - - -
    Raises
    - - -
    - - -
    -
    - -
    - - async def - fetch_clan( self, name: str, /, access_token: Optional[str] = None, *, type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> aiobungie.crates.clans.Clan: - - - -
    - -
    669    async def fetch_clan(
    -670        self,
    -671        name: str,
    -672        /,
    -673        access_token: typing.Optional[str] = None,
    -674        *,
    -675        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    -676    ) -> clans.Clan:
    -677        """Fetch a Clan by its name.
    -678        This method will return the first clan found with given name.
    -679
    -680        Parameters
    -681        ----------
    -682        name: `str`
    -683            The clan name
    -684
    -685        Other Parameters
    -686        ----------------
    -687        access_token : `typing.Optional[str]`
    -688            An optional access token to make the request with.
    -689
    -690            If the token was bound to a member of the clan,
    -691            This field `aiobungie.crates.Clan.current_user_membership` will be available
    -692            and will return the membership of the user who made this request.
    -693        type : `aiobungie.GroupType`
    -694            The group type, Default is aiobungie.GroupType.CLAN.
    -695
    -696        Returns
    -697        -------
    -698        `aiobungie.crates.Clan`
    -699            A Bungie clan.
    -700
    -701        Raises
    -702        ------
    -703        `aiobungie.NotFound`
    -704            The clan was not found.
    -705        """
    -706        resp = await self.rest.fetch_clan(name, access_token, type=type)
    -707
    -708        return self.factory.deserialize_clan(resp)
    -
    - - -

    Fetch a Clan by its name. -This method will return the first clan found with given name.

    - -
    Parameters
    - -
      -
    • name (str): -The clan name
    • -
    - -
    Other Parameters
    - - - -
    Returns
    - - - -
    Raises
    - - -
    - - -
    -
    - -
    - - async def - fetch_clan_conversations( self, clan_id: int, /) -> collections.abc.Sequence[aiobungie.crates.clans.ClanConversation]: - - - -
    - -
    710    async def fetch_clan_conversations(
    -711        self, clan_id: int, /
    -712    ) -> collections.Sequence[clans.ClanConversation]:
    -713        """Fetch the conversations/chat channels of the given clan id.
    -714
    -715        Parameters
    -716        ----------
    -717        clan_id : `int`
    -718            The clan id.
    -719
    -720        Returns
    -721        `collections.Sequence[aiobungie.crates.ClanConversation]`
    -722            A sequence of the clan chat channels.
    -723        """
    -724        resp = await self.rest.fetch_clan_conversations(clan_id)
    -725
    -726        return self.factory.deserialize_clan_conversations(resp)
    -
    - - -

    Fetch the conversations/chat channels of the given clan id.

    - -
    Parameters
    - - -
    - - -
    -
    - -
    - - async def - fetch_clan_admins( self, clan_id: int, /) -> aiobungie.FlatIterator[aiobungie.crates.clans.ClanMember]: - - - -
    - -
    728    async def fetch_clan_admins(
    -729        self, clan_id: int, /
    -730    ) -> iterators.FlatIterator[clans.ClanMember]:
    -731        """Fetch the clan founder and admins.
    -732
    -733        Parameters
    -734        ----------
    -735        clan_id : `int`
    -736            The clan id.
    -737
    -738        Returns
    -739        -------
    -740        `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]`
    -741            An iterator over the found clan admins and founder.
    -742
    -743        Raises
    -744        ------
    -745        `aiobungie.NotFound`
    -746            The requested clan was not found.
    -747        """
    -748        resp = await self.rest.fetch_clan_admins(clan_id)
    -749
    -750        return self.factory.deserialize_clan_members(resp)
    -
    - - -

    Fetch the clan founder and admins.

    - -
    Parameters
    - -
      -
    • clan_id (int): -The clan id.
    • -
    - -
    Returns
    - - - -
    Raises
    - - -
    - - -
    -
    - -
    - - async def - fetch_groups_for_member( self, member_id: int, member_type: Union[int, aiobungie.MembershipType], /, *, filter: int = 0, group_type: aiobungie.GroupType = <GroupType.CLAN: 1>) -> collections.abc.Sequence[aiobungie.crates.clans.GroupMember]: - - - -
    - -
    752    async def fetch_groups_for_member(
    -753        self,
    -754        member_id: int,
    -755        member_type: typedefs.IntAnd[enums.MembershipType],
    -756        /,
    -757        *,
    -758        filter: int = 0,
    -759        group_type: enums.GroupType = enums.GroupType.CLAN,
    -760    ) -> collections.Sequence[clans.GroupMember]:
    -761        """Fetch information about the groups that a given member has joined.
    -762
    -763        Parameters
    -764        ----------
    -765        member_id : `int`
    -766            The member's id
    -767        member_type : `aiobungie.MembershipType`
    -768            The member's membership type.
    -769
    -770        Other Parameters
    -771        ----------------
    -772        filter : `int`
    -773            Filter apply to list of joined groups. This Default to `0`
    -774        group_type : `aiobungie.GroupType`
    -775            The group's type.
    -776            This is always set to `aiobungie.GroupType.CLAN` and should not be changed.
    -777
    -778        Returns
    -779        -------
    -780        `collections.Sequence[aiobungie.crates.GroupMember]`
    -781            A sequence of joined groups for the fetched member.
    -782        """
    -783        resp = await self.rest.fetch_groups_for_member(
    -784            member_id, member_type, filter=filter, group_type=group_type
    -785        )
    -786
    -787        return [
    -788            self.factory.deserialize_group_member(group) for group in resp["results"]
    -789        ]
    -
    - - -

    Fetch information about the groups that a given member has joined.

    - -
    Parameters
    - - - -
    Other Parameters
    - - - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_potential_groups_for_member( self, member_id: int, member_type: Union[int, aiobungie.MembershipType], /, *, filter: int = 0, group_type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> collections.abc.Sequence[aiobungie.crates.clans.GroupMember]: - - - -
    - -
    791    async def fetch_potential_groups_for_member(
    -792        self,
    -793        member_id: int,
    -794        member_type: typedefs.IntAnd[enums.MembershipType],
    -795        /,
    -796        *,
    -797        filter: int = 0,
    -798        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    -799    ) -> collections.Sequence[clans.GroupMember]:
    -800        """Fetch the potential groups for a clan member.
    -801
    -802        Parameters
    -803        ----------
    -804        member_id : `int`
    -805            The member's id
    -806        member_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    -807            The member's membership type.
    -808
    -809        Other Parameters
    -810        ----------------
    -811        filter : `int`
    -812            Filter apply to list of joined groups. This Default to `0`
    -813        group_type : `aiobungie.typedefs.IntAnd[aiobungie.GroupType]`
    -814            The group's type.
    -815            This is always set to `aiobungie.GroupType.CLAN` and should not be changed.
    -816
    -817        Returns
    -818        -------
    -819        `collections.Sequence[aiobungie.crates.GroupMember]`
    -820            A sequence of joined potential groups for the fetched member.
    -821        """
    -822        resp = await self.rest.fetch_potential_groups_for_member(
    -823            member_id, member_type, filter=filter, group_type=group_type
    -824        )
    -825
    -826        return [
    -827            self.factory.deserialize_group_member(group) for group in resp["results"]
    -828        ]
    -
    - - -

    Fetch the potential groups for a clan member.

    - -
    Parameters
    - - - -
    Other Parameters
    - - - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_clan_members( self, clan_id: int, /, *, name: Optional[str] = None, type: Union[int, aiobungie.MembershipType] = <MembershipType.NONE: 0>) -> aiobungie.FlatIterator[aiobungie.crates.clans.ClanMember]: - - - -
    - -
    830    async def fetch_clan_members(
    -831        self,
    -832        clan_id: int,
    -833        /,
    -834        *,
    -835        name: typing.Optional[str] = None,
    -836        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    -837    ) -> iterators.FlatIterator[clans.ClanMember]:
    -838        """Fetch Bungie clan members.
    -839
    -840        Parameters
    -841        ----------
    -842        clan_id : `int`
    -843            The clans id
    -844
    -845        Other Parameters
    -846        ----------------
    -847        name : `typing.Optional[str]`
    -848            If provided, Only players matching this name will be returned.
    -849        type : `aiobungie.MembershipType`
    -850            An optional clan member's membership type.
    -851            This parameter is used to filter the returned results
    -852            by the provided membership, For an example XBox memberships only,
    -853            Otherwise will return all memberships.
    -854
    -855        Returns
    -856        -------
    -857        `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]`
    -858            An iterator over the bungie clan members.
    -859
    -860        Raises
    -861        ------
    -862        `aiobungie.NotFound`
    -863            The clan was not found.
    -864        """
    -865        resp = await self.rest.fetch_clan_members(clan_id, type=type, name=name)
    -866
    -867        return self.factory.deserialize_clan_members(resp)
    -
    - - -

    Fetch Bungie clan members.

    - -
    Parameters
    - -
      -
    • clan_id (int): -The clans id
    • -
    - -
    Other Parameters
    - -
      -
    • name (typing.Optional[str]): -If provided, Only players matching this name will be returned.
    • -
    • type (aiobungie.MembershipType): -An optional clan member's membership type. -This parameter is used to filter the returned results -by the provided membership, For an example XBox memberships only, -Otherwise will return all memberships.
    • -
    - -
    Returns
    - - - -
    Raises
    - - -
    - - -
    -
    - -
    - - async def - fetch_clan_banners(self) -> collections.abc.Sequence[aiobungie.crates.clans.ClanBanner]: - - - -
    - -
    869    async def fetch_clan_banners(self) -> collections.Sequence[clans.ClanBanner]:
    -870        """Fetch the clan banners.
    -871
    -872        Returns
    -873        -------
    -874        `collections.Sequence[aiobungie.crates.ClanBanner]`
    -875            A sequence of the clan banners.
    -876        """
    -877        resp = await self.rest.fetch_clan_banners()
    -878
    -879        return self.factory.deserialize_clan_banners(resp)
    -
    - - -

    Fetch the clan banners.

    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - kick_clan_member( self, access_token: str, /, group_id: int, membership_id: int, membership_type: Union[int, aiobungie.MembershipType]) -> aiobungie.crates.clans.Clan: - - - -
    - -
    882    async def kick_clan_member(
    -883        self,
    -884        access_token: str,
    -885        /,
    -886        group_id: int,
    -887        membership_id: int,
    -888        membership_type: typedefs.IntAnd[enums.MembershipType],
    -889    ) -> clans.Clan:
    -890        """Kick a member from the clan.
    -891
    -892        .. note::
    -893            This request requires OAuth2: oauth2: `AdminGroups` scope.
    -894
    -895        Parameters
    -896        ----------
    -897        access_token : `str`
    -898            The bearer access token associated with the bungie account.
    -899        group_id: `int`
    -900            The group id.
    -901        membership_id : `int`
    -902            The member id to kick.
    -903        membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    -904            The member's membership type.
    -905
    -906        Returns
    -907        -------
    -908        `aiobungie.crates.clan.Clan`
    -909            The clan that the member was kicked from.
    -910        """
    -911        resp = await self.rest.kick_clan_member(
    -912            access_token,
    -913            group_id=group_id,
    -914            membership_id=membership_id,
    -915            membership_type=membership_type,
    -916        )
    -917
    -918        return self.factory.deserialize_clan(resp)
    -
    - - -

    Kick a member from the clan.

    - -
    - -

    This request requires OAuth2: oauth2: AdminGroups scope.

    - -
    - -
    Parameters
    - -
      -
    • access_token (str): -The bearer access token associated with the bungie account.
    • -
    • group_id (int): -The group id.
    • -
    • membership_id (int): -The member id to kick.
    • -
    • membership_type (aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): -The member's membership type.
    • -
    - -
    Returns
    - -
      -
    • aiobungie.crates.clan.Clan: The clan that the member was kicked from.
    • -
    -
    - - -
    -
    - -
    - - async def - fetch_clan_weekly_rewards(self, clan_id: int) -> aiobungie.crates.milestones.Milestone: - - - -
    - -
    920    async def fetch_clan_weekly_rewards(self, clan_id: int) -> milestones.Milestone:
    -921        """Fetch a Bungie clan's weekly reward state.
    -922
    -923        Parameters
    -924        ----------
    -925        clan_id : `int`
    -926            The clan's id.
    -927
    -928        Returns
    -929        -------
    -930        `aiobungie.crates.Milestone`
    -931            A runtime status of the clan's milestone data.
    -932        """
    -933
    -934        resp = await self.rest.fetch_clan_weekly_rewards(clan_id)
    -935
    -936        return self.factory.deserialize_milestone(resp)
    -
    - - -

    Fetch a Bungie clan's weekly reward state.

    - -
    Parameters
    - -
      -
    • clan_id (int): -The clan's id.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_inventory_item(self, hash: int, /) -> aiobungie.crates.entity.InventoryEntity: - - - -
    - -
    940    async def fetch_inventory_item(self, hash: int, /) -> entity.InventoryEntity:
    -941        """Fetch a static inventory item entity given a its hash.
    -942
    -943        Parameters
    -944        ----------
    -945        hash: `int`
    -946            Inventory item's hash.
    -947
    -948        Returns
    -949        -------
    -950        `aiobungie.crates.InventoryEntity`
    -951            A bungie inventory item.
    -952        """
    -953        resp = await self.rest.fetch_inventory_item(hash)
    -954
    -955        return self.factory.deserialize_inventory_entity(resp)
    -
    - - -

    Fetch a static inventory item entity given a its hash.

    - -
    Parameters
    - -
      -
    • hash (int): -Inventory item's hash.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_objective_entity(self, hash: int, /) -> aiobungie.crates.entity.ObjectiveEntity: - - - -
    - -
    957    async def fetch_objective_entity(self, hash: int, /) -> entity.ObjectiveEntity:
    -958        """Fetch a Destiny objective entity given a its hash.
    -959
    -960        Parameters
    -961        ----------
    -962        hash: `int`
    -963            objective's hash.
    -964
    -965        Returns
    -966        -------
    -967        `aiobungie.crates.ObjectiveEntity`
    -968            An objective entity item.
    -969        """
    -970        resp = await self.rest.fetch_objective_entity(hash)
    -971
    -972        return self.factory.deserialize_objective_entity(resp)
    -
    - - -

    Fetch a Destiny objective entity given a its hash.

    - -
    Parameters
    - -
      -
    • hash (int): -objective's hash.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - search_entities( self, name: str, entity_type: str, *, page: int = 0) -> aiobungie.FlatIterator[aiobungie.crates.entity.SearchableEntity]: - - - -
    - -
    974    async def search_entities(
    -975        self, name: str, entity_type: str, *, page: int = 0
    -976    ) -> iterators.FlatIterator[entity.SearchableEntity]:
    -977        """Search for Destiny2 entities given a name and its type.
    -978
    -979        Parameters
    -980        ----------
    -981        name : `str`
    -982            The name of the entity, i.e., Thunderlord, One thousand voices.
    -983        entity_type : `str`
    -984            The type of the entity, AKA Definition,
    -985            For an example `DestinyInventoryItemDefinition` for emblems, weapons, and other inventory items.
    -986
    -987        Other Parameters
    -988        ----------------
    -989        page : `int`
    -990            An optional page to return. Default to 0.
    -991
    -992        Returns
    -993        -------
    -994        `aiobungie.iterators.FlatIterator[aiobungie.crates.SearchableEntity]`
    -995            An iterator over the found results matching the provided name.
    -996        """
    -997        resp = await self.rest.search_entities(name, entity_type, page=page)
    -998
    -999        return self.factory.deserialize_inventory_results(resp)
    -
    - - -

    Search for Destiny2 entities given a name and its type.

    - -
    Parameters
    - -
      -
    • name (str): -The name of the entity, i.e., Thunderlord, One thousand voices.
    • -
    • entity_type (str): -The type of the entity, AKA Definition, -For an example DestinyInventoryItemDefinition for emblems, weapons, and other inventory items.
    • -
    - -
    Other Parameters
    - -
      -
    • page (int): -An optional page to return. Default to 0.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_fireteams( self, activity_type: Union[int, aiobungie.FireteamActivity], *, platform: Union[int, aiobungie.FireteamPlatform] = <FireteamPlatform.ANY: 0>, language: Union[aiobungie.FireteamLanguage, str] = <FireteamLanguage.ALL: >, date_range: int = 0, page: int = 0, slots_filter: int = 0) -> Optional[collections.abc.Sequence[aiobungie.crates.fireteams.Fireteam]]: - - - -
    - -
    1003    async def fetch_fireteams(
    -1004        self,
    -1005        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    -1006        *,
    -1007        platform: typedefs.IntAnd[
    -1008            fireteams.FireteamPlatform
    -1009        ] = fireteams.FireteamPlatform.ANY,
    -1010        language: typing.Union[
    -1011            fireteams.FireteamLanguage, str
    -1012        ] = fireteams.FireteamLanguage.ALL,
    -1013        date_range: int = 0,
    -1014        page: int = 0,
    -1015        slots_filter: int = 0,
    -1016    ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]:
    -1017        """Fetch public Bungie fireteams with open slots.
    -1018
    -1019        Parameters
    -1020        ----------
    -1021        activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]`
    -1022            The fireteam activity type.
    -1023
    -1024        Other Parameters
    -1025        ----------------
    -1026        platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]`
    -1027            If this is provided. Then the results will be filtered with the given platform.
    -1028            Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms.
    -1029        language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]`
    -1030            A locale language to filter the used language in that fireteam.
    -1031            Defaults to `aiobungie.crates.FireteamLanguage.ALL`
    -1032        date_range : `int`
    -1033            An integer to filter the date range of the returned fireteams. Defaults to `aiobungie.FireteamDate.ALL`.
    -1034        page : `int`
    -1035            The page number. By default its `0` which returns all available activities.
    -1036        slots_filter : `int`
    -1037            Filter the returned fireteams based on available slots. Default is `0`
    -1038
    -1039        Returns
    -1040        -------
    -1041        `typing.Optional[collections.Sequence[fireteams.Fireteam]]`
    -1042            A sequence of `aiobungie.crates.Fireteam` or `None`.
    -1043        """
    -1044
    -1045        resp = await self.rest.fetch_fireteams(
    -1046            activity_type,
    -1047            platform=platform,
    -1048            language=language,
    -1049            date_range=date_range,
    -1050            page=page,
    -1051            slots_filter=slots_filter,
    -1052        )
    -1053
    -1054        return self.factory.deserialize_fireteams(resp)
    -
    - - -

    Fetch public Bungie fireteams with open slots.

    - -
    Parameters
    - - - -
    Other Parameters
    - -
      -
    • platform (aiobungie.typedefs.IntAnd[aiobungie.FireteamPlatform]): -If this is provided. Then the results will be filtered with the given platform. -Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
    • -
    • language (typing.Union[aiobungie.FireteamLanguage, str]): -A locale language to filter the used language in that fireteam. -Defaults to aiobungie.crates.FireteamLanguage.ALL
    • -
    • date_range (int): -An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
    • -
    • page (int): -The page number. By default its 0 which returns all available activities.
    • -
    • slots_filter (int): -Filter the returned fireteams based on available slots. Default is 0
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_avaliable_clan_fireteams( self, access_token: str, group_id: int, activity_type: Union[int, aiobungie.FireteamActivity], *, platform: Union[int, aiobungie.FireteamPlatform], language: Union[aiobungie.FireteamLanguage, str], date_range: int = 0, page: int = 0, public_only: bool = False, slots_filter: int = 0) -> Optional[collections.abc.Sequence[aiobungie.crates.fireteams.Fireteam]]: - - - -
    - -
    1056    async def fetch_avaliable_clan_fireteams(
    -1057        self,
    -1058        access_token: str,
    -1059        group_id: int,
    -1060        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    -1061        *,
    -1062        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    -1063        language: typing.Union[fireteams.FireteamLanguage, str],
    -1064        date_range: int = 0,
    -1065        page: int = 0,
    -1066        public_only: bool = False,
    -1067        slots_filter: int = 0,
    -1068    ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]:
    -1069        """Fetch a clan's fireteams with open slots.
    -1070
    -1071        .. note::
    -1072            This method requires OAuth2: ReadGroups scope.
    -1073
    -1074        Parameters
    -1075        ----------
    -1076        access_token : `str`
    -1077            The bearer access token associated with the bungie account.
    -1078        group_id : `int`
    -1079            The group/clan id of the fireteam.
    -1080        activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]`
    -1081            The fireteam activity type.
    -1082
    -1083        Other Parameters
    -1084        ----------------
    -1085        platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]`
    -1086            If this is provided. Then the results will be filtered with the given platform.
    -1087            Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms.
    -1088        language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]`
    -1089            A locale language to filter the used language in that fireteam.
    -1090            Defaults to `aiobungie.crates.FireteamLanguage.ALL`
    -1091        date_range : `int`
    -1092            An integer to filter the date range of the returned fireteams. Defaults to `0`.
    -1093        page : `int`
    -1094            The page number. By default its `0` which returns all available activities.
    -1095        public_only: `bool`
    -1096            If set to True, Then only public fireteams will be returned.
    -1097        slots_filter : `int`
    -1098            Filter the returned fireteams based on available slots. Default is `0`
    -1099
    -1100        Returns
    -1101        -------
    -1102        `typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]`
    -1103            A sequence of  fireteams found in the clan.
    -1104            `None` will be returned if nothing was found.
    -1105        """
    -1106        resp = await self.rest.fetch_avaliable_clan_fireteams(
    -1107            access_token,
    -1108            group_id,
    -1109            activity_type,
    -1110            platform=platform,
    -1111            language=language,
    -1112            date_range=date_range,
    -1113            page=page,
    -1114            public_only=public_only,
    -1115            slots_filter=slots_filter,
    -1116        )
    -1117
    -1118        return self.factory.deserialize_fireteams(resp)
    -
    - - -

    Fetch a clan's fireteams with open slots.

    - -
    - -

    This method requires OAuth2: ReadGroups scope.

    - -
    - -
    Parameters
    - -
      -
    • access_token (str): -The bearer access token associated with the bungie account.
    • -
    • group_id (int): -The group/clan id of the fireteam.
    • -
    • activity_type (aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]): -The fireteam activity type.
    • -
    - -
    Other Parameters
    - -
      -
    • platform (aiobungie.typedefs.IntAnd[aiobungie.FireteamPlatform]): -If this is provided. Then the results will be filtered with the given platform. -Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
    • -
    • language (typing.Union[aiobungie.FireteamLanguage, str]): -A locale language to filter the used language in that fireteam. -Defaults to aiobungie.crates.FireteamLanguage.ALL
    • -
    • date_range (int): -An integer to filter the date range of the returned fireteams. Defaults to 0.
    • -
    • page (int): -The page number. By default its 0 which returns all available activities.
    • -
    • public_only (bool): -If set to True, Then only public fireteams will be returned.
    • -
    • slots_filter (int): -Filter the returned fireteams based on available slots. Default is 0
    • -
    - -
    Returns
    - -
      -
    • typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]: A sequence of fireteams found in the clan. -None will be returned if nothing was found.
    • -
    -
    - - -
    -
    - -
    - - async def - fetch_clan_fireteam( self, access_token: str, fireteam_id: int, group_id: int) -> aiobungie.crates.fireteams.AvailableFireteam: - - - -
    - -
    1120    async def fetch_clan_fireteam(
    -1121        self, access_token: str, fireteam_id: int, group_id: int
    -1122    ) -> fireteams.AvailableFireteam:
    -1123        """Fetch a specific clan fireteam.
    -1124
    -1125        .. note::
    -1126            This method requires OAuth2: ReadGroups scope.
    -1127
    -1128        Parameters
    -1129        ----------
    -1130        access_token : `str`
    -1131            The bearer access token associated with the bungie account.
    -1132        group_id : `int`
    -1133            The group/clan id to fetch the fireteam from.
    -1134        fireteam_id : `int`
    -1135            The fireteam id to fetch.
    -1136
    -1137        Returns
    -1138        -------
    -1139        `typing.Optional[aiobungie.crates.AvailableFireteam]`
    -1140            A sequence of available fireteams objects if exists. else `None` will be returned.
    -1141        """
    -1142        resp = await self.rest.fetch_clan_fireteam(access_token, fireteam_id, group_id)
    -1143
    -1144        return self.factory.deserialize_available_fireteams(
    -1145            resp, no_results=True
    -1146        )  # type: ignore[return-value]
    -
    - - -

    Fetch a specific clan fireteam.

    - -
    - -

    This method requires OAuth2: ReadGroups scope.

    - -
    - -
    Parameters
    - -
      -
    • access_token (str): -The bearer access token associated with the bungie account.
    • -
    • group_id (int): -The group/clan id to fetch the fireteam from.
    • -
    • fireteam_id (int): -The fireteam id to fetch.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_my_clan_fireteams( self, access_token: str, group_id: int, *, include_closed: bool = True, platform: Union[int, aiobungie.FireteamPlatform], language: Union[aiobungie.FireteamLanguage, str], filtered: bool = True, page: int = 0) -> collections.abc.Sequence[aiobungie.crates.fireteams.AvailableFireteam]: - - - -
    - -
    1148    async def fetch_my_clan_fireteams(
    -1149        self,
    -1150        access_token: str,
    -1151        group_id: int,
    -1152        *,
    -1153        include_closed: bool = True,
    -1154        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    -1155        language: typing.Union[fireteams.FireteamLanguage, str],
    -1156        filtered: bool = True,
    -1157        page: int = 0,
    -1158    ) -> collections.Sequence[fireteams.AvailableFireteam]:
    -1159        """A method that's similar to `fetch_fireteams` but requires OAuth2.
    -1160
    -1161        .. note::
    -1162            This method requires OAuth2: ReadGroups scope.
    -1163
    -1164        Parameters
    -1165        ----------
    -1166        access_token : str
    -1167            The bearer access token associated with the bungie account.
    -1168        group_id : int
    -1169            The group/clan id to fetch.
    -1170
    -1171        Other Parameters
    -1172        ----------------
    -1173        include_closed : bool
    -1174            If provided and set to True, It will also return closed fireteams.
    -1175            If provided and set to False, It will only return public fireteams. Default is True.
    -1176        platform : aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]
    -1177            If this is provided. Then the results will be filtered with the given platform.
    -1178            Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
    -1179        language : typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]
    -1180            A locale language to filter the used language in that fireteam.
    -1181            Defaults to aiobungie.crates.FireteamLanguage.ALL
    -1182        filtered : bool
    -1183            If set to True, it will filter by clan. Otherwise not. Default is True.
    -1184        page : int
    -1185            The page number. By default its 0 which returns all available activities.
    -1186
    -1187        Returns
    -1188        -------
    -1189        `collections.Sequence[aiobungie.crates.AvailableFireteam]`
    -1190            A sequence of available fireteams objects if exists. else `None` will be returned.
    -1191        """
    -1192        resp = await self.rest.fetch_my_clan_fireteams(
    -1193            access_token,
    -1194            group_id,
    -1195            include_closed=include_closed,
    -1196            platform=platform,
    -1197            language=language,
    -1198            filtered=filtered,
    -1199            page=page,
    -1200        )
    -1201
    -1202        return self.factory.deserialize_available_fireteams(resp)  # type: ignore[return-value]
    -
    - - -

    A method that's similar to fetch_fireteams but requires OAuth2.

    - -
    - -

    This method requires OAuth2: ReadGroups scope.

    - -
    - -
    Parameters
    - -
      -
    • access_token (str): -The bearer access token associated with the bungie account.
    • -
    • group_id (int): -The group/clan id to fetch.
    • -
    - -
    Other Parameters
    - -
      -
    • include_closed (bool): -If provided and set to True, It will also return closed fireteams. -If provided and set to False, It will only return public fireteams. Default is True.
    • -
    • platform (aiobungie.typedefs.IntAnd[aiobungie.FireteamPlatform]): -If this is provided. Then the results will be filtered with the given platform. -Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
    • -
    • language (typing.Union[aiobungie.FireteamLanguage, str]): -A locale language to filter the used language in that fireteam. -Defaults to aiobungie.crates.FireteamLanguage.ALL
    • -
    • filtered (bool): -If set to True, it will filter by clan. Otherwise not. Default is True.
    • -
    • page (int): -The page number. By default its 0 which returns all available activities.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_friends( self, access_token: str, /) -> collections.abc.Sequence[aiobungie.crates.friends.Friend]: - - - -
    - -
    1206    async def fetch_friends(
    -1207        self, access_token: str, /
    -1208    ) -> collections.Sequence[friends.Friend]:
    -1209        """Fetch bungie friend list.
    -1210
    -1211        .. note::
    -1212            This requests OAuth2: ReadUserData scope.
    -1213
    -1214        Parameters
    -1215        -----------
    -1216        access_token : `str`
    -1217            The bearer access token associated with the bungie account.
    -1218
    -1219        Returns
    -1220        -------
    -1221        `collections.Sequence[aiobungie.crates.Friend]`
    -1222            A sequence of the friends associated with that access token.
    -1223        """
    -1224
    -1225        resp = await self.rest.fetch_friends(access_token)
    -1226
    -1227        return self.factory.deserialize_friends(resp)
    -
    - - -

    Fetch bungie friend list.

    - -
    - -

    This requests OAuth2: ReadUserData scope.

    - -
    - -
    Parameters
    - -
      -
    • access_token (str): -The bearer access token associated with the bungie account.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_friend_requests(self, access_token: str, /) -> aiobungie.crates.friends.FriendRequestView: - - - -
    - -
    1229    async def fetch_friend_requests(
    -1230        self, access_token: str, /
    -1231    ) -> friends.FriendRequestView:
    -1232        """Fetch pending bungie friend requests queue.
    -1233
    -1234        .. note::
    -1235            This requests OAuth2: ReadUserData scope.
    -1236
    -1237        Parameters
    -1238        -----------
    -1239        access_token : `str`
    -1240            The bearer access token associated with the bungie account.
    -1241
    -1242        Returns
    -1243        -------
    -1244        `aiobungie.crates.FriendRequestView`
    -1245            A friend requests view of that associated access token.
    -1246        """
    -1247
    -1248        resp = await self.rest.fetch_friend_requests(access_token)
    -1249
    -1250        return self.factory.deserialize_friend_requests(resp)
    -
    - - -

    Fetch pending bungie friend requests queue.

    - -
    - -

    This requests OAuth2: ReadUserData scope.

    - -
    - -
    Parameters
    - -
      -
    • access_token (str): -The bearer access token associated with the bungie account.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_application(self, appid: int, /) -> aiobungie.crates.application.Application: - - - -
    - -
    1254    async def fetch_application(self, appid: int, /) -> application.Application:
    -1255        """Fetch a Bungie application.
    -1256
    -1257        Parameters
    -1258        -----------
    -1259        appid: `int`
    -1260            The application id.
    -1261
    -1262        Returns
    -1263        --------
    -1264        `aiobungie.crates.Application`
    -1265            A Bungie application.
    -1266        """
    -1267        resp = await self.rest.fetch_application(appid)
    -1268
    -1269        return self.factory.deserialize_app(resp)
    -
    - - -

    Fetch a Bungie application.

    - -
    Parameters
    - -
      -
    • appid (int): -The application id.
    • -
    - -
    Returns
    - - -
    - - -
    -
    - -
    - - async def - fetch_public_milestone_content( self, milestone_hash: int, /) -> aiobungie.crates.milestones.MilestoneContent: - - - -
    - -
    1273    async def fetch_public_milestone_content(
    -1274        self, milestone_hash: int, /
    -1275    ) -> milestones.MilestoneContent:
    -1276        """Fetch the milestone content given its hash.
    -1277
    -1278        Parameters
    -1279        ----------
    -1280        milestone_hash : `int`
    -1281            The milestone hash.
    -1282
    -1283        Returns
    -1284        -------
    -1285        `aiobungie.crates.milestones.MilestoneContent`
    -1286            A milestone content object.
    -1287        """
    -1288        resp = await self.rest.fetch_public_milestone_content(milestone_hash)
    -1289
    -1290        return self.factory.deserialize_public_milestone_content(resp)
    -
    - - -

    Fetch the milestone content given its hash.

    - -
    Parameters
    - -
      -
    • milestone_hash (int): -The milestone hash.
    • -
    - -
    Returns
    - -
      -
    • aiobungie.crates.milestones.MilestoneContent: A milestone content object.
    • -
    -
    - - -
    -
    -
    - -
    -
    @typing.final
    - - class - ClosedReasons(aiobungie.Flag): - - - -
    - -
    782@typing.final
    -783class ClosedReasons(Flag):
    -784    """A Flags enumeration representing the reasons why a person can't join this user's fireteam."""
    -785
    -786    NONE = 0
    -787    MATCHMAKING = 1
    -788    LOADING = 2
    -789    SOLO = 4
    -790    """The activity is required to be played solo."""
    -791    INTERNAL_REASONS = 8
    -792    """
    -793    The user can't be joined for one of a variety of internal reasons.
    -794    Basically, the game can't let you join at this time,
    -795    but for reasons that aren't under the control of this user
    -796    """
    -797    DISALLOWED_BY_GAME_STATE = 16
    -798    """The user's current activity/quest/other transitory game state is preventing joining."""
    -799    OFFLINE = 32768
    -800    """The user appears offline."""
    -
    - - -

    A Flags enumeration representing the reasons why a person can't join this user's fireteam.

    -
    - - -
    -
    - NONE = <ClosedReasons.NONE: 0> - - -
    - - - - -
    -
    -
    - MATCHMAKING = <ClosedReasons.MATCHMAKING: 1> - - -
    - - - - -
    -
    -
    - LOADING = <ClosedReasons.LOADING: 2> - - -
    - - - - -
    -
    -
    - SOLO = <ClosedReasons.SOLO: 4> - - -
    - - -

    The activity is required to be played solo.

    -
    - - -
    -
    -
    - INTERNAL_REASONS = <ClosedReasons.INTERNAL_REASONS: 8> - - -
    - - -

    The user can't be joined for one of a variety of internal reasons. -Basically, the game can't let you join at this time, -but for reasons that aren't under the control of this user

    -
    - - -
    -
    -
    - DISALLOWED_BY_GAME_STATE = <ClosedReasons.DISALLOWED_BY_GAME_STATE: 16> - - -
    - - -

    The user's current activity/quest/other transitory game state is preventing joining.

    -
    - - -
    -
    -
    - OFFLINE = <ClosedReasons.OFFLINE: 32768> - - -
    - - -

    The user appears offline.

    -
    - - -
    -
    -
    Inherited Members
    -
    -
    Flag
    -
    name
    -
    value
    - -
    -
    -
    -
    -
    - -
    -
    @typing.final
    - - class - ComponentFields(aiobungie.Enum): - - - -
    - -
    74@typing.final
    -75class ComponentFields(enums.Enum):
    -76    """An enum that provides fields found in a base component response."""
    -77
    -78    PRIVACY = ComponentPrivacy
    -79    DISABLED = False
    -
    - - -

    An enum that provides fields found in a base component response.

    -
    - - -
    -
    - PRIVACY = <ComponentFields.PRIVACY: <enum 'ComponentPrivacy'>> - - -
    - - - - -
    -
    -
    - DISABLED = <ComponentFields.DISABLED: False> - - -
    - - - - -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    - -
    -
    -
    -
    -
    - -
    -
    @typing.final
    - - class - ComponentPrivacy(builtins.int, aiobungie.Enum): - - - -
    - -
    65@typing.final
    -66class ComponentPrivacy(int, enums.Enum):
    -67    """An enum the provides privacy settings for profile components."""
    -68
    -69    NONE = 0
    -70    PUBLIC = 1
    -71    PRIVATE = 2
    -
    - - -

    An enum the provides privacy settings for profile components.

    -
    - - -
    -
    - NONE = <ComponentPrivacy.NONE: 0> - - -
    - - - - -
    -
    -
    - PUBLIC = <ComponentPrivacy.PUBLIC: 1> - - -
    - - - - -
    -
    -
    - PRIVATE = <ComponentPrivacy.PRIVATE: 2> - - -
    - - - - -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    - -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    - -
    -
    -
    -
    -
    - -
    -
    @typing.final
    - - class - ComponentType(aiobungie.Enum): - - - -
    - -
    363@typing.final
    -364class ComponentType(Enum):
    -365    """An Enum for Destiny 2 profile Components."""
    -366
    -367    NONE = 0
    -368
    -369    PROFILE = 100
    -370    PROFILE_INVENTORIES = 102
    -371    PROFILE_CURRENCIES = 103
    -372    PROFILE_PROGRESSION = 104
    -373    ALL_PROFILES = (
    -374        PROFILE,
    -375        PROFILE_INVENTORIES,
    -376        PROFILE_CURRENCIES,
    -377        PROFILE_PROGRESSION,
    -378    )
    -379    """All profile components."""
    -380
    -381    VENDORS = 400
    -382    VENDOR_SALES = 402
    -383    VENDOR_RECEIPTS = 101
    -384    ALL_VENDORS = (VENDORS, VENDOR_RECEIPTS, VENDOR_SALES)
    -385    """All vendor components."""
    -386
    -387    # Items
    -388    ITEM_INSTANCES = 300
    -389    ITEM_OBJECTIVES = 301
    -390    ITEM_PERKS = 302
    -391    ITEM_RENDER_DATA = 303
    -392    ITEM_STATS = 304
    -393    ITEM_SOCKETS = 305
    -394    ITEM_TALENT_GRINDS = 306
    -395    ITEM_PLUG_STATES = 308
    -396    ITEM_PLUG_OBJECTIVES = 309
    -397    ITEM_REUSABLE_PLUGS = 310
    -398
    -399    ALL_ITEMS = (
    -400        ITEM_PLUG_OBJECTIVES,
    -401        ITEM_PLUG_STATES,
    -402        ITEM_SOCKETS,
    -403        ITEM_INSTANCES,
    -404        ITEM_OBJECTIVES,
    -405        ITEM_PERKS,
    -406        ITEM_RENDER_DATA,
    -407        ITEM_STATS,
    -408        ITEM_TALENT_GRINDS,
    -409        ITEM_REUSABLE_PLUGS,
    -410    )
    -411    """All item components."""
    -412
    -413    PLATFORM_SILVER = 105
    -414    KIOSKS = 500
    -415    CURRENCY_LOOKUPS = 600
    -416    PRESENTATION_NODES = 700
    -417    COLLECTIBLES = 800
    -418    RECORDS = 900
    -419    TRANSITORY = 1000
    -420    METRICS = 1100
    -421    INVENTORIES = 102
    -422    STRING_VARIABLES = 1200
    -423    CRAFTABLES = 1300
    -424
    -425    CHARACTERS = 200
    -426    CHARACTER_INVENTORY = 201
    -427    CHARECTER_PROGRESSION = 202
    -428    CHARACTER_RENDER_DATA = 203
    -429    CHARACTER_ACTIVITIES = 204
    -430    CHARACTER_EQUIPMENT = 205
    -431
    -432    ALL_CHARACTERS = (
    -433        CHARACTERS,
    -434        CHARACTER_INVENTORY,
    -435        CHARECTER_PROGRESSION,
    -436        CHARACTER_RENDER_DATA,
    -437        CHARACTER_ACTIVITIES,
    -438        CHARACTER_EQUIPMENT,
    -439        RECORDS,
    -440    )
    -441    """All character components."""
    -442
    -443    ALL = (
    -444        *ALL_PROFILES,  # type: ignore
    -445        *ALL_CHARACTERS,  # type: ignore
    -446        *ALL_VENDORS,  # type: ignore
    -447        *ALL_ITEMS,  # type: ignore
    -448        RECORDS,
    -449        CURRENCY_LOOKUPS,
    -450        PRESENTATION_NODES,
    -451        COLLECTIBLES,
    -452        KIOSKS,
    -453        METRICS,
    -454        PLATFORM_SILVER,
    -455        INVENTORIES,
    -456        STRING_VARIABLES,
    -457        TRANSITORY,
    -458        CRAFTABLES,
    -459    )
    -460    """ALl components included."""
    -
    - - -

    An Enum for Destiny 2 profile Components.

    -
    - - -
    -
    - NONE = <ComponentType.NONE: 0> - - -
    - - - - -
    -
    -
    - PROFILE = <ComponentType.PROFILE: 100> - - -
    - - - - -
    -
    -
    - PROFILE_INVENTORIES = <ComponentType.PROFILE_INVENTORIES: 102> - - -
    - - - - -
    -
    -
    - PROFILE_CURRENCIES = <ComponentType.PROFILE_CURRENCIES: 103> - - -
    - - - - -
    -
    -
    - PROFILE_PROGRESSION = <ComponentType.PROFILE_PROGRESSION: 104> - - -
    - - - - -
    -
    -
    - ALL_PROFILES = <ComponentType.ALL_PROFILES: (100, 102, 103, 104)> - - -
    - - -

    All profile components.

    -
    - - -
    -
    -
    - VENDORS = <ComponentType.VENDORS: 400> - - -
    - - - - -
    -
    -
    - VENDOR_SALES = <ComponentType.VENDOR_SALES: 402> - - -
    - - - - -
    -
    -
    - VENDOR_RECEIPTS = <ComponentType.VENDOR_RECEIPTS: 101> - - -
    - - - - -
    -
    -
    - ALL_VENDORS = <ComponentType.ALL_VENDORS: (400, 101, 402)> - - -
    - - -

    All vendor components.

    -
    - - -
    -
    -
    - ITEM_INSTANCES = <ComponentType.ITEM_INSTANCES: 300> - - -
    - - - - -
    -
    -
    - ITEM_OBJECTIVES = <ComponentType.ITEM_OBJECTIVES: 301> - - -
    - - - - -
    -
    -
    - ITEM_PERKS = <ComponentType.ITEM_PERKS: 302> - - -
    - - - - -
    -
    -
    - ITEM_RENDER_DATA = <ComponentType.ITEM_RENDER_DATA: 303> - - -
    - - - - -
    -
    -
    - ITEM_STATS = <ComponentType.ITEM_STATS: 304> - - -
    - - - - -
    -
    -
    - ITEM_SOCKETS = <ComponentType.ITEM_SOCKETS: 305> - - -
    - - - - -
    -
    -
    - ITEM_TALENT_GRINDS = <ComponentType.ITEM_TALENT_GRINDS: 306> - - -
    - - - - -
    -
    -
    - ITEM_PLUG_STATES = <ComponentType.ITEM_PLUG_STATES: 308> +

    Base client.

    - -
    - - - +
    Example
    -
    -
    -
    - ITEM_PLUG_OBJECTIVES = <ComponentType.ITEM_PLUG_OBJECTIVES: 309> +
    +
    import aiobungie
     
    -        
    -    
    - - - +client = aiobungie.Client('YOUR_API_KEY') -
    -
    -
    - ITEM_REUSABLE_PLUGS = <ComponentType.ITEM_REUSABLE_PLUGS: 310> +# Search for Destiny2 users. +async def main() -> None: + users = await client.search_users('Crit') - -
    - - - + # Iterate over the users and take the first 5 results. + for user in users.take(5): + print(f'{user.name} ({user.code})') -
    -
    -
    - ALL_ITEMS = <ComponentType.ALL_ITEMS: (309, 308, 305, 300, 301, 302, 303, 304, 306, 310)> + # Iterate through the users memberships. + for membership in user.memberships: + print(membership.type, membership.id) - -
    - - -

    All item components.

    +client.run(main()) # or asyncio.run(main()) +
    +

    Single RESTClient instance.

    -
    -
    -
    - PLATFORM_SILVER = <ComponentType.PLATFORM_SILVER: 105> - - -
    - - - - -
    -
    -
    - KIOSKS = <ComponentType.KIOSKS: 500> - - -
    - - - - -
    -
    -
    - CURRENCY_LOOKUPS = <ComponentType.CURRENCY_LOOKUPS: 600> - - -
    - - - - -
    -
    -
    - PRESENTATION_NODES = <ComponentType.PRESENTATION_NODES: 700> - - -
    - - - - -
    -
    -
    - COLLECTIBLES = <ComponentType.COLLECTIBLES: 800> - - -
    - - - - -
    -
    -
    - RECORDS = <ComponentType.RECORDS: 900> - - -
    - - - - -
    -
    -
    - TRANSITORY = <ComponentType.TRANSITORY: 1000> - - -
    - - - - -
    -
    -
    - METRICS = <ComponentType.METRICS: 1100> - - -
    - - - - -
    -
    -
    - INVENTORIES = <ComponentType.PROFILE_INVENTORIES: 102> - - -
    - - - - -
    -
    -
    - STRING_VARIABLES = <ComponentType.STRING_VARIABLES: 1200> - - -
    - - - - -
    -
    -
    - CRAFTABLES = <ComponentType.CRAFTABLES: 1300> - - -
    - - - - -
    -
    -
    - CHARACTERS = <ComponentType.CHARACTERS: 200> - - -
    - - - - -
    -
    -
    - CHARACTER_INVENTORY = <ComponentType.CHARACTER_INVENTORY: 201> - - -
    - - - - -
    -
    -
    - CHARECTER_PROGRESSION = <ComponentType.CHARECTER_PROGRESSION: 202> - - -
    - - - - -
    -
    -
    - CHARACTER_RENDER_DATA = <ComponentType.CHARACTER_RENDER_DATA: 203> - - -
    - - - +

    The difference between base client and the REST clients:

    -
    -
    -
    - CHARACTER_ACTIVITIES = <ComponentType.CHARACTER_ACTIVITIES: 204> +
      +
    • No Hight-Level concepts.
    • +
    • All returned data are pure JSON objects from the API.
    • +
    • No object creation.
    • +
    - -
    - - - +
    Example
    -
    -
    -
    - CHARACTER_EQUIPMENT = <ComponentType.CHARACTER_EQUIPMENT: 205> +
    +
    import aiobungie
     
    -        
    -    
    - - - +async def main() -> None: + # Using `async with` context manager to close the session properly. + async with aiobungie.RESTClient("TOKEN") as rest: + payload = await rest.fetch_player('Fateꀒ', 4275) -
    -
    -
    - ALL_CHARACTERS = <ComponentType.ALL_CHARACTERS: (200, 201, 202, 203, 204, 205, 900)> + for membership in payload: + print(membership['membershipId'], membership['iconPath']) - -
    - - -

    All character components.

    +import asyncio +asyncio.run(main()) +
    +

    REST client pool.

    -
    -
    -
    - ALL = <ComponentType.ALL: (100, 102, 103, 104, 200, 201, 202, 203, 204, 205, 900, 400, 101, 402, 309, 308, 305, 300, 301, 302, 303, 304, 306, 310, 900, 600, 700, 800, 500, 1100, 105, 102, 1200, 1000, 1300)> - - -
    - - -

    ALl components included.

    -
    +

    A REST client pool allows you to acquire multiple RESTClient instances that shares the same connection.

    +
    Example
    -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    +
    +
    import aiobungie
    +import asyncio
     
    -            
    -
    -
    -
    -
    - -
    -
    @typing.final
    +pool = aiobungie.RESTPool("token") - class - CredentialType(builtins.int, aiobungie.Enum): +async def func1() -> None: + async with pool.acquire() as instance: + tokens = await instance.fetch_oauth2_tokens('code') + pool.metadata['tokens'] = tokens - +# Other instance may access the tokens from pool since its shared. -
    - -
    664@typing.final
    -665class CredentialType(int, Enum):
    -666    """The types of the accounts system supports at bungie."""
    -667
    -668    NONE = 0
    -669    XUID = 1
    -670    PSNID = 2
    -671    WILD = 3
    -672    FAKE = 4
    -673    FACEBOOK = 5
    -674    GOOGLE = 8
    -675    WINDOWS = 9
    -676    DEMONID = 10
    -677    STEAMID = 12
    -678    BATTLENETID = 14
    -679    STADIAID = 16
    -680    TWITCHID = 18
    -
    +async def func2() -> None: + async with pool.acquire() as instance: + tokens = pool.metadata['tokens'] + tokens = await instance.refresh_access_token(tokens.refresh_token) +async def main() -> None: + await asyncio.gather(func1(), func2()) -

    The types of the accounts system supports at bungie.

    +asyncio.run(main()) +
    +

    Should you use the base client or the REST client? +This returns to you. For an example if you're building a website.

    -
    -
    - NONE = <CredentialType.NONE: 0> +

    You can use python as a REST API in the backend with the RESTClient since all returned object are JSON objects. +Which gives you the freedom to deserialize it and implement your own logic in the front-end.

    - -
    - - - +

    Or of you're building a Discord bot for an example or something simple. The base client is the way to go.

    +
    - -
    -
    - XUID = <CredentialType.XUID: 1> + - -
    - - - + -
    -
    -
    - PSNID = <CredentialType.PSNID: 2> +
      1# MIT License
    +  2#
    +  3# Copyright (c) 2020 - Present nxtlo
    +  4#
    +  5# Permission is hereby granted, free of charge, to any person obtaining a copy
    +  6# of this software and associated documentation files (the "Software"), to deal
    +  7# in the Software without restriction, including without limitation the rights
    +  8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    +  9# copies of the Software, and to permit persons to whom the Software is
    + 10# furnished to do so, subject to the following conditions:
    + 11#
    + 12# The above copyright notice and this permission notice shall be included in all
    + 13# copies or substantial portions of the Software.
    + 14#
    + 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    + 16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    + 17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    + 18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    + 19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    + 20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    + 21# SOFTWARE.
    + 22
    + 23"""A Pythonic `async`/`await` wrapper for interacting with the Bungie API.
    + 24
    + 25Base client.
    + 26
    + 27Example
    + 28-------
    + 29```py
    + 30import aiobungie
    + 31
    + 32client = aiobungie.Client('YOUR_API_KEY')
    + 33
    + 34# Search for Destiny2 users.
    + 35async def main() -> None:
    + 36    users = await client.search_users('Crit')
    + 37
    + 38    # Iterate over the users and take the first 5 results.
    + 39    for user in users.take(5):
    + 40        print(f'{user.name} ({user.code})')
    + 41
    + 42        # Iterate through the users memberships.
    + 43        for membership in user.memberships:
    + 44            print(membership.type, membership.id)
    + 45
    + 46client.run(main()) # or asyncio.run(main())
    + 47```
    + 48
    + 49Single RESTClient instance.
    + 50
    + 51The difference between base client and the REST clients:
    + 52
    + 53* No Hight-Level concepts.
    + 54* All returned data are pure JSON objects from the API.
    + 55* No object creation.
    + 56
    + 57Example
    + 58-------
    + 59```py
    + 60import aiobungie
    + 61
    + 62async def main() -> None:
    + 63    # Using `async with` context manager to close the session properly.
    + 64    async with aiobungie.RESTClient("TOKEN") as rest:
    + 65        payload = await rest.fetch_player('Fateꀒ', 4275)
    + 66
    + 67        for membership in payload:
    + 68            print(membership['membershipId'], membership['iconPath'])
    + 69
    + 70import asyncio
    + 71asyncio.run(main())
    + 72```
    + 73
    + 74REST client pool.
    + 75
    + 76A REST client pool allows you to acquire multiple `RESTClient` instances that shares the same connection.
    + 77
    + 78Example
    + 79-------
    + 80```py
    + 81import aiobungie
    + 82import asyncio
    + 83
    + 84pool = aiobungie.RESTPool("token")
    + 85
    + 86async def func1() -> None:
    + 87    async with pool.acquire() as instance:
    + 88        tokens = await instance.fetch_oauth2_tokens('code')
    + 89        pool.metadata['tokens'] = tokens
    + 90
    + 91# Other instance may access the tokens from pool since its shared.
    + 92
    + 93async def func2() -> None:
    + 94    async with pool.acquire() as instance:
    + 95        tokens = pool.metadata['tokens']
    + 96        tokens = await instance.refresh_access_token(tokens.refresh_token)
    + 97
    + 98async def main() -> None:
    + 99    await asyncio.gather(func1(), func2())
    +100
    +101asyncio.run(main())
    +102```
    +103
    +104Should you use the base client or the REST client?
    +105This returns to you. For an example if you're building a website.
    +106
    +107You can use python as a REST API in the backend with the RESTClient since all returned object are JSON objects.
    +108Which gives you the freedom to deserialize it and implement your own logic in the front-end.
    +109
    +110Or of you're building a Discord bot for an example or something simple. The base client is the way to go.
    +111"""
    +112
    +113
    +114from __future__ import annotations
    +115
    +116from aiobungie import builders
    +117from aiobungie import crates
    +118from aiobungie import interfaces
    +119from aiobungie import traits
    +120from aiobungie import typedefs
    +121from aiobungie import url
    +122from aiobungie.client import Client
    +123from aiobungie.error import *
    +124from aiobungie.internal import iterators
    +125from aiobungie.internal.assets import Image
    +126from aiobungie.internal.enums import *
    +127from aiobungie.internal.factory import Factory
    +128from aiobungie.internal.iterators import *
    +129from aiobungie.rest import *
    +130from aiobungie.undefined import Undefined
    +131from aiobungie.undefined import UndefinedOr
    +132from aiobungie.undefined import UndefinedType
    +133
    +134from ._info import __about__
    +135from ._info import __author__
    +136from ._info import __docs__
    +137from ._info import __email__
    +138from ._info import __license__
    +139from ._info import __url__
    +140from ._info import __version__
    +141
    +142# Alias for crate for backwards compatibility.
    +143crate = crates
    +144
    +145# Activity enums
    +146from .crates.activity import Difficulty
    +147
    +148# Components enums
    +149from .crates.components import ComponentFields
    +150from .crates.components import ComponentPrivacy
    +151
    +152# Entity enums
    +153from .crates.entity import GatingScope
    +154from .crates.entity import ObjectiveUIStyle
    +155from .crates.entity import ValueUIStyle
    +156
    +157# Fireteam enums.
    +158from .crates.fireteams import FireteamActivity
    +159from .crates.fireteams import FireteamDate
    +160from .crates.fireteams import FireteamLanguage
    +161from .crates.fireteams import FireteamPlatform
    +162
    +163# Records enums
    +164from .crates.records import RecordState
    +165
    +166__all__ = [mod for mod in dir() if not mod.startswith("_")]  # type: ignore
    +
    - -
    - - - -
    -
    -
    - WILD = <CredentialType.WILD: 3> +
    +
    + +
    +
    @attrs.define(auto_exc=True)
    - -
    - - - + class + AiobungieError(builtins.RuntimeError): - -
    -
    - FAKE = <CredentialType.FAKE: 4> + -
    - - - + +
    57@attrs.define(auto_exc=True)
    +58class AiobungieError(RuntimeError):
    +59    """Base exception class that all other errors inherit from."""
    +
    -
    -
    -
    - FACEBOOK = <CredentialType.FACEBOOK: 5> - -
    - - - +

    Base exception class that all other errors inherit from.

    +
    -
    -
    -
    - GOOGLE = <CredentialType.GOOGLE: 8> - -
    - - - +
    + +
    + + AiobungieError() -
    -
    -
    - WINDOWS = <CredentialType.WINDOWS: 9> + -
    - - - + +
    2def __init__(self, ):
    +3    BaseException.__init__(self, )
    +
    -
    -
    -
    - DEMONID = <CredentialType.DEMONID: 10> - -
    - - - +

    Method generated by attrs for class AiobungieError.

    +
    +
    -
    -
    - STEAMID = <CredentialType.STEAMID: 12> - - -
    - - - +
    +
    Inherited Members
    +
    +
    builtins.BaseException
    +
    with_traceback
    +
    +
    -
    -
    - BATTLENETID = <CredentialType.BATTLENETID: 14> +
    +
    + +
    +
    @typing.final
    - -
    - - - + class + AmmoType(builtins.int, aiobungie.Enum): - -
    -
    - STADIAID = <CredentialType.STADIAID: 16> + -
    - - - + +
    643@typing.final
    +644class AmmoType(int, Enum):
    +645    """AN enum for Detyiny 2 ammo types."""
    +646
    +647    NONE = 0
    +648    PRIMARY = 1
    +649    SPECIAL = 2
    +650    HEAVY = 3
    +
    -
    -
    -
    - TWITCHID = <CredentialType.TWITCHID: 18> - -
    - - - +

    AN enum for Detyiny 2 ammo types.

    +
    + -
    Inherited Members
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    -
    - +
    +
    -
    @typing.final
    +
    @attrs.define(auto_exc=True)
    class - DamageType(builtins.int, aiobungie.Enum): + BadRequest(aiobungie.HTTPError): - +
    - -
    542@typing.final
    -543class DamageType(int, Enum):
    -544    """Enums for Destiny Damage types"""
    -545
    -546    NONE = 0
    -547    KINETIC = 1
    -548    ARC = 2
    -549    SOLAR = 3
    -550    VOID = 4
    -551    RAID = 5
    -552    """This is a special damage type reserved for some raid activity encounters."""
    -553    STASIS = 6
    +    
    +            
    147@attrs.define(auto_exc=True)
    +148class BadRequest(HTTPError):
    +149    """Bad requests exceptions."""
    +150
    +151    url: typing.Optional[typedefs.StrOrURL]
    +152    """The URL/endpoint caused this error."""
    +153
    +154    body: typing.Any
    +155    """The response body."""
    +156
    +157    headers: multidict.CIMultiDictProxy[str]
    +158    """The response headers."""
    +159
    +160    http_status: http.HTTPStatus = attrs.field(default=http.HTTPStatus.BAD_REQUEST)
     
    -

    Enums for Destiny Damage types

    +

    Bad requests exceptions.

    -
    -
    - NONE = <DamageType.NONE: 0> - - -
    - - - +
    + +
    + + BadRequest( message: str, url: Union[str, yarl.URL, NoneType], body: Any, headers: multidict._multidict.CIMultiDictProxy[str], http_status: http.HTTPStatus = <HTTPStatus.BAD_REQUEST: 400>) -
    -
    -
    - KINETIC = <DamageType.KINETIC: 1> + -
    - - - + +
    2def __init__(self, message, url, body, headers, http_status=attr_dict['http_status'].default):
    +3    self.message = message
    +4    self.url = url
    +5    self.body = body
    +6    self.headers = headers
    +7    self.http_status = http_status
    +8    BaseException.__init__(self, self.message,self.url,self.body,self.headers,self.http_status)
    +
    -
    -
    -
    - ARC = <DamageType.ARC: 2> - -
    - - - +

    Method generated by attrs for class BadRequest.

    +
    +
    -
    +
    - SOLAR = <DamageType.SOLAR: 3> + url: Union[str, yarl.URL, NoneType]
    - - + +

    The URL/endpoint caused this error.

    +
    +
    -
    +
    - VOID = <DamageType.VOID: 4> + body: Any
    - - + +

    The response body.

    +
    +
    -
    +
    - RAID = <DamageType.RAID: 5> + headers: multidict._multidict.CIMultiDictProxy[str]
    - + -

    This is a special damage type reserved for some raid activity encounters.

    +

    The response headers.

    -
    +
    - STASIS = <DamageType.STASIS: 6> + http_status: http.HTTPStatus
    - - + +

    The response status.

    +
    +
    Inherited Members
    -
    Enum
    -
    name
    -
    value
    + -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    +
    builtins.BaseException
    +
    with_traceback
    -
    - +
    +
    @typing.final
    class - Difficulty(builtins.int, aiobungie.Enum): + ClanMemberType(builtins.int, aiobungie.Enum): - +
    - -
    65@typing.final
    -66class Difficulty(int, enums.Enum):
    -67    """An enum for activities difficulties."""
    -68
    -69    TRIVIAL = 0
    -70    EASY = 1
    -71    NORMAL = 2
    -72    CHALLENGING = 3
    -73    HARD = 4
    -74    BRAVE = 5
    -75    ALMOST_IMPOSSIBLE = 6
    -76    IMPOSSIBLE = 7
    +    
    +            
    698@typing.final
    +699class ClanMemberType(int, Enum):
    +700    """An enum for bungie clan member types."""
    +701
    +702    NONE = 0
    +703    BEGINNER = 1
    +704    MEMBER = 2
    +705    ADMIN = 3
    +706    ACTING_FOUNDER = 4
    +707    FOUNDER = 5
     
    -

    An enum for activities difficulties.

    +

    An enum for bungie clan member types.

    -
    -
    - TRIVIAL = <Difficulty.TRIVIAL: 0> - - -
    - - - - -
    -
    -
    - EASY = <Difficulty.EASY: 1> - - -
    - - - - -
    -
    -
    - NORMAL = <Difficulty.NORMAL: 2> - - -
    - - - - -
    -
    -
    - CHALLENGING = <Difficulty.CHALLENGING: 3> - - -
    - - - - -
    -
    -
    - HARD = <Difficulty.HARD: 4> - - -
    - - - - -
    -
    -
    - BRAVE = <Difficulty.BRAVE: 5> +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    - -
    - - - +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    +
    -
    -
    - ALMOST_IMPOSSIBLE = <Difficulty.ALMOST_IMPOSSIBLE: 6> +
    +
    + +
    +
    @typing.final
    - -
    - - - + class + Class(builtins.int, aiobungie.Enum): - -
    -
    - IMPOSSIBLE = <Difficulty.IMPOSSIBLE: 7> + -
    - - - + +
    474@typing.final
    +475class Class(int, Enum):
    +476    """An Enum for Destiny character classes."""
    +477
    +478    TITAN = 0
    +479    HUNTER = 1
    +480    WARLOCK = 2
    +481    UNKNOWN = 3
    +
    + + +

    An Enum for Destiny character classes.

    +
    + -
    Inherited Members
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    -
    - +
    +
    -
    @typing.final
    + + class + Client(aiobungie.traits.ClientApp): + + + +
    + +
      61class Client(traits.ClientApp):
    +  62    """Standard Bungie API client application.
    +  63
    +  64    This client deserialize the REST JSON responses using `aiobungie.internal.factory.Factory`
    +  65    and returns `aiobungie.crates` Python object implementations of the responses.
    +  66
    +  67    A `aiobungie.RESTClient` REST client can also be used alone for low-level concepts.
    +  68
    +  69    Example
    +  70    -------
    +  71    ```py
    +  72    import aiobungie
    +  73
    +  74    client = aiobungie.Client('...')
    +  75
    +  76    async def main():
    +  77        async with client.rest:
    +  78            user = await client.fetch_current_user_memberships('...')
    +  79            print(user)
    +  80    ```
    +  81
    +  82    Parameters
    +  83    -----------
    +  84    token: `str`
    +  85        Your Bungie's API key or Token from the developer's portal.
    +  86
    +  87    Other Parameters
    +  88    ----------------
    +  89    rest_client: `aiobungie.interfaces.RESTInterface | None`
    +  90        An optional rest client instance you can pass.
    +  91        If set to `None` then the client will use the default instance.
    +  92
    +  93    max_retries : `int`
    +  94        The max retries number to retry if the request hit a `5xx` status code.
    +  95    max_ratelimit_retries : `int`
    +  96        The max retries number to retry if the request hit a `429` status code. Defaults to `3`.
    +  97    client_secret : `str | None`
    +  98        An optional application client secret,
    +  99        This is only needed if you're fetching OAuth2 tokens with this client.
    + 100    client_id : `int | None`
    + 101        An optional application client id,
    + 102        This is only needed if you're fetching OAuth2 tokens with this client.
    + 103    """
    + 104
    + 105    __slots__ = ("_rest", "_factory", "_client_secret", "_client_id")
    + 106
    + 107    def __init__(
    + 108        self,
    + 109        token: str,
    + 110        /,
    + 111        client_secret: typing.Optional[str] = None,
    + 112        client_id: typing.Optional[int] = None,
    + 113        *,
    + 114        rest_client: typing.Optional[interfaces.RESTInterface] = None,
    + 115        max_retries: int = 4,
    + 116        max_ratelimit_retries: int = 3,
    + 117    ) -> None:
    + 118
    + 119        self._client_secret = client_secret
    + 120        self._client_id = client_id
    + 121
    + 122        self._rest = (
    + 123            rest_client
    + 124            if rest_client is not None
    + 125            else rest_.RESTClient(
    + 126                token,
    + 127                client_secret,
    + 128                client_id,
    + 129                max_retries=max_retries,
    + 130                max_ratelimit_retries=max_ratelimit_retries,
    + 131            )
    + 132        )
    + 133
    + 134        self._factory = factory_.Factory(self)
    + 135
    + 136    @property
    + 137    def factory(self) -> factory_.Factory:
    + 138        return self._factory
    + 139
    + 140    @property
    + 141    def rest(self) -> interfaces.RESTInterface:
    + 142        return self._rest
    + 143
    + 144    @property
    + 145    def request(self) -> Client:
    + 146        return copy.copy(self)
    + 147
    + 148    @property
    + 149    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    + 150        return self._rest.metadata
    + 151
    + 152    def run(
    + 153        self, future: collections.Coroutine[typing.Any, None, None], debug: bool = False
    + 154    ) -> None:
    + 155        loop: typing.Final[asyncio.AbstractEventLoop] = helpers.get_or_make_loop()
    + 156        try:
    + 157            if not loop.is_running():
    + 158                loop.set_debug(debug)
    + 159                loop.run_until_complete(future)
    + 160
    + 161        except Exception as exc:
    + 162            raise RuntimeError(f"Failed to run {future.__qualname__}") from exc
    + 163
    + 164        except KeyboardInterrupt:
    + 165            _LOG.warn("Unexpected Keyboard interrupt. Exiting.")
    + 166            return
    + 167
    + 168    # * User methods.
    + 169
    + 170    async def fetch_current_user_memberships(self, access_token: str, /) -> user.User:
    + 171        """Fetch and return a user object of the bungie net user associated with account.
    + 172
    + 173        .. warning::
    + 174            This method requires OAuth2 scope and a Bearer access token.
    + 175
    + 176        Parameters
    + 177        ----------
    + 178        access_token : `str`
    + 179            A valid Bearer access token for the authorization.
    + 180
    + 181        Returns
    + 182        -------
    + 183        `aiobungie.crates.user.User`
    + 184            A user object includes the Destiny memberships and Bungie.net user.
    + 185        """
    + 186        resp = await self.rest.fetch_current_user_memberships(access_token)
    + 187
    + 188        return self.factory.deserialize_user(resp)
    + 189
    + 190    async def fetch_bungie_user(self, id: int, /) -> user.BungieUser:
    + 191        """Fetch a Bungie user by their BungieNet id.
    + 192
    + 193        .. note::
    + 194            This returns a Bungie user membership only. Take a look at `Client.fetch_membership_from_id`
    + 195            for other memberships.
    + 196
    + 197        Parameters
    + 198        ----------
    + 199        id: `int`
    + 200            The user id.
    + 201
    + 202        Returns
    + 203        -------
    + 204        `aiobungie.crates.user.BungieUser`
    + 205            A Bungie user.
    + 206
    + 207        Raises
    + 208        ------
    + 209        `aiobungie.error.NotFound`
    + 210            The user was not found.
    + 211        """
    + 212        payload = await self.rest.fetch_bungie_user(id)
    + 213
    + 214        return self.factory.deserialize_bungie_user(payload)
    + 215
    + 216    async def search_users(
    + 217        self, name: str, /
    + 218    ) -> iterators.Iterator[user.SearchableDestinyUser]:
    + 219        """Search for players and return all players that matches the same name.
    + 220
    + 221        Parameters
    + 222        ----------
    + 223        name : `buildins.str`
    + 224            The user name.
    + 225
    + 226        Returns
    + 227        -------
    + 228        `aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]`
    + 229            A sequence of destiny memberships.
    + 230        """
    + 231        payload = await self.rest.search_users(name)
    + 232
    + 233        return iterators.Iterator(
    + 234            [
    + 235                self.factory.deserialize_searched_user(user)
    + 236                for user in payload["searchResults"]
    + 237            ]
    + 238        )
    + 239
    + 240    async def fetch_user_themes(self) -> collections.Sequence[user.UserThemes]:
    + 241        """Fetch all available user themes.
    + 242
    + 243        Returns
    + 244        -------
    + 245        `collections.Sequence[aiobungie.crates.user.UserThemes]`
    + 246            A sequence of user themes.
    + 247        """
    + 248        data = await self.rest.fetch_user_themes()
    + 249
    + 250        return self.factory.deserialize_user_themes(data)
    + 251
    + 252    async def fetch_hard_types(
    + 253        self,
    + 254        credential: int,
    + 255        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
    + 256        /,
    + 257    ) -> user.HardLinkedMembership:
    + 258        """Gets any hard linked membership given a credential.
    + 259        Only works for credentials that are public just `aiobungie.CredentialType.STEAMID` right now.
    + 260        Cross Save aware.
    + 261
    + 262        Parameters
    + 263        ----------
    + 264        credential: `int`
    + 265            A valid SteamID64
    + 266        type: `aiobungie.CredentialType`
    + 267            The credential type. This must not be changed
    + 268            Since its only credential that works "currently"
    + 269
    + 270        Returns
    + 271        -------
    + 272        `aiobungie.crates.user.HardLinkedMembership`
    + 273            Information about the hard linked data.
    + 274        """
    + 275
    + 276        payload = await self.rest.fetch_hardlinked_credentials(credential, type)
    + 277
    + 278        return user.HardLinkedMembership(
    + 279            id=int(payload["membershipId"]),
    + 280            type=enums.MembershipType(payload["membershipType"]),
    + 281            cross_save_type=enums.MembershipType(payload["CrossSaveOverriddenType"]),
    + 282        )
    + 283
    + 284    async def fetch_membership_from_id(
    + 285        self,
    + 286        id: int,
    + 287        /,
    + 288        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    + 289    ) -> user.User:
    + 290        """Fetch Bungie user's memberships from their id.
    + 291
    + 292        Notes
    + 293        -----
    + 294        * This returns both BungieNet membership and a sequence of the player's DestinyMemberships
    + 295        Which includes Stadia, Xbox, Steam and PSN memberships if the player has them,
    + 296        see `aiobungie.crates.user.DestinyMembership` for more details.
    + 297        * If you only want the bungie user. Consider using `Client.fetch_user` method.
    + 298
    + 299        Parameters
    + 300        ----------
    + 301        id : `int`
    + 302            The user's id.
    + 303        type : `aiobungie.MembershipType`
    + 304            The user's membership type.
    + 305
    + 306        Returns
    + 307        -------
    + 308        `aiobungie.crates.User`
    + 309            A Bungie user with their membership types.
    + 310
    + 311        Raises
    + 312        ------
    + 313        aiobungie.NotFound
    + 314            The requested user was not found.
    + 315        """
    + 316        payload = await self.rest.fetch_membership_from_id(id, type)
    + 317
    + 318        return self.factory.deserialize_user(payload)
    + 319
    + 320    async def fetch_user_credentials(
    + 321        self, access_token: str, membership_id: int, /
    + 322    ) -> collections.Sequence[user.UserCredentials]:
    + 323        """Fetch an array of credential types attached to the requested account.
    + 324
    + 325        .. note::
    + 326            This method require OAuth2 Bearer access token.
    + 327
    + 328        Parameters
    + 329        ----------
    + 330        access_token : `str`
    + 331            The bearer access token associated with the bungie account.
    + 332        membership_id : `int`
    + 333            The id of the membership to return.
    + 334
    + 335        Returns
    + 336        -------
    + 337        `collections.Sequence[aiobungie.crates.UserCredentials]`
    + 338            A sequence of the attached user credentials.
    + 339
    + 340        Raises
    + 341        ------
    + 342        `aiobungie.Unauthorized`
    + 343            The access token was wrong or no access token passed.
    + 344        """
    + 345        resp = await self.rest.fetch_user_credentials(access_token, membership_id)
    + 346
    + 347        return self.factory.deserialize_user_credentials(resp)
    + 348
    + 349    # * Destiny 2.
    + 350
    + 351    async def fetch_profile(
    + 352        self,
    + 353        member_id: int,
    + 354        type: typedefs.IntAnd[enums.MembershipType],
    + 355        components: list[enums.ComponentType],
    + 356        auth: typing.Optional[str] = None,
    + 357    ) -> components.Component:
    + 358        """
    + 359        Fetch a bungie profile passing components to the request.
    + 360
    + 361        Parameters
    + 362        ----------
    + 363        member_id: `int`
    + 364            The member's id.
    + 365        type: `aiobungie.MembershipType`
    + 366            A valid membership type.
    + 367        components : `list[aiobungie.ComponentType]`
    + 368            List of profile components to collect and return.
    + 369
    + 370        Other Parameters
    + 371        ----------------
    + 372        auth : `typing.Optional[str]`
    + 373            A Bearer access_token to make the request with.
    + 374            This is optional and limited to components that only requires an Authorization token.
    + 375
    + 376        Returns
    + 377        --------
    + 378        `aiobungie.crates.Component`
    + 379            A Destiny 2 player profile with its components.
    + 380            Only passed components will be available if they exists. Otherwise they will be `None`
    + 381
    + 382        Raises
    + 383        ------
    + 384        `aiobungie.MembershipTypeError`
    + 385            The provided membership type was invalid.
    + 386        """
    + 387        data = await self.rest.fetch_profile(member_id, type, components, auth)
    + 388        return self.factory.deserialize_components(data)
    + 389
    + 390    async def fetch_linked_profiles(
    + 391        self,
    + 392        member_id: int,
    + 393        member_type: typedefs.IntAnd[enums.MembershipType],
    + 394        /,
    + 395        *,
    + 396        all: bool = False,
    + 397    ) -> profile.LinkedProfile:
    + 398        """Returns a summary information about all profiles linked to the requested member.
    + 399
    + 400        The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships.
    + 401
    + 402        .. note::
    + 403            It will only return linked accounts whose linkages you are allowed to view.
    + 404
    + 405        Parameters
    + 406        ----------
    + 407        member_id : `int`
    + 408            The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID.
    + 409        member_type : `aiobungie.MembershipType`
    + 410            The type for the membership whose linked Destiny account you want to return.
    + 411
    + 412        Other Parameters
    + 413        ----------------
    + 414        all : `bool`
    + 415            If provided and set to `True`, All memberships regardless
    + 416            of whether they're obscured by overrides will be returned,
    + 417
    + 418            If provided and set to `False`, Only available memberships will be returned.
    + 419            The default for this is `False`.
    + 420
    + 421        Returns
    + 422        -------
    + 423        `aiobungie.crates.profile.LinkedProfile`
    + 424            A linked profile object.
    + 425        """
    + 426        resp = await self.rest.fetch_linked_profiles(member_id, member_type, all=all)
    + 427
    + 428        return self.factory.deserialize_linked_profiles(resp)
    + 429
    + 430    async def fetch_player(
    + 431        self,
    + 432        name: str,
    + 433        code: int,
    + 434        /,
    + 435        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
    + 436    ) -> collections.Sequence[user.DestinyMembership]:
    + 437        """Fetch a Destiny 2 player's memberships.
    + 438
    + 439        Parameters
    + 440        -----------
    + 441        name: `str`
    + 442            The unique Bungie player name.
    + 443        code : `int`
    + 444            The unique Bungie display name code.
    + 445        type: `aiobungie.internal.enums.MembershipType`
    + 446            The player's membership type, e,g. XBOX, STEAM, PSN
    + 447
    + 448        Returns
    + 449        --------
    + 450        `collections.Sequence[aiobungie.crates.DestinyMembership]`
    + 451            A sequence of the found Destiny 2 player memberships.
    + 452            An empty sequence will be returned if no one found.
    + 453
    + 454        Raises
    + 455        ------
    + 456        `aiobungie.MembershipTypeError`
    + 457            The provided membership type was invalid.
    + 458        """
    + 459        resp = await self.rest.fetch_player(name, code, type)
    + 460
    + 461        return self.factory.deserialize_destiny_memberships(resp)
    + 462
    + 463    async def fetch_character(
    + 464        self,
    + 465        member_id: int,
    + 466        membership_type: typedefs.IntAnd[enums.MembershipType],
    + 467        character_id: int,
    + 468        components: list[enums.ComponentType],
    + 469        auth: typing.Optional[str] = None,
    + 470    ) -> components.CharacterComponent:
    + 471        """Fetch a Destiny 2 character.
    + 472
    + 473        Parameters
    + 474        ----------
    + 475        member_id: `int`
    + 476            A valid bungie member id.
    + 477        character_id: `int`
    + 478            The Destiny character id to retrieve.
    + 479        membership_type: `aiobungie.internal.enums.MembershipType`
    + 480            The member's membership type.
    + 481        components: `list[aiobungie.ComponentType]`
    + 482            Multiple arguments of character components to collect and return.
    + 483
    + 484        Other Parameters
    + 485        ----------------
    + 486        auth : `typing.Optional[str]`
    + 487            A Bearer access_token to make the request with.
    + 488            This is optional and limited to components that only requires an Authorization token.
    + 489
    + 490        Returns
    + 491        -------
    + 492        `aiobungie.crates.CharacterComponent`
    + 493            A Bungie character component.
    + 494
    + 495        `aiobungie.MembershipTypeError`
    + 496            The provided membership type was invalid.
    + 497        """
    + 498        resp = await self.rest.fetch_character(
    + 499            member_id, membership_type, character_id, components, auth
    + 500        )
    + 501
    + 502        return self.factory.deserialize_character_component(resp)
    + 503
    + 504    async def fetch_unique_weapon_history(
    + 505        self,
    + 506        membership_id: int,
    + 507        character_id: int,
    + 508        membership_type: typedefs.IntAnd[enums.MembershipType],
    + 509    ) -> collections.Sequence[activity.ExtendedWeaponValues]:
    + 510        """Fetch details about unique weapon usage for a character. Includes all exotics.
    + 511
    + 512        Parameters
    + 513        ----------
    + 514        membership_id : `int`
    + 515            The Destiny user membership id.
    + 516        character_id : `int`
    + 517            The character id to retrieve.
    + 518        membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    + 519            The Destiny user's membership type.
    + 520
    + 521        Returns
    + 522        -------
    + 523        `collections.Sequence[aiobungie.crates.ExtendedWeaponValues]`
    + 524            A sequence of the weapon's extended values.
    + 525        """
    + 526        resp = await self._rest.fetch_unique_weapon_history(
    + 527            membership_id, character_id, membership_type
    + 528        )
    + 529
    + 530        return [
    + 531            self._factory.deserialize_extended_weapon_values(weapon)
    + 532            for weapon in resp["weapons"]
    + 533        ]
    + 534
    + 535    # * Destiny 2 Activities.
    + 536
    + 537    async def fetch_activities(
    + 538        self,
    + 539        member_id: int,
    + 540        character_id: int,
    + 541        mode: typedefs.IntAnd[enums.GameMode],
    + 542        *,
    + 543        membership_type: typedefs.IntAnd[
    + 544            enums.MembershipType
    + 545        ] = enums.MembershipType.ALL,
    + 546        page: int = 0,
    + 547        limit: int = 250,
    + 548    ) -> iterators.Iterator[activity.Activity]:
    + 549        """Fetch a Destiny 2 activity for the specified character id.
    + 550
    + 551        Parameters
    + 552        ----------
    + 553        member_id: `int`
    + 554            The user id that starts with `4611`.
    + 555        character_id: `int`
    + 556            The id of the character to retrieve the activities for.
    + 557        mode: `aiobungie.typedefs.IntAnd[aiobungie.internal.enums.GameMode]`
    + 558            This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc.
    + 559
    + 560        Other Parameters
    + 561        ----------------
    + 562        membership_type: `aiobungie.internal.enums.MembershipType`
    + 563            The Member ship type, if nothing was passed than it will return all.
    + 564        page: int
    + 565            The page number. Default is `0`
    + 566        limit: int
    + 567            Limit the returned result. Default is `250`.
    + 568
    + 569        Returns
    + 570        -------
    + 571        `aiobungie.iterators.Iterator[aiobungie.crates.Activity]`
    + 572            An iterator of the player's activities.
    + 573
    + 574        Raises
    + 575        ------
    + 576        `aiobungie.MembershipTypeError`
    + 577            The provided membership type was invalid.
    + 578        """
    + 579        resp = await self.rest.fetch_activities(
    + 580            member_id,
    + 581            character_id,
    + 582            mode,
    + 583            membership_type=membership_type,
    + 584            page=page,
    + 585            limit=limit,
    + 586        )
    + 587
    + 588        return self.factory.deserialize_activities(resp)
    + 589
    + 590    async def fetch_post_activity(self, instance_id: int, /) -> activity.PostActivity:
    + 591        """Fetch a post activity details.
    + 592
    + 593        Parameters
    + 594        ----------
    + 595        instance_id: `int`
    + 596            The activity instance id.
    + 597
    + 598        Returns
    + 599        -------
    + 600        `aiobungie.crates.PostActivity`
    + 601           A post activity object.
    + 602        """
    + 603        resp = await self.rest.fetch_post_activity(instance_id)
    + 604
    + 605        return self.factory.deserialize_post_activity(resp)
    + 606
    + 607    async def fetch_aggregated_activity_stats(
    + 608        self,
    + 609        character_id: int,
    + 610        membership_id: int,
    + 611        membership_type: typedefs.IntAnd[enums.MembershipType],
    + 612    ) -> iterators.Iterator[activity.AggregatedActivity]:
    + 613        """Fetch aggregated activity stats for a character.
    + 614
    + 615        Parameters
    + 616        ----------
    + 617        character_id: `int`
    + 618            The id of the character to retrieve the activities for.
    + 619        membership_id: `int`
    + 620            The id of the user that started with `4611`.
    + 621        membership_type: `aiobungie.internal.enums.MembershipType`
    + 622            The Member ship type.
    + 623
    + 624        Returns
    + 625        -------
    + 626        `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]`
    + 627            An iterator of the player's activities.
    + 628
    + 629        Raises
    + 630        ------
    + 631        `aiobungie.MembershipTypeError`
    + 632            The provided membership type was invalid.
    + 633        """
    + 634        resp = await self.rest.fetch_aggregated_activity_stats(
    + 635            character_id, membership_id, membership_type
    + 636        )
    + 637
    + 638        return self.factory.deserialize_aggregated_activities(resp)
    + 639
    + 640    # * Destiny 2 Clans or GroupsV2.
    + 641
    + 642    async def fetch_clan_from_id(
    + 643        self,
    + 644        id: int,
    + 645        /,
    + 646        access_token: typing.Optional[str] = None,
    + 647    ) -> clans.Clan:
    + 648        """Fetch a Bungie Clan by its id.
    + 649
    + 650        Parameters
    + 651        -----------
    + 652        id: `int`
    + 653            The clan id.
    + 654
    + 655        Returns
    + 656        --------
    + 657        `aiobungie.crates.Clan`
    + 658            An Bungie clan.
    + 659
    + 660        Raises
    + 661        ------
    + 662        `aiobungie.NotFound`
    + 663            The clan was not found.
    + 664        """
    + 665        resp = await self.rest.fetch_clan_from_id(id, access_token)
    + 666
    + 667        return self.factory.deserialize_clan(resp)
    + 668
    + 669    async def fetch_clan(
    + 670        self,
    + 671        name: str,
    + 672        /,
    + 673        access_token: typing.Optional[str] = None,
    + 674        *,
    + 675        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    + 676    ) -> clans.Clan:
    + 677        """Fetch a Clan by its name.
    + 678        This method will return the first clan found with given name.
    + 679
    + 680        Parameters
    + 681        ----------
    + 682        name: `str`
    + 683            The clan name
    + 684
    + 685        Other Parameters
    + 686        ----------------
    + 687        access_token : `typing.Optional[str]`
    + 688            An optional access token to make the request with.
    + 689
    + 690            If the token was bound to a member of the clan,
    + 691            This field `aiobungie.crates.Clan.current_user_membership` will be available
    + 692            and will return the membership of the user who made this request.
    + 693        type : `aiobungie.GroupType`
    + 694            The group type, Default is aiobungie.GroupType.CLAN.
    + 695
    + 696        Returns
    + 697        -------
    + 698        `aiobungie.crates.Clan`
    + 699            A Bungie clan.
    + 700
    + 701        Raises
    + 702        ------
    + 703        `aiobungie.NotFound`
    + 704            The clan was not found.
    + 705        """
    + 706        resp = await self.rest.fetch_clan(name, access_token, type=type)
    + 707
    + 708        return self.factory.deserialize_clan(resp)
    + 709
    + 710    async def fetch_clan_conversations(
    + 711        self, clan_id: int, /
    + 712    ) -> collections.Sequence[clans.ClanConversation]:
    + 713        """Fetch the conversations/chat channels of the given clan id.
    + 714
    + 715        Parameters
    + 716        ----------
    + 717        clan_id : `int`
    + 718            The clan id.
    + 719
    + 720        Returns
    + 721        `collections.Sequence[aiobungie.crates.ClanConversation]`
    + 722            A sequence of the clan chat channels.
    + 723        """
    + 724        resp = await self.rest.fetch_clan_conversations(clan_id)
    + 725
    + 726        return self.factory.deserialize_clan_conversations(resp)
    + 727
    + 728    async def fetch_clan_admins(
    + 729        self, clan_id: int, /
    + 730    ) -> iterators.Iterator[clans.ClanMember]:
    + 731        """Fetch the clan founder and admins.
    + 732
    + 733        Parameters
    + 734        ----------
    + 735        clan_id : `int`
    + 736            The clan id.
    + 737
    + 738        Returns
    + 739        -------
    + 740        `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]`
    + 741            An iterator over the found clan admins and founder.
    + 742
    + 743        Raises
    + 744        ------
    + 745        `aiobungie.NotFound`
    + 746            The requested clan was not found.
    + 747        """
    + 748        resp = await self.rest.fetch_clan_admins(clan_id)
    + 749
    + 750        return self.factory.deserialize_clan_members(resp)
    + 751
    + 752    async def fetch_groups_for_member(
    + 753        self,
    + 754        member_id: int,
    + 755        member_type: typedefs.IntAnd[enums.MembershipType],
    + 756        /,
    + 757        *,
    + 758        filter: int = 0,
    + 759        group_type: enums.GroupType = enums.GroupType.CLAN,
    + 760    ) -> collections.Sequence[clans.GroupMember]:
    + 761        """Fetch information about the groups that a given member has joined.
    + 762
    + 763        Parameters
    + 764        ----------
    + 765        member_id : `int`
    + 766            The member's id
    + 767        member_type : `aiobungie.MembershipType`
    + 768            The member's membership type.
    + 769
    + 770        Other Parameters
    + 771        ----------------
    + 772        filter : `int`
    + 773            Filter apply to list of joined groups. This Default to `0`
    + 774        group_type : `aiobungie.GroupType`
    + 775            The group's type.
    + 776            This is always set to `aiobungie.GroupType.CLAN` and should not be changed.
    + 777
    + 778        Returns
    + 779        -------
    + 780        `collections.Sequence[aiobungie.crates.GroupMember]`
    + 781            A sequence of joined groups for the fetched member.
    + 782        """
    + 783        resp = await self.rest.fetch_groups_for_member(
    + 784            member_id, member_type, filter=filter, group_type=group_type
    + 785        )
    + 786
    + 787        return [
    + 788            self.factory.deserialize_group_member(group) for group in resp["results"]
    + 789        ]
    + 790
    + 791    async def fetch_potential_groups_for_member(
    + 792        self,
    + 793        member_id: int,
    + 794        member_type: typedefs.IntAnd[enums.MembershipType],
    + 795        /,
    + 796        *,
    + 797        filter: int = 0,
    + 798        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    + 799    ) -> collections.Sequence[clans.GroupMember]:
    + 800        """Fetch the potential groups for a clan member.
    + 801
    + 802        Parameters
    + 803        ----------
    + 804        member_id : `int`
    + 805            The member's id
    + 806        member_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    + 807            The member's membership type.
    + 808
    + 809        Other Parameters
    + 810        ----------------
    + 811        filter : `int`
    + 812            Filter apply to list of joined groups. This Default to `0`
    + 813        group_type : `aiobungie.typedefs.IntAnd[aiobungie.GroupType]`
    + 814            The group's type.
    + 815            This is always set to `aiobungie.GroupType.CLAN` and should not be changed.
    + 816
    + 817        Returns
    + 818        -------
    + 819        `collections.Sequence[aiobungie.crates.GroupMember]`
    + 820            A sequence of joined potential groups for the fetched member.
    + 821        """
    + 822        resp = await self.rest.fetch_potential_groups_for_member(
    + 823            member_id, member_type, filter=filter, group_type=group_type
    + 824        )
    + 825
    + 826        return [
    + 827            self.factory.deserialize_group_member(group) for group in resp["results"]
    + 828        ]
    + 829
    + 830    async def fetch_clan_members(
    + 831        self,
    + 832        clan_id: int,
    + 833        /,
    + 834        *,
    + 835        name: typing.Optional[str] = None,
    + 836        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    + 837    ) -> iterators.Iterator[clans.ClanMember]:
    + 838        """Fetch Bungie clan members.
    + 839
    + 840        Parameters
    + 841        ----------
    + 842        clan_id : `int`
    + 843            The clans id
    + 844
    + 845        Other Parameters
    + 846        ----------------
    + 847        name : `typing.Optional[str]`
    + 848            If provided, Only players matching this name will be returned.
    + 849        type : `aiobungie.MembershipType`
    + 850            An optional clan member's membership type.
    + 851            This parameter is used to filter the returned results
    + 852            by the provided membership, For an example XBox memberships only,
    + 853            Otherwise will return all memberships.
    + 854
    + 855        Returns
    + 856        -------
    + 857        `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]`
    + 858            An iterator over the bungie clan members.
    + 859
    + 860        Raises
    + 861        ------
    + 862        `aiobungie.NotFound`
    + 863            The clan was not found.
    + 864        """
    + 865        resp = await self.rest.fetch_clan_members(clan_id, type=type, name=name)
    + 866
    + 867        return self.factory.deserialize_clan_members(resp)
    + 868
    + 869    async def fetch_clan_banners(self) -> collections.Sequence[clans.ClanBanner]:
    + 870        """Fetch the clan banners.
    + 871
    + 872        Returns
    + 873        -------
    + 874        `collections.Sequence[aiobungie.crates.ClanBanner]`
    + 875            A sequence of the clan banners.
    + 876        """
    + 877        resp = await self.rest.fetch_clan_banners()
    + 878
    + 879        return self.factory.deserialize_clan_banners(resp)
    + 880
    + 881    # This method is required to be here since it deserialize the clan.
    + 882    async def kick_clan_member(
    + 883        self,
    + 884        access_token: str,
    + 885        /,
    + 886        group_id: int,
    + 887        membership_id: int,
    + 888        membership_type: typedefs.IntAnd[enums.MembershipType],
    + 889    ) -> clans.Clan:
    + 890        """Kick a member from the clan.
    + 891
    + 892        .. note::
    + 893            This request requires OAuth2: oauth2: `AdminGroups` scope.
    + 894
    + 895        Parameters
    + 896        ----------
    + 897        access_token : `str`
    + 898            The bearer access token associated with the bungie account.
    + 899        group_id: `int`
    + 900            The group id.
    + 901        membership_id : `int`
    + 902            The member id to kick.
    + 903        membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    + 904            The member's membership type.
    + 905
    + 906        Returns
    + 907        -------
    + 908        `aiobungie.crates.clan.Clan`
    + 909            The clan that the member was kicked from.
    + 910        """
    + 911        resp = await self.rest.kick_clan_member(
    + 912            access_token,
    + 913            group_id=group_id,
    + 914            membership_id=membership_id,
    + 915            membership_type=membership_type,
    + 916        )
    + 917
    + 918        return self.factory.deserialize_clan(resp)
    + 919
    + 920    async def fetch_clan_weekly_rewards(self, clan_id: int) -> milestones.Milestone:
    + 921        """Fetch a Bungie clan's weekly reward state.
    + 922
    + 923        Parameters
    + 924        ----------
    + 925        clan_id : `int`
    + 926            The clan's id.
    + 927
    + 928        Returns
    + 929        -------
    + 930        `aiobungie.crates.Milestone`
    + 931            A runtime status of the clan's milestone data.
    + 932        """
    + 933
    + 934        resp = await self.rest.fetch_clan_weekly_rewards(clan_id)
    + 935
    + 936        return self.factory.deserialize_milestone(resp)
    + 937
    + 938    # * Destiny 2 Entities aka Definitions.
    + 939
    + 940    async def fetch_inventory_item(self, hash: int, /) -> entity.InventoryEntity:
    + 941        """Fetch a static inventory item entity given a its hash.
    + 942
    + 943        Parameters
    + 944        ----------
    + 945        hash: `int`
    + 946            Inventory item's hash.
    + 947
    + 948        Returns
    + 949        -------
    + 950        `aiobungie.crates.InventoryEntity`
    + 951            A bungie inventory item.
    + 952        """
    + 953        resp = await self.rest.fetch_inventory_item(hash)
    + 954
    + 955        return self.factory.deserialize_inventory_entity(resp)
    + 956
    + 957    async def fetch_objective_entity(self, hash: int, /) -> entity.ObjectiveEntity:
    + 958        """Fetch a Destiny objective entity given a its hash.
    + 959
    + 960        Parameters
    + 961        ----------
    + 962        hash: `int`
    + 963            objective's hash.
    + 964
    + 965        Returns
    + 966        -------
    + 967        `aiobungie.crates.ObjectiveEntity`
    + 968            An objective entity item.
    + 969        """
    + 970        resp = await self.rest.fetch_objective_entity(hash)
    + 971
    + 972        return self.factory.deserialize_objective_entity(resp)
    + 973
    + 974    async def search_entities(
    + 975        self, name: str, entity_type: str, *, page: int = 0
    + 976    ) -> iterators.Iterator[entity.SearchableEntity]:
    + 977        """Search for Destiny2 entities given a name and its type.
    + 978
    + 979        Parameters
    + 980        ----------
    + 981        name : `str`
    + 982            The name of the entity, i.e., Thunderlord, One thousand voices.
    + 983        entity_type : `str`
    + 984            The type of the entity, AKA Definition,
    + 985            For an example `DestinyInventoryItemDefinition` for emblems, weapons, and other inventory items.
    + 986
    + 987        Other Parameters
    + 988        ----------------
    + 989        page : `int`
    + 990            An optional page to return. Default to 0.
    + 991
    + 992        Returns
    + 993        -------
    + 994        `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]`
    + 995            An iterator over the found results matching the provided name.
    + 996        """
    + 997        resp = await self.rest.search_entities(name, entity_type, page=page)
    + 998
    + 999        return self.factory.deserialize_inventory_results(resp)
    +1000
    +1001    # Fireteams
    +1002
    +1003    async def fetch_fireteams(
    +1004        self,
    +1005        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    +1006        *,
    +1007        platform: typedefs.IntAnd[
    +1008            fireteams.FireteamPlatform
    +1009        ] = fireteams.FireteamPlatform.ANY,
    +1010        language: typing.Union[
    +1011            fireteams.FireteamLanguage, str
    +1012        ] = fireteams.FireteamLanguage.ALL,
    +1013        date_range: int = 0,
    +1014        page: int = 0,
    +1015        slots_filter: int = 0,
    +1016    ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]:
    +1017        """Fetch public Bungie fireteams with open slots.
    +1018
    +1019        Parameters
    +1020        ----------
    +1021        activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]`
    +1022            The fireteam activity type.
    +1023
    +1024        Other Parameters
    +1025        ----------------
    +1026        platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]`
    +1027            If this is provided. Then the results will be filtered with the given platform.
    +1028            Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms.
    +1029        language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]`
    +1030            A locale language to filter the used language in that fireteam.
    +1031            Defaults to `aiobungie.crates.FireteamLanguage.ALL`
    +1032        date_range : `int`
    +1033            An integer to filter the date range of the returned fireteams. Defaults to `aiobungie.FireteamDate.ALL`.
    +1034        page : `int`
    +1035            The page number. By default its `0` which returns all available activities.
    +1036        slots_filter : `int`
    +1037            Filter the returned fireteams based on available slots. Default is `0`
    +1038
    +1039        Returns
    +1040        -------
    +1041        `typing.Optional[collections.Sequence[fireteams.Fireteam]]`
    +1042            A sequence of `aiobungie.crates.Fireteam` or `None`.
    +1043        """
    +1044
    +1045        resp = await self.rest.fetch_fireteams(
    +1046            activity_type,
    +1047            platform=platform,
    +1048            language=language,
    +1049            date_range=date_range,
    +1050            page=page,
    +1051            slots_filter=slots_filter,
    +1052        )
    +1053
    +1054        return self.factory.deserialize_fireteams(resp)
    +1055
    +1056    async def fetch_avaliable_clan_fireteams(
    +1057        self,
    +1058        access_token: str,
    +1059        group_id: int,
    +1060        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    +1061        *,
    +1062        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    +1063        language: typing.Union[fireteams.FireteamLanguage, str],
    +1064        date_range: int = 0,
    +1065        page: int = 0,
    +1066        public_only: bool = False,
    +1067        slots_filter: int = 0,
    +1068    ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]:
    +1069        """Fetch a clan's fireteams with open slots.
    +1070
    +1071        .. note::
    +1072            This method requires OAuth2: ReadGroups scope.
    +1073
    +1074        Parameters
    +1075        ----------
    +1076        access_token : `str`
    +1077            The bearer access token associated with the bungie account.
    +1078        group_id : `int`
    +1079            The group/clan id of the fireteam.
    +1080        activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]`
    +1081            The fireteam activity type.
    +1082
    +1083        Other Parameters
    +1084        ----------------
    +1085        platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]`
    +1086            If this is provided. Then the results will be filtered with the given platform.
    +1087            Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms.
    +1088        language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]`
    +1089            A locale language to filter the used language in that fireteam.
    +1090            Defaults to `aiobungie.crates.FireteamLanguage.ALL`
    +1091        date_range : `int`
    +1092            An integer to filter the date range of the returned fireteams. Defaults to `0`.
    +1093        page : `int`
    +1094            The page number. By default its `0` which returns all available activities.
    +1095        public_only: `bool`
    +1096            If set to True, Then only public fireteams will be returned.
    +1097        slots_filter : `int`
    +1098            Filter the returned fireteams based on available slots. Default is `0`
    +1099
    +1100        Returns
    +1101        -------
    +1102        `typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]`
    +1103            A sequence of  fireteams found in the clan.
    +1104            `None` will be returned if nothing was found.
    +1105        """
    +1106        resp = await self.rest.fetch_avaliable_clan_fireteams(
    +1107            access_token,
    +1108            group_id,
    +1109            activity_type,
    +1110            platform=platform,
    +1111            language=language,
    +1112            date_range=date_range,
    +1113            page=page,
    +1114            public_only=public_only,
    +1115            slots_filter=slots_filter,
    +1116        )
    +1117
    +1118        return self.factory.deserialize_fireteams(resp)
    +1119
    +1120    async def fetch_clan_fireteam(
    +1121        self, access_token: str, fireteam_id: int, group_id: int
    +1122    ) -> fireteams.AvailableFireteam:
    +1123        """Fetch a specific clan fireteam.
    +1124
    +1125        .. note::
    +1126            This method requires OAuth2: ReadGroups scope.
    +1127
    +1128        Parameters
    +1129        ----------
    +1130        access_token : `str`
    +1131            The bearer access token associated with the bungie account.
    +1132        group_id : `int`
    +1133            The group/clan id to fetch the fireteam from.
    +1134        fireteam_id : `int`
    +1135            The fireteam id to fetch.
    +1136
    +1137        Returns
    +1138        -------
    +1139        `typing.Optional[aiobungie.crates.AvailableFireteam]`
    +1140            A sequence of available fireteams objects if exists. else `None` will be returned.
    +1141        """
    +1142        resp = await self.rest.fetch_clan_fireteam(access_token, fireteam_id, group_id)
    +1143
    +1144        return self.factory.deserialize_available_fireteams(
    +1145            resp, no_results=True
    +1146        )  # type: ignore[return-value]
    +1147
    +1148    async def fetch_my_clan_fireteams(
    +1149        self,
    +1150        access_token: str,
    +1151        group_id: int,
    +1152        *,
    +1153        include_closed: bool = True,
    +1154        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    +1155        language: typing.Union[fireteams.FireteamLanguage, str],
    +1156        filtered: bool = True,
    +1157        page: int = 0,
    +1158    ) -> collections.Sequence[fireteams.AvailableFireteam]:
    +1159        """A method that's similar to `fetch_fireteams` but requires OAuth2.
    +1160
    +1161        .. note::
    +1162            This method requires OAuth2: ReadGroups scope.
    +1163
    +1164        Parameters
    +1165        ----------
    +1166        access_token : str
    +1167            The bearer access token associated with the bungie account.
    +1168        group_id : int
    +1169            The group/clan id to fetch.
    +1170
    +1171        Other Parameters
    +1172        ----------------
    +1173        include_closed : bool
    +1174            If provided and set to True, It will also return closed fireteams.
    +1175            If provided and set to False, It will only return public fireteams. Default is True.
    +1176        platform : aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]
    +1177            If this is provided. Then the results will be filtered with the given platform.
    +1178            Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
    +1179        language : typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]
    +1180            A locale language to filter the used language in that fireteam.
    +1181            Defaults to aiobungie.crates.FireteamLanguage.ALL
    +1182        filtered : bool
    +1183            If set to True, it will filter by clan. Otherwise not. Default is True.
    +1184        page : int
    +1185            The page number. By default its 0 which returns all available activities.
    +1186
    +1187        Returns
    +1188        -------
    +1189        `collections.Sequence[aiobungie.crates.AvailableFireteam]`
    +1190            A sequence of available fireteams objects if exists. else `None` will be returned.
    +1191        """
    +1192        resp = await self.rest.fetch_my_clan_fireteams(
    +1193            access_token,
    +1194            group_id,
    +1195            include_closed=include_closed,
    +1196            platform=platform,
    +1197            language=language,
    +1198            filtered=filtered,
    +1199            page=page,
    +1200        )
    +1201
    +1202        return self.factory.deserialize_available_fireteams(resp)  # type: ignore[return-value]
    +1203
    +1204    # Friends and social.
    +1205
    +1206    async def fetch_friends(
    +1207        self, access_token: str, /
    +1208    ) -> collections.Sequence[friends.Friend]:
    +1209        """Fetch bungie friend list.
    +1210
    +1211        .. note::
    +1212            This requests OAuth2: ReadUserData scope.
    +1213
    +1214        Parameters
    +1215        -----------
    +1216        access_token : `str`
    +1217            The bearer access token associated with the bungie account.
    +1218
    +1219        Returns
    +1220        -------
    +1221        `collections.Sequence[aiobungie.crates.Friend]`
    +1222            A sequence of the friends associated with that access token.
    +1223        """
    +1224
    +1225        resp = await self.rest.fetch_friends(access_token)
    +1226
    +1227        return self.factory.deserialize_friends(resp)
    +1228
    +1229    async def fetch_friend_requests(
    +1230        self, access_token: str, /
    +1231    ) -> friends.FriendRequestView:
    +1232        """Fetch pending bungie friend requests queue.
    +1233
    +1234        .. note::
    +1235            This requests OAuth2: ReadUserData scope.
    +1236
    +1237        Parameters
    +1238        -----------
    +1239        access_token : `str`
    +1240            The bearer access token associated with the bungie account.
    +1241
    +1242        Returns
    +1243        -------
    +1244        `aiobungie.crates.FriendRequestView`
    +1245            A friend requests view of that associated access token.
    +1246        """
    +1247
    +1248        resp = await self.rest.fetch_friend_requests(access_token)
    +1249
    +1250        return self.factory.deserialize_friend_requests(resp)
    +1251
    +1252    # Applications and Developer portal.
    +1253
    +1254    async def fetch_application(self, appid: int, /) -> application.Application:
    +1255        """Fetch a Bungie application.
    +1256
    +1257        Parameters
    +1258        -----------
    +1259        appid: `int`
    +1260            The application id.
    +1261
    +1262        Returns
    +1263        --------
    +1264        `aiobungie.crates.Application`
    +1265            A Bungie application.
    +1266        """
    +1267        resp = await self.rest.fetch_application(appid)
    +1268
    +1269        return self.factory.deserialize_app(resp)
    +1270
    +1271    # Milestones
    +1272
    +1273    async def fetch_public_milestone_content(
    +1274        self, milestone_hash: int, /
    +1275    ) -> milestones.MilestoneContent:
    +1276        """Fetch the milestone content given its hash.
    +1277
    +1278        Parameters
    +1279        ----------
    +1280        milestone_hash : `int`
    +1281            The milestone hash.
    +1282
    +1283        Returns
    +1284        -------
    +1285        `aiobungie.crates.milestones.MilestoneContent`
    +1286            A milestone content object.
    +1287        """
    +1288        resp = await self.rest.fetch_public_milestone_content(milestone_hash)
    +1289
    +1290        return self.factory.deserialize_public_milestone_content(resp)
    +
    - class - Dungeon(builtins.int, aiobungie.Enum): - +

    Standard Bungie API client application.

    -
    - -
    165@typing.final
    -166class Dungeon(int, Enum):
    -167    """An Enum for all available Dungeon/Like missions in Destiny 2."""
    -168
    -169    NORMAL_PRESAGE = 2124066889
    -170    """Normal Presage"""
    -171
    -172    MASTER_PRESAGE = 4212753278
    -173    """Master Presage"""
    -174
    -175    HARBINGER = 1738383283
    -176    """Harbinger"""
    -177
    -178    PROPHECY = 4148187374
    -179    """Prophecy"""
    -180
    -181    MASTER_POH = 785700673
    -182    """Master Pit of Heresy?"""
    -183
    -184    LEGEND_POH = 785700678
    -185    """Legend Pit of Heresy?"""
    -186
    -187    POH = 1375089621
    -188    """Normal Pit of Heresy."""
    -189
    -190    SHATTERED = 2032534090
    -191    """Shattered Throne"""
    -192
    -193    GOA_LEGEND = 4078656646
    -194    """Grasp of Avarice legend."""
    -195
    -196    GOA_MASTER = 3774021532
    -197    """Grasp of Avarice master."""
    -
    +

    This client deserialize the REST JSON responses using aiobungie.Factory +and returns aiobungie.crates Python object implementations of the responses.

    +

    A aiobungie.RESTClient REST client can also be used alone for low-level concepts.

    -

    An Enum for all available Dungeon/Like missions in Destiny 2.

    -
    +
    Example
    +
    +
    import aiobungie
     
    -                            
    -
    - NORMAL_PRESAGE = <Dungeon.NORMAL_PRESAGE: 2124066889> +client = aiobungie.Client('...') - -
    - - -

    Normal Presage

    +async def main(): + async with client.rest: + user = await client.fetch_current_user_memberships('...') + print(user) +
    +
    Parameters
    - -
    -
    - MASTER_PRESAGE = <Dungeon.MASTER_PRESAGE: 4212753278> +
      +
    • token (str): +Your Bungie's API key or Token from the developer's portal.
    • +
    - -
    - - -

    Master Presage

    +
    Other Parameters
    + +
      +
    • rest_client (aiobungie.interfaces.RESTInterface | None): +An optional rest client instance you can pass. +If set to None then the client will use the default instance.
    • +
    • max_retries (int): +The max retries number to retry if the request hit a 5xx status code.
    • +
    • max_ratelimit_retries (int): +The max retries number to retry if the request hit a 429 status code. Defaults to 3.
    • +
    • client_secret (str | None): +An optional application client secret, +This is only needed if you're fetching OAuth2 tokens with this client.
    • +
    • client_id (int | None): +An optional application client id, +This is only needed if you're fetching OAuth2 tokens with this client.
    • +
    -
    -
    -
    - HARBINGER = <Dungeon.HARBINGER: 1738383283> +
    + +
    + + Client( token: str, /, client_secret: Optional[str] = None, client_id: Optional[int] = None, *, rest_client: Optional[aiobungie.interfaces.rest.RESTInterface] = None, max_retries: int = 4, max_ratelimit_retries: int = 3) + + -
    - - -

    Harbinger

    -
    + +
    107    def __init__(
    +108        self,
    +109        token: str,
    +110        /,
    +111        client_secret: typing.Optional[str] = None,
    +112        client_id: typing.Optional[int] = None,
    +113        *,
    +114        rest_client: typing.Optional[interfaces.RESTInterface] = None,
    +115        max_retries: int = 4,
    +116        max_ratelimit_retries: int = 3,
    +117    ) -> None:
    +118
    +119        self._client_secret = client_secret
    +120        self._client_id = client_id
    +121
    +122        self._rest = (
    +123            rest_client
    +124            if rest_client is not None
    +125            else rest_.RESTClient(
    +126                token,
    +127                client_secret,
    +128                client_id,
    +129                max_retries=max_retries,
    +130                max_ratelimit_retries=max_ratelimit_retries,
    +131            )
    +132        )
    +133
    +134        self._factory = factory_.Factory(self)
    +
    + +
    -
    +
    - PROPHECY = <Dungeon.PROPHECY: 4148187374> + factory: aiobungie.Factory
    - + -

    Prophecy

    +

    Returns the marshalling factory for the client.

    -
    +
    - MASTER_POH = <Dungeon.MASTER_POH: 785700673> + rest: aiobungie.interfaces.rest.RESTInterface
    - + -

    Master Pit of Heresy?

    +

    Returns the REST client for the this client.

    -
    +
    - LEGEND_POH = <Dungeon.LEGEND_POH: 785700678> + request: aiobungie.Client
    - + -

    Legend Pit of Heresy?

    +

    A readonly ClientApp instance used for external requests.

    -
    +
    - POH = <Dungeon.POH: 1375089621> + metadata: collections.abc.MutableMapping[typing.Any, typing.Any]
    - + -

    Normal Pit of Heresy.

    +

    A mutable mapping storage for the user's needs.

    -
    -
    - SHATTERED = <Dungeon.SHATTERED: 2032534090> +
    + +
    + + def + run( self, future: collections.abc.Coroutine[typing.Any, None, None], debug: bool = False) -> None: + + -
    - - -

    Shattered Throne

    -
    + +
    152    def run(
    +153        self, future: collections.Coroutine[typing.Any, None, None], debug: bool = False
    +154    ) -> None:
    +155        loop: typing.Final[asyncio.AbstractEventLoop] = helpers.get_or_make_loop()
    +156        try:
    +157            if not loop.is_running():
    +158                loop.set_debug(debug)
    +159                loop.run_until_complete(future)
    +160
    +161        except Exception as exc:
    +162            raise RuntimeError(f"Failed to run {future.__qualname__}") from exc
    +163
    +164        except KeyboardInterrupt:
    +165            _LOG.warn("Unexpected Keyboard interrupt. Exiting.")
    +166            return
    +
    -
    -
    -
    - GOA_LEGEND = <Dungeon.GOA_LEGEND: 4078656646> +

    Runs a coroutine function until its complete.

    - -
    - - -

    Grasp of Avarice legend.

    -
    +

    This is equivalent to asyncio.get_event_loop().run_until_complete(...)

    +
    Parameters
    -
    -
    -
    - GOA_MASTER = <Dungeon.GOA_MASTER: 3774021532> +
      +
    • future (collections.Coroutine[None, None, None]): +A coroutine object.
    • +
    • debug (bool): +Either to enable asyncio debug or not. Disabled by default.
    • +
    - -
    - - -

    Grasp of Avarice master.

    +
    Example
    + +
    +
    async def main() -> None:
    +    await fetch(...)
    +
    +# Run the coroutine.
    +client.run(main())
    +
    +
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    +
    + +
    + + async def + fetch_current_user_memberships(self, access_token: str, /) -> aiobungie.crates.user.User: -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    + + +
    + +
    170    async def fetch_current_user_memberships(self, access_token: str, /) -> user.User:
    +171        """Fetch and return a user object of the bungie net user associated with account.
    +172
    +173        .. warning::
    +174            This method requires OAuth2 scope and a Bearer access token.
    +175
    +176        Parameters
    +177        ----------
    +178        access_token : `str`
    +179            A valid Bearer access token for the authorization.
    +180
    +181        Returns
    +182        -------
    +183        `aiobungie.crates.user.User`
    +184            A user object includes the Destiny memberships and Bungie.net user.
    +185        """
    +186        resp = await self.rest.fetch_current_user_memberships(access_token)
    +187
    +188        return self.factory.deserialize_user(resp)
    +
    -
    -
    -
    -
    -
    - -
    - - class - Enum(enum.Enum): - +

    Fetch and return a user object of the bungie net user associated with account.

    -
    - -
    77class Enum(__enum.Enum):
    -78    """Builtin Python enum with extra handlings."""
    -79
    -80    @property
    -81    def name(self) -> str:  # type: ignore[override]
    -82        return self._name_
    -83
    -84    @property
    -85    def value(self) -> typing.Any:  # type: ignore[override]
    -86        return self._value_
    -87
    -88    def __str__(self) -> str:
    -89        return self._name_
    -90
    -91    def __repr__(self) -> str:
    -92        return f"<{type(self).__name__}.{self._name_}: {self._value_!s}>"
    -93
    -94    def __int__(self) -> int:
    -95        if isinstance(self.value, _ITERABLE):
    -96            raise TypeError(
    -97                f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.",
    -98            )
    -99        return int(self.value)
    -
    +
    +

    This method requires OAuth2 scope and a Bearer access token.

    -

    Builtin Python enum with extra handlings.

    +
    Parameters
    -
    -
    - name: str +
      +
    • access_token (str): +A valid Bearer access token for the authorization.
    • +
    - -
    - - - +
    Returns
    -
    -
    -
    - value: Any +
      +
    • aiobungie.crates.user.User: A user object includes the Destiny memberships and Bungie.net user.
    • +
    +
    - -
    - - -
    -
    -
    - -
    +
    + +
    - class - Factory(aiobungie.interfaces.factory.FactoryInterface): + async def + fetch_bungie_user(self, id: int, /) -> aiobungie.crates.user.BungieUser: - +
    - -
      61class Factory(interfaces.FactoryInterface):
    -  62    """The base deserialization factory class for all aiobungie objects.
    -  63
    -  64    Highly inspired hikari entity factory used to deserialize JSON responses from the REST client and turning them
    -  65    into a `aiobungie.crates` Python classes.
    -  66    """
    -  67
    -  68    __slots__ = ("_net",)
    -  69
    -  70    def __init__(self, net: traits.Netrunner) -> None:
    -  71        self._net = net
    -  72
    -  73    def deserialize_bungie_user(self, data: typedefs.JSONObject) -> user.BungieUser:
    -  74        return user.BungieUser(
    -  75            id=int(data["membershipId"]),
    -  76            created_at=time.clean_date(data["firstAccess"]),
    -  77            name=data.get("cachedBungieGlobalDisplayName", undefined.Undefined),
    -  78            is_deleted=data["isDeleted"],
    -  79            about=data["about"],
    -  80            updated_at=time.clean_date(data["lastUpdate"]),
    -  81            psn_name=data.get("psnDisplayName", None),
    -  82            stadia_name=data.get("stadiaDisplayName", None),
    -  83            steam_name=data.get("steamDisplayName", None),
    -  84            twitch_name=data.get("twitchDisplayName", None),
    -  85            blizzard_name=data.get("blizzardDisplayName", None),
    -  86            status=data["statusText"],
    -  87            locale=data["locale"],
    -  88            picture=assets.Image(path=str(data["profilePicturePath"])),
    -  89            code=data.get("cachedBungieGlobalDisplayNameCode", None),
    -  90            unique_name=data.get("uniqueName", None),
    -  91            theme_id=int(data["profileTheme"]),
    -  92            show_activity=bool(data["showActivity"]),
    -  93            theme_name=data["profileThemeName"],
    -  94            display_title=data["userTitleDisplay"],
    -  95        )
    -  96
    -  97    def deserialize_partial_bungie_user(
    -  98        self, payload: typedefs.JSONObject
    -  99    ) -> user.PartialBungieUser:
    - 100        return user.PartialBungieUser(
    - 101            net=self._net,
    - 102            types=[
    - 103                enums.MembershipType(type_)
    - 104                for type_ in payload.get("applicableMembershipTypes", [])
    - 105            ],
    - 106            name=payload.get("displayName", undefined.Undefined),
    - 107            id=int(payload["membershipId"]),
    - 108            crossave_override=enums.MembershipType(payload["crossSaveOverride"]),
    - 109            is_public=payload["isPublic"],
    - 110            icon=assets.Image(payload.get("iconPath", "")),
    - 111            type=enums.MembershipType(payload["membershipType"]),
    - 112        )
    - 113
    - 114    def deserialize_destiny_membership(
    - 115        self, payload: typedefs.JSONObject
    - 116    ) -> user.DestinyMembership:
    - 117        name: undefined.UndefinedOr[str] = undefined.Undefined
    - 118        if (
    - 119            raw_name := payload.get("bungieGlobalDisplayName", "")
    - 120        ) and not typedefs.is_unknown(raw_name):
    - 121            name = raw_name
    - 122
    - 123        return user.DestinyMembership(
    - 124            net=self._net,
    - 125            id=int(payload["membershipId"]),
    - 126            name=name,
    - 127            code=payload.get("bungieGlobalDisplayNameCode", None),
    - 128            last_seen_name=payload.get("LastSeenDisplayName")
    - 129            or payload.get("displayName")  # noqa: W503
    - 130            or "",  # noqa: W503
    - 131            type=enums.MembershipType(payload["membershipType"]),
    - 132            is_public=payload["isPublic"],
    - 133            crossave_override=enums.MembershipType(payload["crossSaveOverride"]),
    - 134            icon=assets.Image(payload.get("iconPath", "")),
    - 135            types=[
    - 136                enums.MembershipType(type_)
    - 137                for type_ in payload.get("applicableMembershipTypes", [])
    - 138            ],
    - 139        )
    - 140
    - 141    def deserialize_destiny_memberships(
    - 142        self, data: typedefs.JSONArray
    - 143    ) -> collections.Sequence[user.DestinyMembership]:
    - 144        return [self.deserialize_destiny_membership(membership) for membership in data]
    - 145
    - 146    def deserialize_user(self, data: typedefs.JSONObject) -> user.User:
    - 147
    - 148        primary_membership_id: typing.Optional[int] = None
    - 149        if raw_primary_id := data.get("primaryMembershipId"):
    - 150            primary_membership_id = int(raw_primary_id)
    - 151
    - 152        return user.User(
    - 153            bungie=self.deserialize_bungie_user(data["bungieNetUser"]),
    - 154            destiny=self.deserialize_destiny_memberships(data["destinyMemberships"]),
    - 155            primary_membership_id=primary_membership_id,
    - 156        )
    - 157
    - 158    def deserialize_searched_user(
    - 159        self, payload: typedefs.JSONObject
    - 160    ) -> user.SearchableDestinyUser:
    - 161        name: undefined.UndefinedOr[str] = undefined.Undefined
    - 162        if (raw_name := payload["bungieGlobalDisplayName"]) and not typedefs.is_unknown(
    - 163            raw_name
    - 164        ):
    - 165            name = raw_name
    - 166
    - 167        code: typing.Optional[int] = None
    - 168        if raw_code := payload.get("bungieGlobalDisplayNameCode"):
    - 169            code = int(raw_code)
    - 170
    - 171        bungie_id: typing.Optional[int] = None
    - 172        if raw_bungie_id := payload.get("bungieNetMembershipId"):
    - 173            bungie_id = int(raw_bungie_id)
    - 174
    - 175        return user.SearchableDestinyUser(
    - 176            name=name,
    - 177            code=code,
    - 178            bungie_id=bungie_id,
    - 179            memberships=self.deserialize_destiny_memberships(
    - 180                payload["destinyMemberships"]
    - 181            ),
    - 182        )
    - 183
    - 184    def deserialize_user_credentials(
    - 185        self, payload: typedefs.JSONArray
    - 186    ) -> collections.Sequence[user.UserCredentials]:
    - 187        return [
    - 188            user.UserCredentials(
    - 189                type=enums.CredentialType(int(creds["credentialType"])),
    - 190                display_name=creds["credentialDisplayName"],
    - 191                is_public=creds["isPublic"],
    - 192                self_as_string=creds.get("credentialAsString", undefined.Undefined),
    - 193            )
    - 194            for creds in payload
    - 195        ]
    - 196
    - 197    @staticmethod
    - 198    def set_themese_attrs(
    - 199        payload: typedefs.JSONArray, /
    - 200    ) -> typing.Collection[user.UserThemes]:
    - 201        return [
    - 202            user.UserThemes(
    - 203                id=int(entry["userThemeId"]),
    - 204                name=entry["userThemeName"]
    - 205                if "userThemeName" in entry
    - 206                else undefined.Undefined,
    - 207                description=entry["userThemeDescription"]
    - 208                if "userThemeDescription" in entry
    - 209                else undefined.Undefined,
    - 210            )
    - 211            for entry in payload
    - 212        ]
    - 213
    - 214    def deserialize_user_themes(
    - 215        self, payload: typedefs.JSONArray
    - 216    ) -> collections.Sequence[user.UserThemes]:
    - 217        return list(self.set_themese_attrs(payload))
    - 218
    - 219    def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan:
    - 220
    - 221        # This is kinda redundant
    - 222        data = payload
    - 223
    - 224        # This is always outside the details.
    - 225        current_user_map: typing.Optional[
    - 226            collections.Mapping[str, clans.ClanMember]
    - 227        ] = None
    - 228        if raw_current_user_map := payload.get("currentUserMemberMap"):
    - 229            current_user_map = {
    - 230                membership_type: self.deserialize_clan_member(membership)
    - 231                for membership_type, membership in raw_current_user_map.items()
    - 232            }
    - 233
    - 234        try:
    - 235            data = payload["detail"]
    - 236        except KeyError:
    - 237            pass
    - 238
    - 239        id = data["groupId"]
    - 240        name = data["name"]
    - 241        created_at = data["creationDate"]
    - 242        member_count = data["memberCount"]
    - 243        about = data["about"]
    - 244        motto = data["motto"]
    - 245        is_public = data["isPublic"]
    - 246        banner = assets.Image(str(data["bannerPath"]))
    - 247        avatar = assets.Image(str(data["avatarPath"]))
    - 248        tags = data["tags"]
    - 249        type = data["groupType"]
    - 250
    - 251        features = data["features"]
    - 252        features_obj = clans.ClanFeatures(
    - 253            max_members=features["maximumMembers"],
    - 254            max_membership_types=features["maximumMembershipsOfGroupType"],
    - 255            capabilities=features["capabilities"],
    - 256            membership_types=features["membershipTypes"],
    - 257            invite_permissions=features["invitePermissionOverride"],
    - 258            update_banner_permissions=features["updateBannerPermissionOverride"],
    - 259            update_culture_permissions=features["updateCulturePermissionOverride"],
    - 260            join_level=features["joinLevel"],
    - 261        )
    - 262
    - 263        information: typedefs.JSONObject = data["clanInfo"]
    - 264        progression: collections.Mapping[int, progressions.Progression] = {
    - 265            int(prog_hash): self.deserialize_progressions(prog)
    - 266            for prog_hash, prog in information["d2ClanProgressions"].items()
    - 267        }
    - 268
    - 269        founder: typedefs.NoneOr[clans.ClanMember] = None
    - 270        if raw_founder := payload.get("founder"):
    - 271            founder = self.deserialize_clan_member(raw_founder)
    - 272
    - 273        return clans.Clan(
    - 274            net=self._net,
    - 275            id=int(id),
    - 276            name=name,
    - 277            type=enums.GroupType(type),
    - 278            created_at=time.clean_date(created_at),
    - 279            member_count=member_count,
    - 280            motto=motto,
    - 281            about=about,
    - 282            is_public=is_public,
    - 283            banner=banner,
    - 284            avatar=avatar,
    - 285            tags=tags,
    - 286            features=features_obj,
    - 287            owner=founder,
    - 288            progressions=progression,
    - 289            call_sign=information["clanCallsign"],
    - 290            banner_data=information["clanBannerData"],
    - 291            chat_security=data["chatSecurity"],
    - 292            conversation_id=int(data["conversationId"]),
    - 293            allow_chat=data["allowChat"],
    - 294            theme=data["theme"],
    - 295            current_user_membership=current_user_map,
    - 296        )
    - 297
    - 298    def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember:
    - 299        destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"])
    - 300        return clans.ClanMember(
    - 301            net=self._net,
    - 302            last_seen_name=destiny_user.last_seen_name,
    - 303            id=destiny_user.id,
    - 304            name=destiny_user.name,
    - 305            icon=destiny_user.icon,
    - 306            last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])),
    - 307            group_id=int(data["groupId"]),
    - 308            joined_at=time.clean_date(data["joinDate"]),
    - 309            types=destiny_user.types,
    - 310            is_public=destiny_user.is_public,
    - 311            type=destiny_user.type,
    - 312            code=destiny_user.code,
    - 313            is_online=data["isOnline"],
    - 314            crossave_override=destiny_user.crossave_override,
    - 315            bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"])
    - 316            if "bungieNetUserInfo" in data
    - 317            else None,
    - 318            member_type=enums.ClanMemberType(int(data["memberType"])),
    - 319        )
    - 320
    - 321    def deserialize_clan_members(
    - 322        self, data: typedefs.JSONObject, /
    - 323    ) -> iterators.FlatIterator[clans.ClanMember]:
    - 324        return iterators.FlatIterator(
    - 325            [self.deserialize_clan_member(member) for member in data["results"]]
    - 326        )
    - 327
    - 328    def deserialize_group_member(
    - 329        self, payload: typedefs.JSONObject
    - 330    ) -> clans.GroupMember:
    - 331        member = payload["member"]
    - 332        return clans.GroupMember(
    - 333            net=self._net,
    - 334            join_date=time.clean_date(member["joinDate"]),
    - 335            group_id=int(member["groupId"]),
    - 336            member_type=enums.ClanMemberType(member["memberType"]),
    - 337            is_online=member["isOnline"],
    - 338            last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])),
    - 339            inactive_memberships=payload.get("areAllMembershipsInactive", None),
    - 340            member=self.deserialize_destiny_membership(member["destinyUserInfo"]),
    - 341            group=self.deserialize_clan(payload["group"]),
    - 342        )
    - 343
    - 344    def _deserialize_clan_conversation(
    - 345        self, payload: typedefs.JSONObject
    - 346    ) -> clans.ClanConversation:
    - 347        return clans.ClanConversation(
    - 348            net=self._net,
    - 349            id=int(payload["conversationId"]),
    - 350            group_id=int(payload["groupId"]),
    - 351            name=(
    - 352                payload["chatName"]
    - 353                if not typedefs.is_unknown(payload["chatName"])
    - 354                else undefined.Undefined
    - 355            ),
    - 356            chat_enabled=payload["chatEnabled"],
    - 357            security=payload["chatSecurity"],
    - 358        )
    - 359
    - 360    def deserialize_clan_conversations(
    - 361        self, payload: typedefs.JSONArray
    - 362    ) -> collections.Sequence[clans.ClanConversation]:
    - 363        return [self._deserialize_clan_conversation(conv) for conv in payload]
    - 364
    - 365    def deserialize_app_owner(
    - 366        self, payload: typedefs.JSONObject
    - 367    ) -> application.ApplicationOwner:
    - 368        return application.ApplicationOwner(
    - 369            net=self._net,
    - 370            name=payload.get("bungieGlobalDisplayName", undefined.Undefined),
    - 371            id=int(payload["membershipId"]),
    - 372            type=enums.MembershipType(payload["membershipType"]),
    - 373            icon=assets.Image(str(payload["iconPath"])),
    - 374            is_public=payload["isPublic"],
    - 375            code=payload.get("bungieGlobalDisplayNameCode", None),
    - 376        )
    - 377
    - 378    def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application:
    - 379        return application.Application(
    - 380            id=int(payload["applicationId"]),
    - 381            name=payload["name"],
    - 382            link=payload["link"],
    - 383            status=payload["status"],
    - 384            redirect_url=payload.get("redirectUrl", None),
    - 385            created_at=time.clean_date(str(payload["creationDate"])),
    - 386            published_at=time.clean_date(str(payload["firstPublished"])),
    - 387            owner=self.deserialize_app_owner(payload["team"][0]["user"]),  # type: ignore
    - 388            scope=payload.get("scope", undefined.Undefined),
    - 389        )
    - 390
    - 391    def _set_character_attrs(self, payload: typedefs.JSONObject) -> character.Character:
    - 392        total_time = time.format_played(int(payload["minutesPlayedTotal"]), suffix=True)
    - 393        return character.Character(
    - 394            net=self._net,
    - 395            id=int(payload["characterId"]),
    - 396            gender=enums.Gender(payload["genderType"]),
    - 397            race=enums.Race(payload["raceType"]),
    - 398            class_type=enums.Class(payload["classType"]),
    - 399            emblem=assets.Image(str(payload["emblemBackgroundPath"])),
    - 400            emblem_icon=assets.Image(str(payload["emblemPath"])),
    - 401            emblem_hash=int(payload["emblemHash"]),
    - 402            last_played=time.clean_date(payload["dateLastPlayed"]),
    - 403            total_played_time=total_time,
    - 404            member_id=int(payload["membershipId"]),
    - 405            member_type=enums.MembershipType(payload["membershipType"]),
    - 406            level=payload["baseCharacterLevel"],
    - 407            title_hash=payload.get("titleRecordHash", None),
    - 408            light=payload["light"],
    - 409            stats={enums.Stat(int(k)): v for k, v in payload["stats"].items()},
    - 410        )
    - 411
    - 412    def deserialize_profile(
    - 413        self, payload: typedefs.JSONObject, /
    - 414    ) -> typing.Optional[profile.Profile]:
    - 415        if (raw_profile := payload.get("data")) is None:
    - 416            return None
    - 417
    - 418        payload = raw_profile
    - 419        id = int(payload["userInfo"]["membershipId"])
    - 420        name = payload["userInfo"]["displayName"]
    - 421        is_public = payload["userInfo"]["isPublic"]
    - 422        type = enums.MembershipType(payload["userInfo"]["membershipType"])
    - 423        last_played = time.clean_date(str(payload["dateLastPlayed"]))
    - 424        character_ids = [int(cid) for cid in payload["characterIds"]]
    - 425        power_cap = payload["currentSeasonRewardPowerCap"]
    - 426
    - 427        return profile.Profile(
    - 428            id=int(id),
    - 429            name=name,
    - 430            is_public=is_public,
    - 431            type=type,
    - 432            last_played=last_played,
    - 433            character_ids=character_ids,
    - 434            power_cap=power_cap,
    - 435            net=self._net,
    - 436        )
    - 437
    - 438    def deserialize_profile_item(
    - 439        self, payload: typedefs.JSONObject
    - 440    ) -> profile.ProfileItemImpl:
    - 441
    - 442        instance_id: typing.Optional[int] = None
    - 443        if raw_instance_id := payload.get("itemInstanceId"):
    - 444            instance_id = int(raw_instance_id)
    - 445
    - 446        version_number: typing.Optional[int] = None
    - 447        if raw_version := payload.get("versionNumber"):
    - 448            version_number = int(raw_version)
    - 449
    - 450        transfer_status = enums.TransferStatus(payload["transferStatus"])
    - 451
    - 452        return profile.ProfileItemImpl(
    - 453            net=self._net,
    - 454            hash=payload["itemHash"],
    - 455            quantity=payload["quantity"],
    - 456            bind_status=enums.ItemBindStatus(payload["bindStatus"]),
    - 457            location=enums.ItemLocation(payload["location"]),
    - 458            bucket=payload["bucketHash"],
    - 459            transfer_status=transfer_status,
    - 460            lockable=payload["lockable"],
    - 461            state=enums.ItemState(payload["state"]),
    - 462            dismantel_permissions=payload["dismantlePermission"],
    - 463            is_wrapper=payload["isWrapper"],
    - 464            instance_id=instance_id,
    - 465            version_number=version_number,
    - 466            ornament_id=payload.get("overrideStyleItemHash"),
    - 467        )
    - 468
    - 469    def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective:
    - 470        return records.Objective(
    - 471            net=self._net,
    - 472            hash=payload["objectiveHash"],
    - 473            visible=payload["visible"],
    - 474            complete=payload["complete"],
    - 475            completion_value=payload["completionValue"],
    - 476            progress=payload.get("progress"),
    - 477            destination_hash=payload.get("destinationHash"),
    - 478            activity_hash=payload.get("activityHash"),
    - 479        )
    - 480
    - 481    def deserialize_records(
    - 482        self,
    - 483        payload: typedefs.JSONObject,
    - 484        scores: typing.Optional[records.RecordScores] = None,
    - 485        **nodes: int,
    - 486    ) -> records.Record:
    - 487        objectives: typing.Optional[list[records.Objective]] = None
    - 488        interval_objectives: typing.Optional[list[records.Objective]] = None
    - 489        record_state: typedefs.IntAnd[records.RecordState]
    - 490
    - 491        record_state = records.RecordState(payload["state"])
    - 492
    - 493        if raw_objs := payload.get("objectives"):
    - 494            objectives = [self.deserialize_objectives(obj) for obj in raw_objs]
    - 495
    - 496        if raw_interval_objs := payload.get("intervalObjectives"):
    - 497            interval_objectives = [
    - 498                self.deserialize_objectives(obj) for obj in raw_interval_objs
    - 499            ]
    - 500
    - 501        return records.Record(
    - 502            scores=scores,
    - 503            categories_node_hash=nodes.get("categories_hash", undefined.Undefined),
    - 504            seals_node_hash=nodes.get("seals_hash", undefined.Undefined),
    - 505            state=record_state,
    - 506            objectives=objectives,
    - 507            interval_objectives=interval_objectives,
    - 508            redeemed_count=payload.get("intervalsRedeemedCount", 0),
    - 509            completion_times=payload.get("completedCount", None),
    - 510            reward_visibility=payload.get("rewardVisibilty", None),
    - 511        )
    - 512
    - 513    def deserialize_character_records(
    - 514        self,
    - 515        payload: typedefs.JSONObject,
    - 516        scores: typing.Optional[records.RecordScores] = None,
    - 517        record_hashes: typing.Optional[list[int]] = None,
    - 518    ) -> records.CharacterRecord:
    - 519
    - 520        record = self.deserialize_records(payload, scores)
    - 521        return records.CharacterRecord(
    - 522            scores=scores,
    - 523            categories_node_hash=record.categories_node_hash,
    - 524            seals_node_hash=record.seals_node_hash,
    - 525            state=record.state,
    - 526            objectives=record.objectives,
    - 527            interval_objectives=record.interval_objectives,
    - 528            redeemed_count=payload.get("intervalsRedeemedCount", 0),
    - 529            completion_times=payload.get("completedCount"),
    - 530            reward_visibility=payload.get("rewardVisibilty"),
    - 531            record_hashes=record_hashes or [],
    - 532        )
    - 533
    - 534    def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye:
    - 535        return character.Dye(
    - 536            channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"]
    - 537        )
    - 538
    - 539    def deserialize_character_customization(
    - 540        self, payload: typedefs.JSONObject
    - 541    ) -> character.CustomizationOptions:
    - 542        return character.CustomizationOptions(
    - 543            personality=payload["personality"],
    - 544            face=payload["face"],
    - 545            skin_color=payload["skinColor"],
    - 546            lip_color=payload["lipColor"],
    - 547            eye_color=payload["eyeColor"],
    - 548            hair_colors=payload.get("hairColors", []),
    - 549            feature_colors=payload.get("featureColors", []),
    - 550            decal_color=payload["decalColor"],
    - 551            wear_helmet=payload["wearHelmet"],
    - 552            hair_index=payload["hairIndex"],
    - 553            feature_index=payload["featureIndex"],
    - 554            decal_index=payload["decalIndex"],
    - 555        )
    - 556
    - 557    def deserialize_character_minimal_equipments(
    - 558        self, payload: typedefs.JSONObject
    - 559    ) -> character.MinimalEquipments:
    - 560        dyes = None
    - 561        if raw_dyes := payload.get("dyes"):
    - 562            if raw_dyes:
    - 563                dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes]
    - 564        return character.MinimalEquipments(
    - 565            net=self._net, item_hash=payload["itemHash"], dyes=dyes
    - 566        )
    - 567
    - 568    def deserialize_character_render_data(
    - 569        self, payload: typedefs.JSONObject, /
    - 570    ) -> character.RenderedData:
    - 571        return character.RenderedData(
    - 572            net=self._net,
    - 573            customization=self.deserialize_character_customization(
    - 574                payload["customization"]
    - 575            ),
    - 576            custom_dyes=[
    - 577                self.deserialize_character_dye(dye)
    - 578                for dye in payload["customDyes"]
    - 579                if dye
    - 580            ],
    - 581            equipment=[
    - 582                self.deserialize_character_minimal_equipments(equipment)
    - 583                for equipment in payload["peerView"]["equipment"]
    - 584            ],
    - 585        )
    - 586
    - 587    def deserialize_available_activity(
    - 588        self, payload: typedefs.JSONObject
    - 589    ) -> activity.AvailableActivity:
    - 590        return activity.AvailableActivity(
    - 591            hash=payload["activityHash"],
    - 592            is_new=payload["isNew"],
    - 593            is_completed=payload["isCompleted"],
    - 594            is_visible=payload["isVisible"],
    - 595            display_level=payload.get("displayLevel"),
    - 596            recommended_light=payload.get("recommendedLight"),
    - 597            difficulty=activity.Difficulty(payload["difficultyTier"]),
    - 598            can_join=payload["canJoin"],
    - 599            can_lead=payload["canLead"],
    - 600        )
    - 601
    - 602    def deserialize_character_activity(
    - 603        self, payload: typedefs.JSONObject
    - 604    ) -> activity.CharacterActivity:
    - 605        current_mode: typing.Optional[enums.GameMode] = None
    - 606        if raw_current_mode := payload.get("currentActivityModeType"):
    - 607            current_mode = enums.GameMode(raw_current_mode)
    - 608
    - 609        current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None
    - 610        if raw_current_modes := payload.get("currentActivityModeTypes"):
    - 611            current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes]
    - 612
    - 613        return activity.CharacterActivity(
    - 614            date_started=time.clean_date(payload["dateActivityStarted"]),
    - 615            current_hash=payload["currentActivityHash"],
    - 616            current_mode_hash=payload["currentActivityModeHash"],
    - 617            current_mode=current_mode,
    - 618            current_mode_hashes=payload.get("currentActivityModeHashes"),
    - 619            current_mode_types=current_mode_types,
    - 620            current_playlist_hash=payload.get("currentPlaylistActivityHash"),
    - 621            last_story_hash=payload["lastCompletedStoryHash"],
    - 622            available_activities=[
    - 623                self.deserialize_available_activity(activity_)
    - 624                for activity_ in payload["availableActivities"]
    - 625            ],
    - 626        )
    - 627
    - 628    def deserialize_profile_items(
    - 629        self, payload: typedefs.JSONObject, /
    - 630    ) -> list[profile.ProfileItemImpl]:
    - 631        return [self.deserialize_profile_item(item) for item in payload["items"]]
    - 632
    - 633    def _deserialize_node(self, payload: typedefs.JSONObject) -> records.Node:
    - 634        return records.Node(
    - 635            state=int(payload["state"]),
    - 636            objective=self.deserialize_objectives(payload["objective"])
    - 637            if "objective" in payload
    - 638            else None,
    - 639            progress_value=int(payload["progressValue"]),
    - 640            completion_value=int(payload["completionValue"]),
    - 641            record_category_score=int(payload["recordCategoryScore"])
    - 642            if "recordCategoryScore" in payload
    - 643            else None,
    - 644        )
    - 645
    - 646    @staticmethod
    - 647    def _deserialize_collectible(payload: typedefs.JSONObject) -> items.Collectible:
    - 648        recent_collectibles: typing.Optional[collections.Collection[int]] = None
    - 649        if raw_recent_collectibles := payload.get("recentCollectibleHashes"):
    - 650            recent_collectibles = [
    - 651                int(item_hash) for item_hash in raw_recent_collectibles
    - 652            ]
    - 653
    - 654        collectibles: dict[int, int] = {}
    - 655        for item_hash, mapping in payload["collectibles"].items():
    - 656            collectibles[int(item_hash)] = int(mapping["state"])
    - 657
    - 658        return items.Collectible(
    - 659            recent_collectibles=recent_collectibles,
    - 660            collectibles=collectibles,
    - 661            collection_categorie_hash=int(payload["collectionCategoriesRootNodeHash"]),
    - 662            collection_badges_hash=int(payload["collectionBadgesRootNodeHash"]),
    - 663        )
    - 664
    - 665    @staticmethod
    - 666    def _deserialize_currencies(
    - 667        payload: typedefs.JSONObject,
    - 668    ) -> collections.Sequence[items.Currency]:
    - 669        return [
    - 670            items.Currency(hash=int(item_hash), amount=int(amount))
    - 671            for item_hash, amount in payload["itemQuantities"].items()
    - 672        ]
    - 673
    - 674    def deserialize_progressions(
    - 675        self, payload: typedefs.JSONObject
    - 676    ) -> progressions.Progression:
    - 677        return progressions.Progression(
    - 678            hash=int(payload["progressionHash"]),
    - 679            level=int(payload["level"]),
    - 680            cap=int(payload["levelCap"]),
    - 681            daily_limit=int(payload["dailyLimit"]),
    - 682            weekly_limit=int(payload["weeklyLimit"]),
    - 683            current_progress=int(payload["currentProgress"]),
    - 684            daily_progress=int(payload["dailyProgress"]),
    - 685            needed=int(payload["progressToNextLevel"]),
    - 686            next_level=int(payload["nextLevelAt"]),
    - 687        )
    - 688
    - 689    def _deserialize_factions(
    - 690        self, payload: typedefs.JSONObject
    - 691    ) -> progressions.Factions:
    - 692        progs = self.deserialize_progressions(payload)
    - 693        return progressions.Factions(
    - 694            hash=progs.hash,
    - 695            level=progs.level,
    - 696            cap=progs.cap,
    - 697            daily_limit=progs.daily_limit,
    - 698            weekly_limit=progs.weekly_limit,
    - 699            current_progress=progs.current_progress,
    - 700            daily_progress=progs.daily_progress,
    - 701            needed=progs.needed,
    - 702            next_level=progs.next_level,
    - 703            faction_hash=payload["factionHash"],
    - 704            faction_vendor_hash=payload["factionVendorIndex"],
    - 705        )
    - 706
    - 707    def _deserialize_milestone_available_quest(
    - 708        self, payload: typedefs.JSONObject
    - 709    ) -> milestones.MilestoneQuest:
    - 710        return milestones.MilestoneQuest(
    - 711            item_hash=payload["questItemHash"],
    - 712            status=self._deserialize_milestone_quest_status(payload["status"]),
    - 713        )
    - 714
    - 715    def _deserialize_milestone_activity(
    - 716        self, payload: typedefs.JSONObject
    - 717    ) -> milestones.MilestoneActivity:
    - 718
    - 719        phases: typing.Optional[
    - 720            collections.Sequence[milestones.MilestoneActivityPhase]
    - 721        ] = None
    - 722        if raw_phases := payload.get("phases"):
    - 723            phases = [
    - 724                milestones.MilestoneActivityPhase(
    - 725                    is_completed=obj["complete"], hash=obj["phaseHash"]
    - 726                )
    - 727                for obj in raw_phases
    - 728            ]
    - 729
    - 730        return milestones.MilestoneActivity(
    - 731            hash=payload["activityHash"],
    - 732            challenges=[
    - 733                self.deserialize_objectives(obj["objective"])
    - 734                for obj in payload["challenges"]
    - 735            ],
    - 736            modifier_hashes=payload.get("modifierHashes"),
    - 737            boolean_options=payload.get("booleanActivityOptions"),
    - 738            phases=phases,
    - 739        )
    - 740
    - 741    def _deserialize_milestone_quest_status(
    - 742        self, payload: typedefs.JSONObject
    - 743    ) -> milestones.QuestStatus:
    - 744        return milestones.QuestStatus(
    - 745            net=self._net,
    - 746            quest_hash=payload["questHash"],
    - 747            step_hash=payload["stepHash"],
    - 748            step_objectives=[
    - 749                self.deserialize_objectives(objective)
    - 750                for objective in payload["stepObjectives"]
    - 751            ],
    - 752            is_tracked=payload["tracked"],
    - 753            is_completed=payload["completed"],
    - 754            started=payload["started"],
    - 755            item_instance_id=payload["itemInstanceId"],
    - 756            vendor_hash=payload.get("vendorHash"),
    - 757            is_redeemed=payload["redeemed"],
    - 758        )
    - 759
    - 760    def _deserialize_milestone_rewards(
    - 761        self, payload: typedefs.JSONObject
    - 762    ) -> milestones.MilestoneReward:
    - 763        return milestones.MilestoneReward(
    - 764            category_hash=payload["rewardCategoryHash"],
    - 765            entries=[
    - 766                milestones.MilestoneRewardEntry(
    - 767                    entry_hash=entry["rewardEntryHash"],
    - 768                    is_earned=entry["earned"],
    - 769                    is_redeemed=entry["redeemed"],
    - 770                )
    - 771                for entry in payload["entries"]
    - 772            ],
    - 773        )
    - 774
    - 775    def deserialize_milestone(
    - 776        self, payload: typedefs.JSONObject
    - 777    ) -> milestones.Milestone:
    - 778        start_date: typing.Optional[datetime.datetime] = None
    - 779        if raw_start_date := payload.get("startDate"):
    - 780            start_date = time.clean_date(raw_start_date)
    - 781
    - 782        end_date: typing.Optional[datetime.datetime] = None
    - 783        if raw_end_date := payload.get("endDate"):
    - 784            end_date = time.clean_date(raw_end_date)
    - 785
    - 786        rewards: typing.Optional[
    - 787            collections.Collection[milestones.MilestoneReward]
    - 788        ] = None
    - 789        if raw_rewards := payload.get("rewards"):
    - 790            rewards = [
    - 791                self._deserialize_milestone_rewards(reward) for reward in raw_rewards
    - 792            ]
    - 793
    - 794        activities: typing.Optional[
    - 795            collections.Sequence[milestones.MilestoneActivity]
    - 796        ] = None
    - 797        if raw_activities := payload.get("activities"):
    - 798            activities = [
    - 799                self._deserialize_milestone_activity(active)
    - 800                for active in raw_activities
    - 801            ]
    - 802
    - 803        quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None
    - 804        if raw_quests := payload.get("availableQuests"):
    - 805            quests = [
    - 806                self._deserialize_milestone_available_quest(quest)
    - 807                for quest in raw_quests
    - 808            ]
    - 809
    - 810        vendors: typing.Optional[
    - 811            collections.Sequence[milestones.MilestoneVendor]
    - 812        ] = None
    - 813        if raw_vendors := payload.get("vendors"):
    - 814            vendors = [
    - 815                milestones.MilestoneVendor(
    - 816                    vendor_hash=vendor["vendorHash"],
    - 817                    preview_itemhash=vendor.get("previewItemHash"),
    - 818                )
    - 819                for vendor in raw_vendors
    - 820            ]
    - 821
    - 822        return milestones.Milestone(
    - 823            hash=payload["milestoneHash"],
    - 824            start_date=start_date,
    - 825            end_date=end_date,
    - 826            order=payload["order"],
    - 827            rewards=rewards,
    - 828            available_quests=quests,
    - 829            activities=activities,
    - 830            vendors=vendors,
    - 831        )
    - 832
    - 833    def _deserialize_artifact_tiers(
    - 834        self, payload: typedefs.JSONObject
    - 835    ) -> season.ArtifactTier:
    - 836        return season.ArtifactTier(
    - 837            hash=payload["tierHash"],
    - 838            is_unlocked=payload["isUnlocked"],
    - 839            points_to_unlock=payload["pointsToUnlock"],
    - 840            items=[
    - 841                season.ArtifactTierItem(
    - 842                    hash=item["itemHash"], is_active=item["isActive"]
    - 843                )
    - 844                for item in payload["items"]
    - 845            ],
    - 846        )
    - 847
    - 848    def deserialize_characters(
    - 849        self, payload: typedefs.JSONObject
    - 850    ) -> collections.Mapping[int, character.Character]:
    - 851        return {
    - 852            int(char_id): self._set_character_attrs(char)
    - 853            for char_id, char in payload["data"].items()
    - 854        }
    - 855
    - 856    def deserialize_character(
    - 857        self, payload: typedefs.JSONObject
    - 858    ) -> character.Character:
    - 859        return self._set_character_attrs(payload)
    - 860
    - 861    def deserialize_character_equipments(
    - 862        self, payload: typedefs.JSONObject
    - 863    ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]:
    - 864        return {
    - 865            int(char_id): self.deserialize_profile_items(item)
    - 866            for char_id, item in payload["data"].items()
    - 867        }
    - 868
    - 869    def deserialize_character_activities(
    - 870        self, payload: typedefs.JSONObject
    - 871    ) -> collections.Mapping[int, activity.CharacterActivity]:
    - 872        return {
    - 873            int(char_id): self.deserialize_character_activity(data)
    - 874            for char_id, data in payload["data"].items()
    - 875        }
    - 876
    - 877    def deserialize_characters_render_data(
    - 878        self, payload: typedefs.JSONObject
    - 879    ) -> collections.Mapping[int, character.RenderedData]:
    - 880        return {
    - 881            int(char_id): self.deserialize_character_render_data(data)
    - 882            for char_id, data in payload["data"].items()
    - 883        }
    - 884
    - 885    def deserialize_character_progressions(
    - 886        self, payload: typedefs.JSONObject
    - 887    ) -> character.CharacterProgression:
    - 888        progressions_ = {
    - 889            int(prog_id): self.deserialize_progressions(prog)
    - 890            for prog_id, prog in payload["progressions"].items()
    - 891        }
    - 892
    - 893        factions = {
    - 894            int(faction_id): self._deserialize_factions(faction)
    - 895            for faction_id, faction in payload["factions"].items()
    - 896        }
    - 897
    - 898        milestones_ = {
    - 899            int(milestone_hash): self.deserialize_milestone(milestone)
    - 900            for milestone_hash, milestone in payload["milestones"].items()
    - 901        }
    - 902
    - 903        uninstanced_item_objectives = {
    - 904            int(item_hash): [self.deserialize_objectives(ins) for ins in obj]
    - 905            for item_hash, obj in payload["uninstancedItemObjectives"].items()
    - 906        }
    - 907
    - 908        artifact = payload["seasonalArtifact"]
    - 909        seasonal_artifact = season.CharacterScopedArtifact(
    - 910            hash=artifact["artifactHash"],
    - 911            points_used=artifact["pointsUsed"],
    - 912            reset_count=artifact["resetCount"],
    - 913            tiers=[
    - 914                self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"]
    - 915            ],
    - 916        )
    - 917        checklists = payload["checklists"]
    - 918
    - 919        return character.CharacterProgression(
    - 920            progressions=progressions_,
    - 921            factions=factions,
    - 922            checklists=checklists,
    - 923            milestones=milestones_,
    - 924            seasonal_artifact=seasonal_artifact,
    - 925            uninstanced_item_objectives=uninstanced_item_objectives,
    - 926        )
    - 927
    - 928    def deserialize_character_progressions_mapping(
    - 929        self, payload: typedefs.JSONObject
    - 930    ) -> collections.Mapping[int, character.CharacterProgression]:
    - 931        character_progressions: collections.Mapping[
    - 932            int, character.CharacterProgression
    - 933        ] = {}
    - 934        for char_id, data in payload["data"].items():
    - 935            # A little hack to stop mypy complaining about Mapping <-> dict
    - 936            character_progressions[int(char_id)] = self.deserialize_character_progressions(data)  # type: ignore[index]
    - 937        return character_progressions
    - 938
    - 939    def deserialize_characters_records(
    - 940        self,
    - 941        payload: typedefs.JSONObject,
    - 942    ) -> collections.Mapping[int, records.CharacterRecord]:
    - 943
    - 944        return {
    - 945            int(rec_id): self.deserialize_character_records(
    - 946                rec, record_hashes=payload.get("featuredRecordHashes")
    - 947            )
    - 948            for rec_id, rec in payload["records"].items()
    - 949        }
    - 950
    - 951    def deserialize_profile_records(
    - 952        self, payload: typedefs.JSONObject
    - 953    ) -> collections.Mapping[int, records.Record]:
    - 954        raw_profile_records = payload["data"]
    - 955        scores = records.RecordScores(
    - 956            current_score=raw_profile_records["score"],
    - 957            legacy_score=raw_profile_records["legacyScore"],
    - 958            lifetime_score=raw_profile_records["lifetimeScore"],
    - 959        )
    - 960        return {
    - 961            int(record_id): self.deserialize_records(
    - 962                record,
    - 963                scores,
    - 964                categories_hash=raw_profile_records["recordCategoriesRootNodeHash"],
    - 965                seals_hash=raw_profile_records["recordSealsRootNodeHash"],
    - 966            )
    - 967            for record_id, record in raw_profile_records["records"].items()
    - 968        }
    - 969
    - 970    def _deserialize_craftable_socket_plug(
    - 971        self, payload: typedefs.JSONObject
    - 972    ) -> items.CraftableSocketPlug:
    - 973        return items.CraftableSocketPlug(
    - 974            item_hash=int(payload["plugItemHash"]),
    - 975            failed_requirement_indexes=payload.get("failedRequirementIndexes", []),
    - 976        )
    - 977
    - 978    def _deserialize_craftable_socket(
    - 979        self, payload: typedefs.JSONObject
    - 980    ) -> items.CraftableSocket:
    - 981
    - 982        plugs: list[items.CraftableSocketPlug] = []
    - 983        if raw_plug := payload.get("plug"):
    - 984            plugs.extend(
    - 985                self._deserialize_craftable_socket_plug(plug) for plug in raw_plug
    - 986            )
    - 987
    - 988        return items.CraftableSocket(
    - 989            plug_set_hash=int(payload["plugSetHash"]), plugs=plugs
    - 990        )
    - 991
    - 992    def _deserialize_craftable_item(
    - 993        self, payload: typedefs.JSONObject
    - 994    ) -> items.CraftableItem:
    - 995
    - 996        return items.CraftableItem(
    - 997            is_visible=payload["visible"],
    - 998            failed_requirement_indexes=payload.get("failedRequirementIndexes", []),
    - 999            sockets=[
    -1000                self._deserialize_craftable_socket(socket)
    -1001                for socket in payload["sockets"]
    -1002            ],
    -1003        )
    -1004
    -1005    def deserialize_craftables_component(
    -1006        self, payload: typedefs.JSONObject
    -1007    ) -> components.CraftablesComponent:
    -1008        return components.CraftablesComponent(
    -1009            net=self._net,
    -1010            craftables={
    -1011                int(item_id): self._deserialize_craftable_item(item)
    -1012                for item_id, item in payload["craftables"].items()
    -1013                if item is not None
    -1014            },
    -1015            crafting_root_node_hash=payload["craftingRootNodeHash"],
    -1016        )
    -1017
    -1018    def deserialize_components(  # noqa: C901 Too complex.
    -1019        self, payload: typedefs.JSONObject
    -1020    ) -> components.Component:
    -1021
    -1022        profile_: typing.Optional[profile.Profile] = None
    -1023        if raw_profile := payload.get("profile"):
    -1024            profile_ = self.deserialize_profile(raw_profile)
    -1025
    -1026        profile_progression: typing.Optional[profile.ProfileProgression] = None
    -1027        if raw_profile_progression := payload.get("profileProgression"):
    -1028            profile_progression = self.deserialize_profile_progression(
    -1029                raw_profile_progression
    -1030            )
    -1031
    -1032        profile_currencies: typing.Optional[
    -1033            collections.Sequence[profile.ProfileItemImpl]
    -1034        ] = None
    -1035        if raw_profile_currencies := payload.get("profileCurrencies"):
    -1036            if "data" in raw_profile_currencies:
    -1037                profile_currencies = self.deserialize_profile_items(
    -1038                    raw_profile_currencies["data"]
    -1039                )
    -1040
    -1041        profile_inventories: typing.Optional[
    -1042            collections.Sequence[profile.ProfileItemImpl]
    -1043        ] = None
    -1044        if raw_profile_inventories := payload.get("profileInventory"):
    -1045            if "data" in raw_profile_inventories:
    -1046                profile_inventories = self.deserialize_profile_items(
    -1047                    raw_profile_inventories["data"]
    -1048                )
    -1049
    -1050        profile_records: typing.Optional[
    -1051            collections.Mapping[int, records.Record]
    -1052        ] = None
    -1053
    -1054        if raw_profile_records_ := payload.get("profileRecords"):
    -1055            profile_records = self.deserialize_profile_records(raw_profile_records_)
    -1056
    -1057        characters: typing.Optional[typing.Mapping[int, character.Character]] = None
    -1058        if raw_characters := payload.get("characters"):
    -1059            characters = self.deserialize_characters(raw_characters)
    -1060
    -1061        character_records: typing.Optional[
    -1062            collections.Mapping[int, records.CharacterRecord]
    -1063        ] = None
    -1064
    -1065        if raw_character_records := payload.get("characterRecords"):
    -1066            # Had to do it in two steps..
    -1067            to_update: typedefs.JSONObject = {}
    -1068            for _, data in raw_character_records["data"].items():
    -1069                for record_id, record in data.items():
    -1070                    to_update[record_id] = record
    -1071
    -1072            character_records = {
    -1073                int(rec_id): self.deserialize_character_records(
    -1074                    rec, record_hashes=to_update.get("featuredRecordHashes")
    -1075                )
    -1076                for rec_id, rec in to_update["records"].items()
    -1077            }
    -1078
    -1079        character_equipments: typing.Optional[
    -1080            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
    -1081        ] = None
    -1082        if raw_character_equips := payload.get("characterEquipment"):
    -1083            character_equipments = self.deserialize_character_equipments(
    -1084                raw_character_equips
    -1085            )
    -1086
    -1087        character_inventories: typing.Optional[
    -1088            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
    -1089        ] = None
    -1090        if raw_character_inventories := payload.get("characterInventories"):
    -1091            if "data" in raw_character_inventories:
    -1092                character_inventories = self.deserialize_character_equipments(
    -1093                    raw_character_inventories
    -1094                )
    -1095
    -1096        character_activities: typing.Optional[
    -1097            collections.Mapping[int, activity.CharacterActivity]
    -1098        ] = None
    -1099        if raw_char_acts := payload.get("characterActivities"):
    -1100            character_activities = self.deserialize_character_activities(raw_char_acts)
    -1101
    -1102        character_render_data: typing.Optional[
    -1103            collections.Mapping[int, character.RenderedData]
    -1104        ] = None
    -1105        if raw_character_render_data := payload.get("characterRenderData"):
    -1106            character_render_data = self.deserialize_characters_render_data(
    -1107                raw_character_render_data
    -1108            )
    -1109
    -1110        character_progressions: typing.Optional[
    -1111            collections.Mapping[int, character.CharacterProgression]
    -1112        ] = None
    -1113
    -1114        if raw_character_progressions := payload.get("characterProgressions"):
    -1115            character_progressions = self.deserialize_character_progressions_mapping(
    -1116                raw_character_progressions
    -1117            )
    -1118
    -1119        profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None
    -1120        if raw_profile_string_vars := payload.get("profileStringVariables"):
    -1121            profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"]
    -1122
    -1123        character_string_vars: typing.Optional[
    -1124            collections.Mapping[int, collections.Mapping[int, int]]
    -1125        ] = None
    -1126        if raw_character_string_vars := payload.get("characterStringVariables"):
    -1127            character_string_vars = {
    -1128                int(char_id): data["integerValuesByHash"]
    -1129                for char_id, data in raw_character_string_vars["data"].items()
    -1130            }
    -1131
    -1132        metrics: typing.Optional[
    -1133            collections.Sequence[
    -1134                collections.Mapping[
    -1135                    int, tuple[bool, typing.Optional[records.Objective]]
    -1136                ]
    -1137            ]
    -1138        ] = None
    -1139        root_node_hash: typing.Optional[int] = None
    -1140
    -1141        if raw_metrics := payload.get("metrics"):
    -1142            root_node_hash = raw_metrics["data"]["metricsRootNodeHash"]
    -1143            metrics = [
    -1144                {
    -1145                    int(metrics_hash): (
    -1146                        data["invisible"],
    -1147                        self.deserialize_objectives(data["objectiveProgress"])
    -1148                        if "objectiveProgress" in data
    -1149                        else None,
    -1150                    )
    -1151                    for metrics_hash, data in raw_metrics["data"]["metrics"].items()
    -1152                }
    -1153            ]
    -1154        transitory: typing.Optional[fireteams.FireteamParty] = None
    -1155        if raw_transitory := payload.get("profileTransitoryData"):
    -1156            if "data" in raw_transitory:
    -1157                transitory = self.deserialize_fireteam_party(raw_transitory["data"])
    -1158
    -1159        item_components: typing.Optional[components.ItemsComponent] = None
    -1160        if raw_item_components := payload.get("itemComponents"):
    -1161            item_components = self.deserialize_items_component(raw_item_components)
    -1162
    -1163        profile_plugsets: typing.Optional[
    -1164            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    -1165        ] = None
    -1166
    -1167        if raw_profile_plugs := payload.get("profilePlugSets"):
    -1168            profile_plugsets = {
    -1169                int(index): [self.deserialize_plug_item_state(state) for state in data]
    -1170                for index, data in raw_profile_plugs["data"]["plugs"].items()
    -1171            }
    -1172
    -1173        character_plugsets: typing.Optional[
    -1174            collections.Mapping[
    -1175                int, collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    -1176            ]
    -1177        ] = None
    -1178        if raw_char_plugsets := payload.get("characterPlugSets"):
    -1179            character_plugsets = {
    -1180                int(char_id): {
    -1181                    int(index): [
    -1182                        self.deserialize_plug_item_state(state) for state in data
    -1183                    ]
    -1184                    for index, data in inner["plugs"].items()
    -1185                }
    -1186                for char_id, inner in raw_char_plugsets["data"].items()
    -1187            }
    -1188
    -1189        character_collectibles: typing.Optional[
    -1190            collections.Mapping[int, items.Collectible]
    -1191        ] = None
    -1192        if raw_character_collectibles := payload.get("characterCollectibles"):
    -1193            character_collectibles = {
    -1194                int(char_id): self._deserialize_collectible(data)
    -1195                for char_id, data in raw_character_collectibles["data"].items()
    -1196            }
    -1197
    -1198        profile_collectibles: typing.Optional[items.Collectible] = None
    -1199        if raw_profile_collectibles := payload.get("profileCollectibles"):
    -1200            profile_collectibles = self._deserialize_collectible(
    -1201                raw_profile_collectibles["data"]
    -1202            )
    -1203
    -1204        profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
    -1205        if raw_profile_nodes := payload.get("profilePresentationNodes"):
    -1206            profile_nodes = {
    -1207                int(node_hash): self._deserialize_node(node)
    -1208                for node_hash, node in raw_profile_nodes["data"]["nodes"].items()
    -1209            }
    -1210
    -1211        character_nodes: typing.Optional[
    -1212            collections.Mapping[int, collections.Mapping[int, records.Node]]
    -1213        ] = None
    -1214        if raw_character_nodes := payload.get("characterPresentationNodes"):
    -1215            character_nodes = {
    -1216                int(char_id): {
    -1217                    int(node_hash): self._deserialize_node(node)
    -1218                    for node_hash, node in each_character["nodes"].items()
    -1219                }
    -1220                for char_id, each_character in raw_character_nodes["data"].items()
    -1221            }
    -1222
    -1223        platform_silver: typing.Optional[
    -1224            collections.Mapping[str, profile.ProfileItemImpl]
    -1225        ] = None
    -1226        if raw_platform_silver := payload.get("platformSilver"):
    -1227            if "data" in raw_platform_silver:
    -1228                platform_silver = {
    -1229                    platform_name: self.deserialize_profile_item(item)
    -1230                    for platform_name, item in raw_platform_silver["data"][
    -1231                        "platformSilver"
    -1232                    ].items()
    -1233                }
    -1234
    -1235        character_currency_lookups: typing.Optional[
    -1236            collections.Mapping[int, collections.Sequence[items.Currency]]
    -1237        ] = None
    -1238        if raw_char_lookups := payload.get("characterCurrencyLookups"):
    -1239            if "data" in raw_char_lookups:
    -1240                character_currency_lookups = {
    -1241                    int(char_id): self._deserialize_currencies(currencie)
    -1242                    for char_id, currencie in raw_char_lookups["data"].items()
    -1243                }
    -1244
    -1245        character_craftables: typing.Optional[
    -1246            collections.Mapping[int, components.CraftablesComponent]
    -1247        ] = None
    -1248        if raw_character_craftables := payload.get("characterCraftables"):
    -1249
    -1250            if "data" in raw_character_craftables:
    -1251                character_craftables = {
    -1252                    int(char_id): self.deserialize_craftables_component(craftable)
    -1253                    for char_id, craftable in raw_character_craftables["data"].items()
    -1254                }
    -1255
    -1256        return components.Component(
    -1257            profiles=profile_,
    -1258            profile_progression=profile_progression,
    -1259            profile_currencies=profile_currencies,
    -1260            profile_inventories=profile_inventories,
    -1261            profile_records=profile_records,
    -1262            characters=characters,
    -1263            character_records=character_records,
    -1264            character_equipments=character_equipments,
    -1265            character_inventories=character_inventories,
    -1266            character_activities=character_activities,
    -1267            character_render_data=character_render_data,
    -1268            character_progressions=character_progressions,
    -1269            profile_string_variables=profile_string_vars,
    -1270            character_string_variables=character_string_vars,
    -1271            metrics=metrics,
    -1272            root_node_hash=root_node_hash,
    -1273            transitory=transitory,
    -1274            item_components=item_components,
    -1275            profile_plugsets=profile_plugsets,
    -1276            character_plugsets=character_plugsets,
    -1277            character_collectibles=character_collectibles,
    -1278            profile_collectibles=profile_collectibles,
    -1279            profile_nodes=profile_nodes,
    -1280            character_nodes=character_nodes,
    -1281            platform_silver=platform_silver,
    -1282            character_currency_lookups=character_currency_lookups,
    -1283            character_craftables=character_craftables,
    -1284        )
    -1285
    -1286    def deserialize_items_component(
    -1287        self, payload: typedefs.JSONObject
    -1288    ) -> components.ItemsComponent:
    -1289        instances: typing.Optional[
    -1290            collections.Sequence[collections.Mapping[int, items.ItemInstance]]
    -1291        ] = None
    -1292        if raw_instances := payload.get("instances"):
    -1293            instances = [
    -1294                {
    -1295                    int(ins_id): self.deserialize_instanced_item(item)
    -1296                    for ins_id, item in raw_instances["data"].items()
    -1297                }
    -1298            ]
    -1299
    -1300        render_data: typing.Optional[
    -1301            collections.Mapping[int, tuple[bool, dict[int, int]]]
    -1302        ] = None
    -1303        if raw_render_data := payload.get("renderData"):
    -1304            render_data = {
    -1305                int(ins_id): (data["useCustomDyes"], data["artRegions"])
    -1306                for ins_id, data in raw_render_data["data"].items()
    -1307            }
    -1308
    -1309        stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None
    -1310        if raw_stats := payload.get("stats"):
    -1311            builder: collections.Mapping[int, items.ItemStatsView] = {}
    -1312            for ins_id, stat in raw_stats["data"].items():
    -1313                for _, items_ in stat.items():
    -1314                    builder[int(ins_id)] = self.deserialize_item_stats_view(items_)  # type: ignore[index]
    -1315            stats = builder
    -1316
    -1317        sockets: typing.Optional[
    -1318            collections.Mapping[int, collections.Sequence[items.ItemSocket]]
    -1319        ] = None
    -1320        if raw_sockets := payload.get("sockets"):
    -1321            sockets = {
    -1322                int(ins_id): [
    -1323                    self.deserialize_item_socket(socket) for socket in item["sockets"]
    -1324                ]
    -1325                for ins_id, item in raw_sockets["data"].items()
    -1326            }
    -1327
    -1328        objeectives: typing.Optional[
    -1329            collections.Mapping[int, collections.Sequence[records.Objective]]
    -1330        ] = None
    -1331        if raw_objectives := payload.get("objectives"):
    -1332            objeectives = {
    -1333                int(ins_id): [self.deserialize_objectives(objective)]
    -1334                for ins_id, data in raw_objectives["data"].items()
    -1335                for objective in data["objectives"]
    -1336            }
    -1337
    -1338        perks: typing.Optional[
    -1339            collections.Mapping[int, collections.Collection[items.ItemPerk]]
    -1340        ] = None
    -1341        if raw_perks := payload.get("perks"):
    -1342            perks = {
    -1343                int(ins_id): [
    -1344                    self.deserialize_item_perk(perk) for perk in item["perks"]
    -1345                ]
    -1346                for ins_id, item in raw_perks["data"].items()
    -1347            }
    -1348
    -1349        plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None
    -1350        if raw_plug_states := payload.get("plugStates"):
    -1351            pending_states: list[items.PlugItemState] = []
    -1352            for _, plug in raw_plug_states["data"].items():
    -1353                pending_states.append(self.deserialize_plug_item_state(plug))
    -1354            plug_states = pending_states
    -1355
    -1356        reusable_plugs: typing.Optional[
    -1357            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    -1358        ] = None
    -1359        if raw_re_plugs := payload.get("reusablePlugs"):
    -1360            reusable_plugs = {
    -1361                int(ins_id): [
    -1362                    self.deserialize_plug_item_state(state) for state in inner
    -1363                ]
    -1364                for ins_id, plug in raw_re_plugs["data"].items()
    -1365                for inner in list(plug["plugs"].values())
    -1366            }
    -1367
    -1368        plug_objectives: typing.Optional[
    -1369            collections.Mapping[
    -1370                int, collections.Mapping[int, collections.Collection[records.Objective]]
    -1371            ]
    -1372        ] = None
    -1373        if raw_plug_objectives := payload.get("plugObjectives"):
    -1374            plug_objectives = {
    -1375                int(ins_id): {
    -1376                    int(obj_hash): [self.deserialize_objectives(obj) for obj in objs]
    -1377                    for obj_hash, objs in inner["objectivesPerPlug"].items()
    -1378                }
    -1379                for ins_id, inner in raw_plug_objectives["data"].items()
    -1380            }
    -1381
    -1382        return components.ItemsComponent(
    -1383            sockets=sockets,
    -1384            stats=stats,
    -1385            render_data=render_data,
    -1386            instances=instances,
    -1387            objectives=objeectives,
    -1388            perks=perks,
    -1389            plug_states=plug_states,
    -1390            reusable_plugs=reusable_plugs,
    -1391            plug_objectives=plug_objectives,
    -1392        )
    -1393
    -1394    def deserialize_character_component(  # type: ignore[call-arg]
    -1395        self, payload: typedefs.JSONObject
    -1396    ) -> components.CharacterComponent:
    -1397
    -1398        character_: typing.Optional[character.Character] = None
    -1399        if raw_singuler_character := payload.get("character"):
    -1400            character_ = self.deserialize_character(raw_singuler_character["data"])
    -1401
    -1402        inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
    -1403        if raw_inventory := payload.get("inventory"):
    -1404            if "data" in raw_inventory:
    -1405                inventory = self.deserialize_profile_items(raw_inventory["data"])
    -1406
    -1407        activities: typing.Optional[activity.CharacterActivity] = None
    -1408        if raw_activities := payload.get("activities"):
    -1409            activities = self.deserialize_character_activity(raw_activities["data"])
    -1410
    -1411        equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
    -1412        if raw_equipments := payload.get("equipment"):
    -1413            equipment = self.deserialize_profile_items(raw_equipments["data"])
    -1414
    -1415        progressions_: typing.Optional[character.CharacterProgression] = None
    -1416        if raw_progressions := payload.get("progressions"):
    -1417            progressions_ = self.deserialize_character_progressions(
    -1418                raw_progressions["data"]
    -1419            )
    -1420
    -1421        render_data: typing.Optional[character.RenderedData] = None
    -1422        if raw_render_data := payload.get("renderData"):
    -1423            render_data = self.deserialize_character_render_data(
    -1424                raw_render_data["data"]
    -1425            )
    -1426
    -1427        character_records: typing.Optional[
    -1428            collections.Mapping[int, records.CharacterRecord]
    -1429        ] = None
    -1430        if raw_char_records := payload.get("records"):
    -1431            character_records = self.deserialize_characters_records(
    -1432                raw_char_records["data"]
    -1433            )
    -1434
    -1435        item_components: typing.Optional[components.ItemsComponent] = None
    -1436        if raw_item_components := payload.get("itemComponents"):
    -1437            item_components = self.deserialize_items_component(raw_item_components)
    -1438
    -1439        nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
    -1440        if raw_nodes := payload.get("presentationNodes"):
    -1441            nodes = {
    -1442                int(node_hash): self._deserialize_node(node)
    -1443                for node_hash, node in raw_nodes["data"]["nodes"].items()
    -1444            }
    -1445
    -1446        collectibles: typing.Optional[items.Collectible] = None
    -1447        if raw_collectibles := payload.get("collectibles"):
    -1448            collectibles = self._deserialize_collectible(raw_collectibles["data"])
    -1449
    -1450        currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None
    -1451        if raw_currencies := payload.get("currencyLookups"):
    -1452            if "data" in raw_currencies:
    -1453                currency_lookups = self._deserialize_currencies(raw_currencies)
    -1454
    -1455        return components.CharacterComponent(
    -1456            activities=activities,
    -1457            equipment=equipment,
    -1458            inventory=inventory,
    -1459            progressions=progressions_,
    -1460            render_data=render_data,
    -1461            character=character_,
    -1462            character_records=character_records,
    -1463            profile_records=None,
    -1464            item_components=item_components,
    -1465            currency_lookups=currency_lookups,
    -1466            collectibles=collectibles,
    -1467            nodes=nodes,
    -1468        )
    -1469
    -1470    def _set_entity_attrs(
    -1471        self, payload: typedefs.JSONObject, *, key: str = "displayProperties"
    -1472    ) -> entity.Entity:
    -1473
    -1474        name: undefined.UndefinedOr[str] = undefined.Undefined
    -1475        description: undefined.UndefinedOr[str] = undefined.Undefined
    -1476
    -1477        if properties := payload[key]:
    -1478            if (raw_name := properties["name"]) is not typedefs.Unknown:
    -1479                name = raw_name
    -1480
    -1481            if (
    -1482                raw_description := properties["description"]
    -1483            ) and not typedefs.is_unknown(raw_description):
    -1484                description = raw_description
    -1485
    -1486        return entity.Entity(
    -1487            net=self._net,
    -1488            hash=payload["hash"],
    -1489            index=payload["index"],
    -1490            name=name,
    -1491            description=description,
    -1492            has_icon=properties["hasIcon"],
    -1493            icon=assets.Image(properties["icon"] if "icon" in properties else None),
    -1494        )
    -1495
    -1496    def deserialize_inventory_results(
    -1497        self, payload: typedefs.JSONObject
    -1498    ) -> iterators.FlatIterator[entity.SearchableEntity]:
    -1499        suggested_words: list[str] = payload["suggestedWords"]
    -1500
    -1501        def _check_unknown(s: str) -> undefined.UndefinedOr[str]:
    -1502            return s if not typedefs.is_unknown(s) else undefined.Undefined
    -1503
    -1504        return iterators.FlatIterator(
    -1505            [
    -1506                entity.SearchableEntity(
    -1507                    net=self._net,
    -1508                    hash=data["hash"],
    -1509                    entity_type=data["entityType"],
    -1510                    weight=data["weight"],
    -1511                    suggested_words=suggested_words,
    -1512                    name=data["displayProperties"]["name"],
    -1513                    has_icon=data["displayProperties"]["hasIcon"],
    -1514                    description=_check_unknown(
    -1515                        data["displayProperties"]["description"]
    -1516                    ),
    -1517                    icon=assets.Image(data["displayProperties"]["icon"]),
    -1518                )
    -1519                for data in payload["results"]["results"]
    -1520            ]
    -1521        )
    -1522
    -1523    def _deserialize_inventory_item_objects(
    -1524        self, payload: typedefs.JSONObject
    -1525    ) -> entity.InventoryEntityObjects:
    -1526        return entity.InventoryEntityObjects(
    -1527            action=payload.get("action"),
    -1528            set_data=payload.get("setData"),
    -1529            stats=payload.get("stats"),
    -1530            equipping_block=payload.get("equippingBlock"),
    -1531            translation_block=payload.get("translationBlock"),
    -1532            preview=payload.get("preview"),
    -1533            quality=payload.get("quality"),
    -1534            value=payload.get("value"),
    -1535            source_data=payload.get("sourceData"),
    -1536            objectives=payload.get("objectives"),
    -1537            plug=payload.get("plug"),
    -1538            metrics=payload.get("metrics"),
    -1539            gearset=payload.get("gearset"),
    -1540            sack=payload.get("sack"),
    -1541            sockets=payload.get("sockets"),
    -1542            summary=payload.get("summary"),
    -1543            talent_gird=payload.get("talentGrid"),
    -1544            investments_stats=payload.get("investmentStats"),
    -1545            perks=payload.get("perks"),
    -1546            animations=payload.get("animations", []),
    -1547            links=payload.get("links", []),
    -1548        )
    -1549
    -1550    def deserialize_inventory_entity(  # noqa: C901 Too complex.
    -1551        self, payload: typedefs.JSONObject, /
    -1552    ) -> entity.InventoryEntity:
    -1553
    -1554        props = self._set_entity_attrs(payload)
    -1555        objects = self._deserialize_inventory_item_objects(payload)
    -1556
    -1557        collectible_hash: typing.Optional[int] = None
    -1558        if raw_collectible_hash := payload.get("collectibleHash"):
    -1559            collectible_hash = int(raw_collectible_hash)
    -1560
    -1561        secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    -1562        if raw_second_icon := payload.get("secondaryIcon"):
    -1563            secondary_icon = assets.Image(raw_second_icon)
    -1564
    -1565        secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    -1566        if raw_second_overlay := payload.get("secondaryOverlay"):
    -1567            secondary_overlay = assets.Image(raw_second_overlay)
    -1568
    -1569        secondary_special: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    -1570        if raw_second_special := payload.get("secondarySpecial"):
    -1571            secondary_special = assets.Image(raw_second_special)
    -1572
    -1573        screenshot: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    -1574        if raw_screenshot := payload.get("screenshot"):
    -1575            screenshot = assets.Image(raw_screenshot)
    -1576
    -1577        watermark_icon: typing.Optional[assets.Image] = None
    -1578        if raw_watermark_icon := payload.get("iconWatermark"):
    -1579            watermark_icon = assets.Image(raw_watermark_icon)
    -1580
    -1581        watermark_shelved: typing.Optional[assets.Image] = None
    -1582        if raw_watermark_shelved := payload.get("iconWatermarkShelved"):
    -1583            watermark_shelved = assets.Image(raw_watermark_shelved)
    -1584
    -1585        about: undefined.UndefinedOr[str] = undefined.Undefined
    -1586        if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown(
    -1587            raw_about
    -1588        ):
    -1589            about = raw_about
    -1590
    -1591        ui_item_style: undefined.UndefinedOr[str] = undefined.Undefined
    -1592        if (
    -1593            raw_ui_style := payload.get("uiItemDisplayStyle")
    -1594        ) and not typedefs.is_unknown(raw_ui_style):
    -1595            ui_item_style = raw_ui_style
    -1596
    -1597        tier_and_name: undefined.UndefinedOr[str] = undefined.Undefined
    -1598        if (
    -1599            raw_tier_and_name := payload.get("itemTypeAndTierDisplayName")
    -1600        ) and not typedefs.is_unknown(raw_tier_and_name):
    -1601            tier_and_name = raw_tier_and_name
    -1602
    -1603        type_name: undefined.UndefinedOr[str] = undefined.Undefined
    -1604        if (
    -1605            raw_type_name := payload.get("itemTypeDisplayName")
    -1606        ) and not typedefs.is_unknown(raw_type_name):
    -1607            type_name = raw_type_name
    -1608
    -1609        display_source: undefined.UndefinedOr[str] = undefined.Undefined
    -1610        if (
    -1611            raw_display_source := payload.get("displaySource")
    -1612        ) and not typedefs.is_unknown(raw_display_source):
    -1613            display_source = raw_display_source
    -1614
    -1615        lorehash: typing.Optional[int] = None
    -1616        if raw_lore_hash := payload.get("loreHash"):
    -1617            lorehash = int(raw_lore_hash)
    -1618
    -1619        summary_hash: typing.Optional[int] = None
    -1620        if raw_summary_hash := payload.get("summaryItemHash"):
    -1621            summary_hash = raw_summary_hash
    -1622
    -1623        breaker_type_hash: typing.Optional[int] = None
    -1624        if raw_breaker_type_hash := payload.get("breakerTypeHash"):
    -1625            breaker_type_hash = int(raw_breaker_type_hash)
    -1626
    -1627        damage_types: typing.Optional[collections.Sequence[int]] = None
    -1628        if raw_damage_types := payload.get("damageTypes"):
    -1629            damage_types = [int(type_) for type_ in raw_damage_types]
    -1630
    -1631        damagetype_hashes: typing.Optional[collections.Sequence[int]] = None
    -1632        if raw_damagetype_hashes := payload.get("damageTypeHashes"):
    -1633            damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes]
    -1634
    -1635        default_damagetype_hash: typing.Optional[int] = None
    -1636        if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"):
    -1637            default_damagetype_hash = int(raw_defaultdmg_hash)
    -1638
    -1639        emblem_objective_hash: typing.Optional[int] = None
    -1640        if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"):
    -1641            emblem_objective_hash = int(raw_emblem_obj_hash)
    -1642
    -1643        tier_type: typing.Optional[enums.TierType] = None
    -1644        tier: typing.Optional[enums.ItemTier] = None
    -1645        bucket_hash: typing.Optional[int] = None
    -1646        recovery_hash: typing.Optional[int] = None
    -1647        tier_name: undefined.UndefinedOr[str] = undefined.Undefined
    -1648        isinstance_item: bool = False
    -1649        expire_tool_tip: undefined.UndefinedOr[str] = undefined.Undefined
    -1650        expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.Undefined
    -1651        suppress_expiration: bool = False
    -1652        max_stack_size: typing.Optional[int] = None
    -1653        stack_label: undefined.UndefinedOr[str] = undefined.Undefined
    -1654
    -1655        if inventory := payload.get("inventory"):
    -1656            tier_type = enums.TierType(int(inventory["tierType"]))
    -1657            tier = enums.ItemTier(int(inventory["tierTypeHash"]))
    -1658            bucket_hash = int(inventory["bucketTypeHash"])
    -1659            recovery_hash = int(inventory["recoveryBucketTypeHash"])
    -1660            tier_name = inventory["tierTypeName"]
    -1661            isinstance_item = inventory["isInstanceItem"]
    -1662            suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"]
    -1663            max_stack_size = int(inventory["maxStackSize"])
    -1664
    -1665            try:
    -1666                stack_label = inventory["stackUniqueLabel"]
    -1667            except KeyError:
    -1668                pass
    -1669
    -1670        return entity.InventoryEntity(
    -1671            net=self._net,
    -1672            collectible_hash=collectible_hash,
    -1673            name=props.name,
    -1674            about=about,
    -1675            emblem_objective_hash=emblem_objective_hash,
    -1676            suppress_expiration=suppress_expiration,
    -1677            max_stack_size=max_stack_size,
    -1678            stack_label=stack_label,
    -1679            tier=tier,
    -1680            tier_type=tier_type,
    -1681            tier_name=tier_name,
    -1682            bucket_hash=bucket_hash,
    -1683            recovery_bucket_hash=recovery_hash,
    -1684            isinstance_item=isinstance_item,
    -1685            expire_in_orbit_message=expire_in_orbit_message,
    -1686            expiration_tooltip=expire_tool_tip,
    -1687            lore_hash=lorehash,
    -1688            type_and_tier_name=tier_and_name,
    -1689            summary_hash=summary_hash,
    -1690            ui_display_style=ui_item_style,
    -1691            type_name=type_name,
    -1692            breaker_type_hash=breaker_type_hash,
    -1693            description=props.description,
    -1694            display_source=display_source,
    -1695            hash=props.hash,
    -1696            damage_types=damage_types,
    -1697            index=props.index,
    -1698            icon=props.icon,
    -1699            has_icon=props.has_icon,
    -1700            screenshot=screenshot,
    -1701            watermark_icon=watermark_icon,
    -1702            watermark_shelved=watermark_shelved,
    -1703            secondary_icon=secondary_icon,
    -1704            secondary_overlay=secondary_overlay,
    -1705            secondary_special=secondary_special,
    -1706            type=enums.ItemType(int(payload["itemType"])),
    -1707            trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])],
    -1708            trait_ids=[trait for trait in payload.get("traitIds", [])],
    -1709            category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]],
    -1710            item_class=enums.Class(int(payload["classType"])),
    -1711            sub_type=enums.ItemSubType(int(payload["itemSubType"])),
    -1712            breaker_type=int(payload["breakerType"]),
    -1713            default_damagetype=int(payload["defaultDamageType"]),
    -1714            default_damagetype_hash=default_damagetype_hash,
    -1715            damagetype_hashes=damagetype_hashes,
    -1716            tooltip_notifications=payload["tooltipNotifications"],
    -1717            not_transferable=payload["nonTransferrable"],
    -1718            allow_actions=payload["allowActions"],
    -1719            is_equippable=payload["equippable"],
    -1720            objects=objects,
    -1721            background_colors=payload.get("backgroundColor", {}),
    -1722            season_hash=payload.get("seasonHash"),
    -1723            has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"],
    -1724        )
    -1725
    -1726    def deserialize_objective_entity(
    -1727        self, payload: typedefs.JSONObject, /
    -1728    ) -> entity.ObjectiveEntity:
    -1729        props = self._set_entity_attrs(payload)
    -1730        return entity.ObjectiveEntity(
    -1731            net=self._net,
    -1732            hash=props.hash,
    -1733            index=props.index,
    -1734            description=props.description,
    -1735            name=props.name,
    -1736            has_icon=props.has_icon,
    -1737            icon=props.icon,
    -1738            unlock_value_hash=payload["unlockValueHash"],
    -1739            completion_value=payload["completionValue"],
    -1740            scope=entity.GatingScope(int(payload["scope"])),
    -1741            location_hash=payload["locationHash"],
    -1742            allowed_negative_value=payload["allowNegativeValue"],
    -1743            allowed_value_change=payload["allowValueChangeWhenCompleted"],
    -1744            counting_downward=payload["isCountingDownward"],
    -1745            value_style=entity.ValueUIStyle(int(payload["valueStyle"])),
    -1746            progress_description=payload["progressDescription"],
    -1747            perks=payload["perks"],
    -1748            stats=payload["stats"],
    -1749            minimum_visibility=payload["minimumVisibilityThreshold"],
    -1750            allow_over_completion=payload["allowOvercompletion"],
    -1751            show_value_style=payload["showValueOnComplete"],
    -1752            display_only_objective=payload["isDisplayOnlyObjective"],
    -1753            complete_value_style=entity.ValueUIStyle(
    -1754                int(payload["completedValueStyle"])
    -1755            ),
    -1756            progress_value_style=entity.ValueUIStyle(
    -1757                int(payload["inProgressValueStyle"])
    -1758            ),
    -1759            ui_label=payload["uiLabel"],
    -1760            ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])),
    -1761        )
    -1762
    -1763    def _deserialize_activity_values(
    -1764        self, payload: typedefs.JSONObject, /
    -1765    ) -> activity.ActivityValues:
    -1766        team: typing.Optional[int] = None
    -1767        if raw_team := payload.get("team"):
    -1768            team = raw_team["basic"]["value"]
    -1769        return activity.ActivityValues(
    -1770            assists=payload["assists"]["basic"]["value"],
    -1771            deaths=payload["deaths"]["basic"]["value"],
    -1772            kills=payload["kills"]["basic"]["value"],
    -1773            is_completed=bool(payload["completed"]["basic"]["value"]),
    -1774            opponents_defeated=payload["opponentsDefeated"]["basic"]["value"],
    -1775            efficiency=payload["efficiency"]["basic"]["value"],
    -1776            kd_ratio=payload["killsDeathsRatio"]["basic"]["value"],
    -1777            kd_assists=payload["killsDeathsAssists"]["basic"]["value"],
    -1778            score=payload["score"]["basic"]["value"],
    -1779            duration=payload["activityDurationSeconds"]["basic"]["displayValue"],
    -1780            team=team,
    -1781            completion_reason=payload["completionReason"]["basic"]["displayValue"],
    -1782            fireteam_id=payload["fireteamId"]["basic"]["value"],
    -1783            start_seconds=payload["startSeconds"]["basic"]["value"],
    -1784            played_time=payload["timePlayedSeconds"]["basic"]["displayValue"],
    -1785            player_count=payload["playerCount"]["basic"]["value"],
    -1786            team_score=payload["teamScore"]["basic"]["value"],
    -1787        )
    -1788
    -1789    def deserialize_activity(
    -1790        self,
    -1791        payload: typedefs.JSONObject,
    -1792        /,
    -1793    ) -> activity.Activity:
    -1794        period = time.clean_date(payload["period"])
    -1795        details = payload["activityDetails"]
    -1796        ref_id = int(details["referenceId"])
    -1797        instance_id = int(details["instanceId"])
    -1798        mode = enums.GameMode(details["mode"])
    -1799        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
    -1800        is_private = details["isPrivate"]
    -1801        membership_type = enums.MembershipType(int(details["membershipType"]))
    -1802
    -1803        # Since we're using the same fields for post activity method
    -1804        # this check is required since post activity doesn't values values
    -1805        values = self._deserialize_activity_values(payload["values"])
    -1806
    -1807        return activity.Activity(
    -1808            net=self._net,
    -1809            hash=ref_id,
    -1810            instance_id=instance_id,
    -1811            mode=mode,
    -1812            modes=modes,
    -1813            is_private=is_private,
    -1814            membership_type=membership_type,
    -1815            occurred_at=period,
    -1816            values=values,
    -1817        )
    -1818
    -1819    def deserialize_activities(
    -1820        self, payload: typedefs.JSONObject
    -1821    ) -> iterators.FlatIterator[activity.Activity]:
    -1822        return iterators.FlatIterator(
    -1823            [
    -1824                self.deserialize_activity(activity_)
    -1825                for activity_ in payload["activities"]
    -1826            ]
    -1827        )
    -1828
    -1829    def deserialize_extended_weapon_values(
    -1830        self, payload: typedefs.JSONObject
    -1831    ) -> activity.ExtendedWeaponValues:
    -1832
    -1833        assists: typing.Optional[int] = None
    -1834        if raw_assists := payload["values"].get("uniqueWeaponAssists"):
    -1835            assists = raw_assists["basic"]["value"]
    -1836        assists_damage: typing.Optional[int] = None
    -1837
    -1838        if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"):
    -1839            assists_damage = raw_assists_damage["basic"]["value"]
    -1840
    -1841        return activity.ExtendedWeaponValues(
    -1842            reference_id=int(payload["referenceId"]),
    -1843            kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"],
    -1844            precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][
    -1845                "value"
    -1846            ],
    -1847            assists=assists,
    -1848            assists_damage=assists_damage,
    -1849            precision_kills_percentage=(
    -1850                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"],
    -1851                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][
    -1852                    "displayValue"
    -1853                ],
    -1854            ),
    -1855        )
    -1856
    -1857    def _deserialize_extended_values(
    -1858        self, payload: typedefs.JSONObject
    -1859    ) -> activity.ExtendedValues:
    -1860        weapons: typing.Optional[
    -1861            collections.Collection[activity.ExtendedWeaponValues]
    -1862        ] = None
    -1863
    -1864        if raw_weapons := payload.get("weapons"):
    -1865            weapons = [
    -1866                self.deserialize_extended_weapon_values(value) for value in raw_weapons
    -1867            ]
    -1868
    -1869        return activity.ExtendedValues(
    -1870            precision_kills=payload["values"]["precisionKills"]["basic"]["value"],
    -1871            grenade_kills=payload["values"]["weaponKillsGrenade"]["basic"]["value"],
    -1872            melee_kills=payload["values"]["weaponKillsMelee"]["basic"]["value"],
    -1873            super_kills=payload["values"]["weaponKillsSuper"]["basic"]["value"],
    -1874            ability_kills=payload["values"]["weaponKillsAbility"]["basic"]["value"],
    -1875            weapons=weapons,
    -1876        )
    -1877
    -1878    def deserialize_post_activity_player(
    -1879        self, payload: typedefs.JSONObject, /
    -1880    ) -> activity.PostActivityPlayer:
    -1881        player = payload["player"]
    -1882
    -1883        class_hash: typedefs.NoneOr[int] = None
    -1884        if (class_hash := player.get("classHash")) is not None:
    -1885            class_hash = class_hash
    -1886
    -1887        race_hash: typedefs.NoneOr[int] = None
    -1888        if (race_hash := player.get("raceHash")) is not None:
    -1889            race_hash = race_hash
    -1890
    -1891        gender_hash: typedefs.NoneOr[int] = None
    -1892        if (gender_hash := player.get("genderHash")) is not None:
    -1893            gender_hash = gender_hash
    -1894
    -1895        character_class: undefined.UndefinedOr[str] = undefined.Undefined
    -1896        if (
    -1897            character_class := player.get("characterClass")
    -1898        ) and not typedefs.is_unknown(character_class):
    -1899            character_class = character_class
    -1900
    -1901        character_level: typedefs.NoneOr[int] = None
    -1902        if (character_level := player.get("characterLevel")) is not None:
    -1903            character_level = character_level
    -1904
    -1905        return activity.PostActivityPlayer(
    -1906            standing=int(payload["standing"]),
    -1907            score=int(payload["score"]["basic"]["value"]),
    -1908            character_id=payload["characterId"],
    -1909            destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]),
    -1910            character_class=character_class,
    -1911            character_level=character_level,
    -1912            race_hash=race_hash,
    -1913            gender_hash=gender_hash,
    -1914            class_hash=class_hash,
    -1915            light_level=int(player["lightLevel"]),
    -1916            emblem_hash=int(player["emblemHash"]),
    -1917            values=self._deserialize_activity_values(payload["values"]),
    -1918            extended_values=self._deserialize_extended_values(payload["extended"]),
    -1919        )
    -1920
    -1921    def _deserialize_post_activity_team(
    -1922        self, payload: typedefs.JSONObject
    -1923    ) -> activity.PostActivityTeam:
    -1924        return activity.PostActivityTeam(
    -1925            id=payload["teamId"],
    -1926            is_defeated=bool(payload["standing"]["basic"]["value"]),
    -1927            score=int(payload["score"]["basic"]["value"]),
    -1928            name=payload["teamName"],
    -1929        )
    -1930
    -1931    def deserialize_post_activity(
    -1932        self, payload: typedefs.JSONObject
    -1933    ) -> activity.PostActivity:
    -1934        period = time.clean_date(payload["period"])
    -1935        details = payload["activityDetails"]
    -1936        ref_id = int(details["referenceId"])
    -1937        instance_id = int(details["instanceId"])
    -1938        mode = enums.GameMode(details["mode"])
    -1939        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
    -1940        is_private = details["isPrivate"]
    -1941        membership_type = enums.MembershipType(int(details["membershipType"]))
    -1942        return activity.PostActivity(
    -1943            net=self._net,
    -1944            hash=ref_id,
    -1945            membership_type=membership_type,
    -1946            instance_id=instance_id,
    -1947            mode=mode,
    -1948            modes=modes,
    -1949            is_private=is_private,
    -1950            occurred_at=period,
    -1951            starting_phase=int(payload["startingPhaseIndex"]),
    -1952            players=[
    -1953                self.deserialize_post_activity_player(player)
    -1954                for player in payload["entries"]
    -1955            ],
    -1956            teams=[
    -1957                self._deserialize_post_activity_team(team) for team in payload["teams"]
    -1958            ],
    -1959        )
    -1960
    -1961    def _deserialize_aggregated_activity_values(
    -1962        self, payload: typedefs.JSONObject
    -1963    ) -> activity.AggregatedActivityValues:
    -1964        # This ID is always the same for all aggregated values.
    -1965        activity_id = int(payload["fastestCompletionMsForActivity"]["activityId"])
    -1966
    -1967        return activity.AggregatedActivityValues(
    -1968            id=activity_id,
    -1969            fastest_completion_time=(
    -1970                int(payload["fastestCompletionMsForActivity"]["basic"]["value"]),
    -1971                payload["fastestCompletionMsForActivity"]["basic"]["displayValue"],
    -1972            ),
    -1973            completions=int(payload["activityCompletions"]["basic"]["value"]),
    -1974            kills=int(payload["activityKills"]["basic"]["value"]),
    -1975            deaths=int(payload["activityDeaths"]["basic"]["value"]),
    -1976            assists=int(payload["activityAssists"]["basic"]["value"]),
    -1977            seconds_played=(
    -1978                int(payload["activitySecondsPlayed"]["basic"]["value"]),
    -1979                payload["activitySecondsPlayed"]["basic"]["displayValue"],
    -1980            ),
    -1981            wins=int(payload["activityWins"]["basic"]["value"]),
    -1982            goals_missed=int(payload["activityGoalsMissed"]["basic"]["value"]),
    -1983            special_actions=int(payload["activitySpecialActions"]["basic"]["value"]),
    -1984            best_goals_hit=int(payload["activityBestGoalsHit"]["basic"]["value"]),
    -1985            best_single_score=int(
    -1986                payload["activityBestSingleGameScore"]["basic"]["value"]
    -1987            ),
    -1988            goals_hit=int(payload["activityGoalsHit"]["basic"]["value"]),
    -1989            special_score=int(payload["activitySpecialScore"]["basic"]["value"]),
    -1990            kd_assists=int(payload["activityKillsDeathsAssists"]["basic"]["value"]),
    -1991            kd_ratio=float(
    -1992                payload["activityKillsDeathsAssists"]["basic"]["displayValue"]
    -1993            ),
    -1994            precision_kills=int(payload["activityPrecisionKills"]["basic"]["value"]),
    -1995        )
    -1996
    -1997    def deserialize_aggregated_activity(
    -1998        self, payload: typedefs.JSONObject
    -1999    ) -> activity.AggregatedActivity:
    -2000        return activity.AggregatedActivity(
    -2001            hash=int(payload["activityHash"]),
    -2002            values=self._deserialize_aggregated_activity_values(payload["values"]),
    -2003        )
    -2004
    -2005    def deserialize_aggregated_activities(
    -2006        self, payload: typedefs.JSONObject
    -2007    ) -> iterators.FlatIterator[activity.AggregatedActivity]:
    -2008        return iterators.FlatIterator(
    -2009            [
    -2010                self.deserialize_aggregated_activity(activity)
    -2011                for activity in payload["activities"]
    -2012            ]
    -2013        )
    -2014
    -2015    def deserialize_linked_profiles(
    -2016        self, payload: typedefs.JSONObject
    -2017    ) -> profile.LinkedProfile:
    -2018        bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"])
    -2019        error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
    -2020        profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
    -2021
    -2022        if raw_profile := payload.get("profiles"):
    -2023            for pfile in raw_profile:
    -2024                profiles_vec.append(self.deserialize_destiny_membership(pfile))
    -2025
    -2026        if raw_profiles_with_errors := payload.get("profilesWithErrors"):
    -2027            for raw_error_pfile in raw_profiles_with_errors:
    -2028                if error_pfile := raw_error_pfile.get("infoCard"):
    -2029                    error_profiles_vec.append(
    -2030                        self.deserialize_destiny_membership(error_pfile)
    -2031                    )
    -2032
    -2033        return profile.LinkedProfile(
    -2034            net=self._net,
    -2035            bungie=bungie_user,
    -2036            profiles=profiles_vec,
    -2037            profiles_with_errors=error_profiles_vec,
    -2038        )
    -2039
    -2040    def deserialize_clan_banners(
    -2041        self, payload: typedefs.JSONObject
    -2042    ) -> collections.Sequence[clans.ClanBanner]:
    -2043        banners_seq: typing.MutableSequence[clans.ClanBanner] = []
    -2044        if banners := payload.get("clanBannerDecals"):
    -2045            for k, v in banners.items():
    -2046                banner_obj = clans.ClanBanner(
    -2047                    id=int(k),
    -2048                    foreground=assets.Image(v["foregroundPath"]),
    -2049                    background=assets.Image(v["backgroundPath"]),
    -2050                )
    -2051                banners_seq.append(banner_obj)
    -2052        return banners_seq
    -2053
    -2054    def deserialize_public_milestone_content(
    -2055        self, payload: typedefs.JSONObject
    -2056    ) -> milestones.MilestoneContent:
    -2057        items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None
    -2058        if raw_categories := payload.get("itemCategories"):
    -2059            for item in raw_categories:
    -2060                title = undefined.Undefined
    -2061                if raw_title := item.get("title"):
    -2062                    if raw_title != typedefs.Unknown:
    -2063                        title = raw_title
    -2064                if raw_hashes := item.get("itemHashes"):
    -2065                    hashes: collections.Sequence[int] = raw_hashes
    -2066
    -2067                items_categoris = milestones.MilestoneItems(title=title, hashes=hashes)
    -2068
    -2069        about = undefined.Undefined
    -2070        if (raw_about := payload["about"]) != typedefs.Unknown:
    -2071            about = raw_about
    -2072
    -2073        status = undefined.Undefined
    -2074        if (raw_status := payload["status"]) != typedefs.Unknown:
    -2075            status = raw_status
    -2076
    -2077        tips: typing.MutableSequence[undefined.UndefinedOr[str]] = []
    -2078        if raw_tips := payload.get("tips"):
    -2079            for raw_tip in raw_tips:
    -2080                if raw_tip == typedefs.Unknown:
    -2081                    raw_tip = undefined.Undefined
    -2082                tips.append(raw_tip)
    -2083
    -2084        return milestones.MilestoneContent(
    -2085            about=about, status=status, tips=tips, items=items_categoris
    -2086        )
    -2087
    -2088    def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend:
    -2089        name = undefined.Undefined
    -2090        if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown:
    -2091            name = raw_name
    -2092
    -2093        bungie_user: typedefs.NoneOr[user.BungieUser] = None
    -2094
    -2095        if raw_bungie_user := payload.get("bungieNetUser"):
    -2096            bungie_user = self.deserialize_bungie_user(raw_bungie_user)
    -2097
    -2098        return friends.Friend(
    -2099            net=self._net,
    -2100            id=int(payload["lastSeenAsMembershipId"]),
    -2101            name=name,
    -2102            code=payload.get("bungieGlobalDisplayNameCode"),
    -2103            relationship=enums.Relationship(payload["relationship"]),
    -2104            user=bungie_user,
    -2105            online_status=enums.Presence(payload["onlineStatus"]),
    -2106            online_title=payload["onlineTitle"],
    -2107            type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]),
    -2108        )
    -2109
    -2110    def deserialize_friends(
    -2111        self, payload: typedefs.JSONObject
    -2112    ) -> collections.Sequence[friends.Friend]:
    -2113        mut_seq: typing.MutableSequence[friends.Friend] = []
    -2114        if raw_friends := payload.get("friends"):
    -2115            for friend in raw_friends:
    -2116                mut_seq.append(self.deserialize_friend(friend))
    -2117        return mut_seq
    -2118
    -2119    def deserialize_friend_requests(
    -2120        self, payload: typedefs.JSONObject
    -2121    ) -> friends.FriendRequestView:
    -2122        incoming: typing.MutableSequence[friends.Friend] = []
    -2123        outgoing: typing.MutableSequence[friends.Friend] = []
    -2124
    -2125        if raw_incoming_requests := payload.get("incomingRequests"):
    -2126            for incoming_request in raw_incoming_requests:
    -2127                incoming.append(self.deserialize_friend(incoming_request))
    -2128
    -2129        if raw_outgoing_requests := payload.get("outgoingRequests"):
    -2130            for outgoing_request in raw_outgoing_requests:
    -2131                outgoing.append(self.deserialize_friend(outgoing_request))
    -2132
    -2133        return friends.FriendRequestView(incoming=incoming, outgoing=outgoing)
    -2134
    -2135    def _set_fireteam_fields(
    -2136        self, payload: typedefs.JSONObject, total_results: typing.Optional[int] = None
    -2137    ) -> fireteams.Fireteam:
    -2138        activity_type = fireteams.FireteamActivity(payload["activityType"])
    -2139        return fireteams.Fireteam(
    -2140            id=int(payload["fireteamId"]),
    -2141            group_id=int(payload["groupId"]),
    -2142            platform=fireteams.FireteamPlatform(payload["platform"]),
    -2143            is_immediate=payload["isImmediate"],
    -2144            activity_type=activity_type,
    -2145            owner_id=int(payload["ownerMembershipId"]),
    -2146            player_slot_count=payload["playerSlotCount"],
    -2147            available_player_slots=payload["availablePlayerSlotCount"],
    -2148            available_alternate_slots=payload["availableAlternateSlotCount"],
    -2149            title=payload["title"],
    -2150            date_created=time.clean_date(payload["dateCreated"]),
    -2151            is_public=payload["isPublic"],
    -2152            locale=fireteams.FireteamLanguage(payload["locale"]),
    -2153            is_valid=payload["isValid"],
    -2154            last_modified=time.clean_date(payload["datePlayerModified"]),
    -2155            total_results=total_results or 0,
    -2156        )
    -2157
    -2158    def deserialize_fireteams(
    -2159        self, payload: typedefs.JSONObject
    -2160    ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]:
    -2161        fireteams_: typing.MutableSequence[fireteams.Fireteam] = []
    -2162
    -2163        result: list[typedefs.JSONObject]
    -2164        if not (result := payload["results"]):
    -2165            return None
    -2166        for elem in result:
    -2167            fireteams_.append(
    -2168                self._set_fireteam_fields(
    -2169                    elem, total_results=int(payload["totalResults"])
    -2170                )
    -2171            )
    -2172        return fireteams_
    -2173
    -2174    def deserialize_fireteam_destiny_users(
    -2175        self, payload: typedefs.JSONObject
    -2176    ) -> fireteams.FireteamUser:
    -2177        destiny_obj = self.deserialize_destiny_membership(payload)
    -2178        # We could helpers.just return a DestinyMembership object but this is
    -2179        # missing the fireteam display name and id fields.
    -2180        return fireteams.FireteamUser(
    -2181            net=self._net,
    -2182            id=destiny_obj.id,
    -2183            code=destiny_obj.code,
    -2184            icon=destiny_obj.icon,
    -2185            types=destiny_obj.types,
    -2186            type=destiny_obj.type,
    -2187            is_public=destiny_obj.is_public,
    -2188            crossave_override=destiny_obj.crossave_override,
    -2189            name=destiny_obj.name,
    -2190            last_seen_name=destiny_obj.last_seen_name,
    -2191            fireteam_display_name=payload["FireteamDisplayName"],
    -2192            fireteam_membership_id=enums.MembershipType(
    -2193                payload["FireteamMembershipType"]
    -2194            ),
    -2195        )
    -2196
    -2197    def deserialize_fireteam_members(
    -2198        self, payload: typedefs.JSONObject, *, alternatives: bool = False
    -2199    ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]:
    -2200        members_: list[fireteams.FireteamMember] = []
    -2201        if members := payload.get("Members" if not alternatives else "Alternates"):
    -2202            for member in members:
    -2203                bungie_fields = self.deserialize_partial_bungie_user(member)
    -2204                members_fields = fireteams.FireteamMember(
    -2205                    destiny_user=self.deserialize_fireteam_destiny_users(member),
    -2206                    has_microphone=member["hasMicrophone"],
    -2207                    character_id=int(member["characterId"]),
    -2208                    date_joined=time.clean_date(member["dateJoined"]),
    -2209                    last_platform_invite_date=time.clean_date(
    -2210                        member["lastPlatformInviteAttemptDate"]
    -2211                    ),
    -2212                    last_platform_invite_result=int(
    -2213                        member["lastPlatformInviteAttemptResult"]
    -2214                    ),
    -2215                    net=self._net,
    -2216                    name=bungie_fields.name,
    -2217                    id=bungie_fields.id,
    -2218                    icon=bungie_fields.icon,
    -2219                    is_public=bungie_fields.is_public,
    -2220                    crossave_override=bungie_fields.crossave_override,
    -2221                    types=bungie_fields.types,
    -2222                    type=bungie_fields.type,
    -2223                )
    -2224                members_.append(members_fields)
    -2225        else:
    -2226            return None
    -2227        return members_
    -2228
    -2229    def deserialize_available_fireteams(
    -2230        self,
    -2231        data: typedefs.JSONObject,
    -2232        *,
    -2233        no_results: bool = False,
    -2234    ) -> typing.Union[
    -2235        fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam]
    -2236    ]:
    -2237        fireteams_: list[fireteams.AvailableFireteam] = []
    -2238
    -2239        # This needs to be used outside the results
    -2240        # JSON key.
    -2241        if no_results is True:
    -2242            payload = data
    -2243
    -2244        if result := payload.get("results"):
    -2245
    -2246            for fireteam in result:
    -2247                found_fireteams = self._set_fireteam_fields(fireteam["Summary"])
    -2248                fireteams_fields = fireteams.AvailableFireteam(
    -2249                    id=found_fireteams.id,
    -2250                    group_id=found_fireteams.group_id,
    -2251                    platform=found_fireteams.platform,
    -2252                    activity_type=found_fireteams.activity_type,
    -2253                    is_immediate=found_fireteams.is_immediate,
    -2254                    is_public=found_fireteams.is_public,
    -2255                    is_valid=found_fireteams.is_valid,
    -2256                    owner_id=found_fireteams.owner_id,
    -2257                    player_slot_count=found_fireteams.player_slot_count,
    -2258                    available_player_slots=found_fireteams.available_player_slots,
    -2259                    available_alternate_slots=found_fireteams.available_alternate_slots,
    -2260                    title=found_fireteams.title,
    -2261                    date_created=found_fireteams.date_created,
    -2262                    locale=found_fireteams.locale,
    -2263                    last_modified=found_fireteams.last_modified,
    -2264                    total_results=found_fireteams.total_results,
    -2265                    members=self.deserialize_fireteam_members(payload),
    -2266                    alternatives=self.deserialize_fireteam_members(
    -2267                        payload, alternatives=True
    -2268                    ),
    -2269                )
    -2270            fireteams_.append(fireteams_fields)
    -2271            if no_results:
    -2272                return fireteams_fields
    -2273        return fireteams_
    -2274
    -2275    def deserialize_fireteam_party(
    -2276        self, payload: typedefs.JSONObject
    -2277    ) -> fireteams.FireteamParty:
    -2278        last_destination_hash: typing.Optional[int] = None
    -2279        if raw_dest_hash := payload.get("lastOrbitedDestinationHash"):
    -2280            last_destination_hash = int(raw_dest_hash)
    -2281
    -2282        return fireteams.FireteamParty(
    -2283            members=[
    -2284                self._deserialize_fireteam_party_member(member)
    -2285                for member in payload["partyMembers"]
    -2286            ],
    -2287            activity=self._deserialize_fireteam_party_current_activity(
    -2288                payload["currentActivity"]
    -2289            ),
    -2290            settings=self._deserialize_fireteam_party_settings(payload["joinability"]),
    -2291            last_destination_hash=last_destination_hash,
    -2292            tracking=payload["tracking"],
    -2293        )
    -2294
    -2295    def _deserialize_fireteam_party_member(
    -2296        self, payload: typedefs.JSONObject
    -2297    ) -> fireteams.FireteamPartyMember:
    -2298
    -2299        status = fireteams.FireteamPartyMemberState(payload["status"])
    -2300        displayname: undefined.UndefinedOr[str] = undefined.Undefined
    -2301        if raw_name := payload.get("displayName"):
    -2302            displayname = raw_name
    -2303
    -2304        return fireteams.FireteamPartyMember(
    -2305            membership_id=int(payload["membershipId"]),
    -2306            emblem_hash=int(payload["emblemHash"]),
    -2307            status=status,
    -2308            display_name=displayname,
    -2309        )
    -2310
    -2311    def _deserialize_fireteam_party_current_activity(
    -2312        self, payload: typedefs.JSONObject
    -2313    ) -> fireteams.FireteamPartyCurrentActivity:
    -2314        start_date: typing.Optional[datetime.datetime] = None
    -2315        if raw_start_date := payload.get("startTime"):
    -2316            start_date = time.clean_date(raw_start_date)
    -2317
    -2318        end_date: typing.Optional[datetime.datetime] = None
    -2319        if raw_end_date := payload.get("endTime"):
    -2320            end_date = time.clean_date(raw_end_date)
    -2321        return fireteams.FireteamPartyCurrentActivity(
    -2322            start_time=start_date,
    -2323            end_time=end_date,
    -2324            score=float(payload["score"]),
    -2325            highest_opposing_score=float(payload["highestOpposingFactionScore"]),
    -2326            opponenst_count=int(payload["numberOfOpponents"]),
    -2327            player_count=int(payload["numberOfPlayers"]),
    -2328        )
    -2329
    -2330    def _deserialize_fireteam_party_settings(
    -2331        self, payload: typedefs.JSONObject
    -2332    ) -> fireteams.FireteamPartySettings:
    -2333        closed_reasons = enums.ClosedReasons(payload["closedReasons"])
    -2334        return fireteams.FireteamPartySettings(
    -2335            open_slots=int(payload["openSlots"]),
    -2336            privacy_setting=enums.PrivacySetting(int(payload["privacySetting"])),
    -2337            closed_reasons=closed_reasons,
    -2338        )
    -2339
    -2340    def deserialize_seasonal_artifact(
    -2341        self, payload: typedefs.JSONObject
    -2342    ) -> season.Artifact:
    -2343        if raw_artifact := payload.get("seasonalArtifact"):
    -2344            if points := raw_artifact.get("pointProgression"):
    -2345                points_prog = progressions.Progression(
    -2346                    hash=points["progressionHash"],
    -2347                    level=points["level"],
    -2348                    cap=points["levelCap"],
    -2349                    daily_limit=points["dailyLimit"],
    -2350                    weekly_limit=points["weeklyLimit"],
    -2351                    current_progress=points["currentProgress"],
    -2352                    daily_progress=points["dailyProgress"],
    -2353                    needed=points["progressToNextLevel"],
    -2354                    next_level=points["nextLevelAt"],
    -2355                )
    -2356
    -2357            if bonus := raw_artifact.get("powerBonusProgression"):
    -2358                power_bonus_prog = progressions.Progression(
    -2359                    hash=bonus["progressionHash"],
    -2360                    level=bonus["level"],
    -2361                    cap=bonus["levelCap"],
    -2362                    daily_limit=bonus["dailyLimit"],
    -2363                    weekly_limit=bonus["weeklyLimit"],
    -2364                    current_progress=bonus["currentProgress"],
    -2365                    daily_progress=bonus["dailyProgress"],
    -2366                    needed=bonus["progressToNextLevel"],
    -2367                    next_level=bonus["nextLevelAt"],
    -2368                )
    -2369            artifact = season.Artifact(
    -2370                net=self._net,
    -2371                hash=raw_artifact["artifactHash"],
    -2372                power_bonus=raw_artifact["powerBonus"],
    -2373                acquired_points=raw_artifact["pointsAcquired"],
    -2374                bonus=power_bonus_prog,
    -2375                points=points_prog,
    -2376            )
    -2377        return artifact
    -2378
    -2379    def deserialize_profile_progression(
    -2380        self, payload: typedefs.JSONObject
    -2381    ) -> profile.ProfileProgression:
    -2382        return profile.ProfileProgression(
    -2383            artifact=self.deserialize_seasonal_artifact(payload["data"]),
    -2384            checklist={
    -2385                int(check_id): checklists
    -2386                for check_id, checklists in payload["data"]["checklists"].items()
    -2387            },
    -2388        )
    -2389
    -2390    def deserialize_instanced_item(
    -2391        self, payload: typedefs.JSONObject
    -2392    ) -> items.ItemInstance:
    -2393        damage_type_hash: typing.Optional[int] = None
    -2394        if raw_damagetype_hash := payload.get("damageTypeHash"):
    -2395            damage_type_hash = int(raw_damagetype_hash)
    -2396
    -2397        required_hashes: typing.Optional[collections.Collection[int]] = None
    -2398        if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"):
    -2399            required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes]
    -2400
    -2401        breaker_type: typing.Optional[items.ItemBreakerType] = None
    -2402        if raw_break_type := payload.get("breakerType"):
    -2403            breaker_type = items.ItemBreakerType(int(raw_break_type))
    -2404
    -2405        breaker_type_hash: typing.Optional[int] = None
    -2406        if raw_break_type_hash := payload.get("breakerTypeHash"):
    -2407            breaker_type_hash = int(raw_break_type_hash)
    -2408
    -2409        energy: typing.Optional[items.ItemEnergy] = None
    -2410        if raw_energy := payload.get("energy"):
    -2411            energy = self.deserialize_item_energy(raw_energy)
    -2412
    -2413        primary_stats = None
    -2414        if raw_primary_stats := payload.get("primaryStat"):
    -2415            primary_stats = self.deserialize_item_stats_view(raw_primary_stats)
    -2416
    -2417        return items.ItemInstance(
    -2418            damage_type=enums.DamageType(int(payload["damageType"])),
    -2419            damage_type_hash=damage_type_hash,
    -2420            primary_stat=primary_stats,
    -2421            item_level=int(payload["itemLevel"]),
    -2422            quality=int(payload["quality"]),
    -2423            is_equipped=payload["isEquipped"],
    -2424            can_equip=payload["canEquip"],
    -2425            equip_required_level=int(payload["equipRequiredLevel"]),
    -2426            required_equip_unlock_hashes=required_hashes,
    -2427            cant_equip_reason=int(payload["cannotEquipReason"]),
    -2428            breaker_type=breaker_type,
    -2429            breaker_type_hash=breaker_type_hash,
    -2430            energy=energy,
    -2431        )
    -2432
    -2433    def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy:
    -2434        energy_hash: typing.Optional[int] = None
    -2435        if raw_energy_hash := payload.get("energyTypeHash"):
    -2436            energy_hash = int(raw_energy_hash)
    -2437
    -2438        return items.ItemEnergy(
    -2439            hash=energy_hash,
    -2440            type=items.ItemEnergyType(int(payload["energyType"])),
    -2441            capacity=int(payload["energyCapacity"]),
    -2442            used_energy=int(payload["energyUsed"]),
    -2443            unused_energy=int(payload["energyUnused"]),
    -2444        )
    -2445
    -2446    def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk:
    -2447        perk_hash: typing.Optional[int] = None
    -2448        if raw_perk_hash := payload.get("perkHash"):
    -2449            perk_hash = int(raw_perk_hash)
    -2450
    -2451        return items.ItemPerk(
    -2452            hash=perk_hash,
    -2453            icon=assets.Image(payload["iconPath"]),
    -2454            is_active=payload["isActive"],
    -2455            is_visible=payload["visible"],
    -2456        )
    -2457
    -2458    def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket:
    -2459        plug_hash: typing.Optional[int] = None
    -2460        if raw_plug_hash := payload.get("plugHash"):
    -2461            plug_hash = int(raw_plug_hash)
    -2462
    -2463        enable_fail_indexes: typing.Optional[list[int]] = None
    -2464        if raw_indexes := payload.get("enableFailIndexes"):
    -2465            enable_fail_indexes = [int(index) for index in raw_indexes]
    -2466
    -2467        return items.ItemSocket(
    -2468            plug_hash=plug_hash,
    -2469            is_enabled=payload["isEnabled"],
    -2470            enable_fail_indexes=enable_fail_indexes,
    -2471            is_visible=payload.get("visible"),
    -2472        )
    -2473
    -2474    def deserialize_item_stats_view(
    -2475        self, payload: typedefs.JSONObject
    -2476    ) -> items.ItemStatsView:
    -2477        return items.ItemStatsView(
    -2478            stat_hash=payload.get("statHash"), value=payload.get("value")
    -2479        )
    -2480
    -2481    def deserialize_plug_item_state(
    -2482        self, payload: typedefs.JSONObject
    -2483    ) -> items.PlugItemState:
    -2484        item_hash: typing.Optional[int] = None
    -2485        if raw_item_hash := payload.get("plugItemHash"):
    -2486            item_hash = int(raw_item_hash)
    -2487
    -2488        insert_fail_indexes: typedefs.NoneOr[list[int]] = None
    -2489        if raw_fail_indexes := payload.get("insertFailIndexes"):
    -2490            insert_fail_indexes = [int(k) for k in raw_fail_indexes]
    -2491
    -2492        enable_fail_indexes: typedefs.NoneOr[list[int]] = None
    -2493        if raw_enabled_indexes := payload.get("enableFailIndexes"):
    -2494            enable_fail_indexes = [int(k) for k in raw_enabled_indexes]
    -2495
    -2496        return items.PlugItemState(
    -2497            item_hash=item_hash,
    -2498            insert_fail_indexes=insert_fail_indexes,
    -2499            enable_fail_indexes=enable_fail_indexes,
    -2500            is_enabled=payload["enabled"],
    -2501            can_insert=payload["canInsert"],
    -2502        )
    +    
    +            
    190    async def fetch_bungie_user(self, id: int, /) -> user.BungieUser:
    +191        """Fetch a Bungie user by their BungieNet id.
    +192
    +193        .. note::
    +194            This returns a Bungie user membership only. Take a look at `Client.fetch_membership_from_id`
    +195            for other memberships.
    +196
    +197        Parameters
    +198        ----------
    +199        id: `int`
    +200            The user id.
    +201
    +202        Returns
    +203        -------
    +204        `aiobungie.crates.user.BungieUser`
    +205            A Bungie user.
    +206
    +207        Raises
    +208        ------
    +209        `aiobungie.error.NotFound`
    +210            The user was not found.
    +211        """
    +212        payload = await self.rest.fetch_bungie_user(id)
    +213
    +214        return self.factory.deserialize_bungie_user(payload)
     
    -

    The base deserialization factory class for all aiobungie objects.

    +

    Fetch a Bungie user by their BungieNet id.

    + +
    + +

    This returns a Bungie user membership only. Take a look at Client.fetch_membership_from_id +for other memberships.

    -

    Highly inspired hikari entity factory used to deserialize JSON responses from the REST client and turning them -into a aiobungie.crates Python classes.

    +
    Parameters
    -
    - -
    - - Factory(net: aiobungie.traits.Netrunner) +
      +
    • id (int): +The user id.
    • +
    - +
    Returns
    -
    - -
    70    def __init__(self, net: traits.Netrunner) -> None:
    -71        self._net = net
    -
    +
      +
    • aiobungie.crates.user.BungieUser: A Bungie user.
    • +
    + +
    Raises
    + +
    -
    -
    - +
    +
    - def - deserialize_bungie_user(self, data: dict[str, typing.Any]) -> aiobungie.crates.user.BungieUser: + async def + search_users( self, name: str, /) -> aiobungie.Iterator[aiobungie.crates.user.SearchableDestinyUser]: - +
    - -
    73    def deserialize_bungie_user(self, data: typedefs.JSONObject) -> user.BungieUser:
    -74        return user.BungieUser(
    -75            id=int(data["membershipId"]),
    -76            created_at=time.clean_date(data["firstAccess"]),
    -77            name=data.get("cachedBungieGlobalDisplayName", undefined.Undefined),
    -78            is_deleted=data["isDeleted"],
    -79            about=data["about"],
    -80            updated_at=time.clean_date(data["lastUpdate"]),
    -81            psn_name=data.get("psnDisplayName", None),
    -82            stadia_name=data.get("stadiaDisplayName", None),
    -83            steam_name=data.get("steamDisplayName", None),
    -84            twitch_name=data.get("twitchDisplayName", None),
    -85            blizzard_name=data.get("blizzardDisplayName", None),
    -86            status=data["statusText"],
    -87            locale=data["locale"],
    -88            picture=assets.Image(path=str(data["profilePicturePath"])),
    -89            code=data.get("cachedBungieGlobalDisplayNameCode", None),
    -90            unique_name=data.get("uniqueName", None),
    -91            theme_id=int(data["profileTheme"]),
    -92            show_activity=bool(data["showActivity"]),
    -93            theme_name=data["profileThemeName"],
    -94            display_title=data["userTitleDisplay"],
    -95        )
    +    
    +            
    216    async def search_users(
    +217        self, name: str, /
    +218    ) -> iterators.Iterator[user.SearchableDestinyUser]:
    +219        """Search for players and return all players that matches the same name.
    +220
    +221        Parameters
    +222        ----------
    +223        name : `buildins.str`
    +224            The user name.
    +225
    +226        Returns
    +227        -------
    +228        `aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]`
    +229            A sequence of destiny memberships.
    +230        """
    +231        payload = await self.rest.search_users(name)
    +232
    +233        return iterators.Iterator(
    +234            [
    +235                self.factory.deserialize_searched_user(user)
    +236                for user in payload["searchResults"]
    +237            ]
    +238        )
     
    -

    Deserialize a raw JSON Bungie.net user only payload into a user object.

    - -
    - -

    This only returns the Bungie.net user and not the Destiny memberships.

    - -
    +

    Search for players and return all players that matches the same name.

    Parameters
    Returns
    -
    - +
    +
    - def - deserialize_partial_bungie_user( self, payload: dict[str, typing.Any]) -> aiobungie.crates.user.PartialBungieUser: + async def + fetch_user_themes(self) -> collections.abc.Sequence[aiobungie.crates.user.UserThemes]: - +
    - -
     97    def deserialize_partial_bungie_user(
    - 98        self, payload: typedefs.JSONObject
    - 99    ) -> user.PartialBungieUser:
    -100        return user.PartialBungieUser(
    -101            net=self._net,
    -102            types=[
    -103                enums.MembershipType(type_)
    -104                for type_ in payload.get("applicableMembershipTypes", [])
    -105            ],
    -106            name=payload.get("displayName", undefined.Undefined),
    -107            id=int(payload["membershipId"]),
    -108            crossave_override=enums.MembershipType(payload["crossSaveOverride"]),
    -109            is_public=payload["isPublic"],
    -110            icon=assets.Image(payload.get("iconPath", "")),
    -111            type=enums.MembershipType(payload["membershipType"]),
    -112        )
    +    
    +            
    240    async def fetch_user_themes(self) -> collections.Sequence[user.UserThemes]:
    +241        """Fetch all available user themes.
    +242
    +243        Returns
    +244        -------
    +245        `collections.Sequence[aiobungie.crates.user.UserThemes]`
    +246            A sequence of user themes.
    +247        """
    +248        data = await self.rest.fetch_user_themes()
    +249
    +250        return self.factory.deserialize_user_themes(data)
     
    -

    Deserialize a raw JSON of a partial bungieNetUserInfo.

    +

    Fetch all available user themes.

    + +
    Returns
    + +
      +
    • collections.Sequence[aiobungie.crates.user.UserThemes]: A sequence of user themes.
    • +
    +
    + + +
    +
    + +
    + + async def + fetch_hard_types( self, credential: int, type: Union[int, aiobungie.CredentialType] = <CredentialType.STEAMID: 12>, /) -> aiobungie.crates.user.HardLinkedMembership: + + + +
    + +
    252    async def fetch_hard_types(
    +253        self,
    +254        credential: int,
    +255        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
    +256        /,
    +257    ) -> user.HardLinkedMembership:
    +258        """Gets any hard linked membership given a credential.
    +259        Only works for credentials that are public just `aiobungie.CredentialType.STEAMID` right now.
    +260        Cross Save aware.
    +261
    +262        Parameters
    +263        ----------
    +264        credential: `int`
    +265            A valid SteamID64
    +266        type: `aiobungie.CredentialType`
    +267            The credential type. This must not be changed
    +268            Since its only credential that works "currently"
    +269
    +270        Returns
    +271        -------
    +272        `aiobungie.crates.user.HardLinkedMembership`
    +273            Information about the hard linked data.
    +274        """
    +275
    +276        payload = await self.rest.fetch_hardlinked_credentials(credential, type)
    +277
    +278        return user.HardLinkedMembership(
    +279            id=int(payload["membershipId"]),
    +280            type=enums.MembershipType(payload["membershipType"]),
    +281            cross_save_type=enums.MembershipType(payload["CrossSaveOverriddenType"]),
    +282        )
    +
    -

    A partial user is a bungie.net user payload with missing information from -the main BungieUser object.

    + +

    Gets any hard linked membership given a credential. +Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now. +Cross Save aware.

    Parameters
    Returns
    -
    - +
    +
    - def - deserialize_destiny_membership( self, payload: dict[str, typing.Any]) -> aiobungie.crates.user.DestinyMembership: + async def + fetch_membership_from_id( self, id: int, /, type: Union[int, aiobungie.MembershipType] = <MembershipType.NONE: 0>) -> aiobungie.crates.user.User: - +
    - -
    114    def deserialize_destiny_membership(
    -115        self, payload: typedefs.JSONObject
    -116    ) -> user.DestinyMembership:
    -117        name: undefined.UndefinedOr[str] = undefined.Undefined
    -118        if (
    -119            raw_name := payload.get("bungieGlobalDisplayName", "")
    -120        ) and not typedefs.is_unknown(raw_name):
    -121            name = raw_name
    -122
    -123        return user.DestinyMembership(
    -124            net=self._net,
    -125            id=int(payload["membershipId"]),
    -126            name=name,
    -127            code=payload.get("bungieGlobalDisplayNameCode", None),
    -128            last_seen_name=payload.get("LastSeenDisplayName")
    -129            or payload.get("displayName")  # noqa: W503
    -130            or "",  # noqa: W503
    -131            type=enums.MembershipType(payload["membershipType"]),
    -132            is_public=payload["isPublic"],
    -133            crossave_override=enums.MembershipType(payload["crossSaveOverride"]),
    -134            icon=assets.Image(payload.get("iconPath", "")),
    -135            types=[
    -136                enums.MembershipType(type_)
    -137                for type_ in payload.get("applicableMembershipTypes", [])
    -138            ],
    -139        )
    +    
    +            
    284    async def fetch_membership_from_id(
    +285        self,
    +286        id: int,
    +287        /,
    +288        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    +289    ) -> user.User:
    +290        """Fetch Bungie user's memberships from their id.
    +291
    +292        Notes
    +293        -----
    +294        * This returns both BungieNet membership and a sequence of the player's DestinyMemberships
    +295        Which includes Stadia, Xbox, Steam and PSN memberships if the player has them,
    +296        see `aiobungie.crates.user.DestinyMembership` for more details.
    +297        * If you only want the bungie user. Consider using `Client.fetch_user` method.
    +298
    +299        Parameters
    +300        ----------
    +301        id : `int`
    +302            The user's id.
    +303        type : `aiobungie.MembershipType`
    +304            The user's membership type.
    +305
    +306        Returns
    +307        -------
    +308        `aiobungie.crates.User`
    +309            A Bungie user with their membership types.
    +310
    +311        Raises
    +312        ------
    +313        aiobungie.NotFound
    +314            The requested user was not found.
    +315        """
    +316        payload = await self.rest.fetch_membership_from_id(id, type)
    +317
    +318        return self.factory.deserialize_user(payload)
     
    -

    Deserialize a raw JSON of destinyUserInfo destiny membership information.

    +

    Fetch Bungie user's memberships from their id.

    + +
    Notes
    + +
      +
    • This returns both BungieNet membership and a sequence of the player's DestinyMemberships +Which includes Stadia, Xbox, Steam and PSN memberships if the player has them, +see aiobungie.crates.user.DestinyMembership for more details.
    • +
    • If you only want the bungie user. Consider using Client.fetch_user method.
    • +
    Parameters
    Returns
      -
    • aiobungie.crates.user.DestinyMembership: A Destiny 2 membership.
    • +
    • aiobungie.crates.User: A Bungie user with their membership types.
    • +
    + +
    Raises
    + +
    -
    - +
    +
    - def - deserialize_destiny_memberships( self, data: list[typing.Any]) -> collections.abc.Sequence[aiobungie.crates.user.DestinyMembership]: + async def + fetch_user_credentials( self, access_token: str, membership_id: int, /) -> collections.abc.Sequence[aiobungie.crates.user.UserCredentials]: - +
    - -
    141    def deserialize_destiny_memberships(
    -142        self, data: typedefs.JSONArray
    -143    ) -> collections.Sequence[user.DestinyMembership]:
    -144        return [self.deserialize_destiny_membership(membership) for membership in data]
    +    
    +            
    320    async def fetch_user_credentials(
    +321        self, access_token: str, membership_id: int, /
    +322    ) -> collections.Sequence[user.UserCredentials]:
    +323        """Fetch an array of credential types attached to the requested account.
    +324
    +325        .. note::
    +326            This method require OAuth2 Bearer access token.
    +327
    +328        Parameters
    +329        ----------
    +330        access_token : `str`
    +331            The bearer access token associated with the bungie account.
    +332        membership_id : `int`
    +333            The id of the membership to return.
    +334
    +335        Returns
    +336        -------
    +337        `collections.Sequence[aiobungie.crates.UserCredentials]`
    +338            A sequence of the attached user credentials.
    +339
    +340        Raises
    +341        ------
    +342        `aiobungie.Unauthorized`
    +343            The access token was wrong or no access token passed.
    +344        """
    +345        resp = await self.rest.fetch_user_credentials(access_token, membership_id)
    +346
    +347        return self.factory.deserialize_user_credentials(resp)
     
    -

    Deserialize a raw JSON payload/array of destinyUserInfo.

    +

    Fetch an array of credential types attached to the requested account.

    + +
    + +

    This method require OAuth2 Bearer access token.

    + +
    Parameters
      -
    • payload (aiobungie.typedefs.JSONArray): -The JSON payload.
    • +
    • access_token (str): +The bearer access token associated with the bungie account.
    • +
    • membership_id (int): +The id of the membership to return.
    Returns
      -
    • collections.Sequence[aiobungie.crates.user.DestinyMembership]: A sequence of Destiny 2 memberships.
    • +
    • collections.Sequence[aiobungie.crates.UserCredentials]: A sequence of the attached user credentials.
    • +
    + +
    Raises
    + +
    -
    - +
    +
    - def - deserialize_user(self, data: dict[str, typing.Any]) -> aiobungie.crates.user.User: + async def + fetch_profile( self, member_id: int, type: Union[int, aiobungie.MembershipType], components: list[aiobungie.ComponentType], auth: Optional[str] = None) -> aiobungie.crates.components.Component: - +
    - -
    146    def deserialize_user(self, data: typedefs.JSONObject) -> user.User:
    -147
    -148        primary_membership_id: typing.Optional[int] = None
    -149        if raw_primary_id := data.get("primaryMembershipId"):
    -150            primary_membership_id = int(raw_primary_id)
    -151
    -152        return user.User(
    -153            bungie=self.deserialize_bungie_user(data["bungieNetUser"]),
    -154            destiny=self.deserialize_destiny_memberships(data["destinyMemberships"]),
    -155            primary_membership_id=primary_membership_id,
    -156        )
    +    
    +            
    351    async def fetch_profile(
    +352        self,
    +353        member_id: int,
    +354        type: typedefs.IntAnd[enums.MembershipType],
    +355        components: list[enums.ComponentType],
    +356        auth: typing.Optional[str] = None,
    +357    ) -> components.Component:
    +358        """
    +359        Fetch a bungie profile passing components to the request.
    +360
    +361        Parameters
    +362        ----------
    +363        member_id: `int`
    +364            The member's id.
    +365        type: `aiobungie.MembershipType`
    +366            A valid membership type.
    +367        components : `list[aiobungie.ComponentType]`
    +368            List of profile components to collect and return.
    +369
    +370        Other Parameters
    +371        ----------------
    +372        auth : `typing.Optional[str]`
    +373            A Bearer access_token to make the request with.
    +374            This is optional and limited to components that only requires an Authorization token.
    +375
    +376        Returns
    +377        --------
    +378        `aiobungie.crates.Component`
    +379            A Destiny 2 player profile with its components.
    +380            Only passed components will be available if they exists. Otherwise they will be `None`
    +381
    +382        Raises
    +383        ------
    +384        `aiobungie.MembershipTypeError`
    +385            The provided membership type was invalid.
    +386        """
    +387        data = await self.rest.fetch_profile(member_id, type, components, auth)
    +388        return self.factory.deserialize_components(data)
     
    -

    Deserialize a raw JSON results of fetched user memberships and Bungie.net user its their id.

    +

    Fetch a bungie profile passing components to the request.

    Parameters
    + +
    Other Parameters
    + +
      +
    • auth (typing.Optional[str]): +A Bearer access_token to make the request with. +This is optional and limited to components that only requires an Authorization token.
    Returns
    + +
    Raises
    + +
    -
    - +
    +
    - def - deserialize_searched_user( self, payload: dict[str, typing.Any]) -> aiobungie.crates.user.SearchableDestinyUser: + async def + fetch_linked_profiles( self, member_id: int, member_type: Union[int, aiobungie.MembershipType], /, *, all: bool = False) -> aiobungie.crates.profile.LinkedProfile: - +
    - -
    158    def deserialize_searched_user(
    -159        self, payload: typedefs.JSONObject
    -160    ) -> user.SearchableDestinyUser:
    -161        name: undefined.UndefinedOr[str] = undefined.Undefined
    -162        if (raw_name := payload["bungieGlobalDisplayName"]) and not typedefs.is_unknown(
    -163            raw_name
    -164        ):
    -165            name = raw_name
    -166
    -167        code: typing.Optional[int] = None
    -168        if raw_code := payload.get("bungieGlobalDisplayNameCode"):
    -169            code = int(raw_code)
    -170
    -171        bungie_id: typing.Optional[int] = None
    -172        if raw_bungie_id := payload.get("bungieNetMembershipId"):
    -173            bungie_id = int(raw_bungie_id)
    -174
    -175        return user.SearchableDestinyUser(
    -176            name=name,
    -177            code=code,
    -178            bungie_id=bungie_id,
    -179            memberships=self.deserialize_destiny_memberships(
    -180                payload["destinyMemberships"]
    -181            ),
    -182        )
    +    
    +            
    390    async def fetch_linked_profiles(
    +391        self,
    +392        member_id: int,
    +393        member_type: typedefs.IntAnd[enums.MembershipType],
    +394        /,
    +395        *,
    +396        all: bool = False,
    +397    ) -> profile.LinkedProfile:
    +398        """Returns a summary information about all profiles linked to the requested member.
    +399
    +400        The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships.
    +401
    +402        .. note::
    +403            It will only return linked accounts whose linkages you are allowed to view.
    +404
    +405        Parameters
    +406        ----------
    +407        member_id : `int`
    +408            The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID.
    +409        member_type : `aiobungie.MembershipType`
    +410            The type for the membership whose linked Destiny account you want to return.
    +411
    +412        Other Parameters
    +413        ----------------
    +414        all : `bool`
    +415            If provided and set to `True`, All memberships regardless
    +416            of whether they're obscured by overrides will be returned,
    +417
    +418            If provided and set to `False`, Only available memberships will be returned.
    +419            The default for this is `False`.
    +420
    +421        Returns
    +422        -------
    +423        `aiobungie.crates.profile.LinkedProfile`
    +424            A linked profile object.
    +425        """
    +426        resp = await self.rest.fetch_linked_profiles(member_id, member_type, all=all)
    +427
    +428        return self.factory.deserialize_linked_profiles(resp)
     
    -

    Deserialize the results of user search details.

    +

    Returns a summary information about all profiles linked to the requested member.

    -
    Parameters
    +

    The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships.

    - +
    -
    Returns
    +

    It will only return linked accounts whose linkages you are allowed to view.

    -
    +
    Parameters
    -
    -
    - -
    - - def - deserialize_user_credentials( self, payload: list[typing.Any]) -> collections.abc.Sequence[aiobungie.crates.user.UserCredentials]: - - - -
    - -
    184    def deserialize_user_credentials(
    -185        self, payload: typedefs.JSONArray
    -186    ) -> collections.Sequence[user.UserCredentials]:
    -187        return [
    -188            user.UserCredentials(
    -189                type=enums.CredentialType(int(creds["credentialType"])),
    -190                display_name=creds["credentialDisplayName"],
    -191                is_public=creds["isPublic"],
    -192                self_as_string=creds.get("credentialAsString", undefined.Undefined),
    -193            )
    -194            for creds in payload
    -195        ]
    -
    - - -

    Deserialize a JSON array of Bungie user credentials.

    +
      +
    • member_id (int): +The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID.
    • +
    • member_type (aiobungie.MembershipType): +The type for the membership whose linked Destiny account you want to return.
    • +
    -
    Parameters
    +
    Other Parameters
      -
    • payload (aiobungie.typedefs.JSONArray): -The JSON payload.
    • +
    • all (bool): +If provided and set to True, All memberships regardless +of whether they're obscured by overrides will be returned,

      + +

      If provided and set to False, Only available memberships will be returned. +The default for this is False.

    Returns
    -
    - -
    -
    @staticmethod
    - - def - set_themese_attrs( payload: list[typing.Any], /) -> Collection[aiobungie.crates.user.UserThemes]: - - - -
    - -
    197    @staticmethod
    -198    def set_themese_attrs(
    -199        payload: typedefs.JSONArray, /
    -200    ) -> typing.Collection[user.UserThemes]:
    -201        return [
    -202            user.UserThemes(
    -203                id=int(entry["userThemeId"]),
    -204                name=entry["userThemeName"]
    -205                if "userThemeName" in entry
    -206                else undefined.Undefined,
    -207                description=entry["userThemeDescription"]
    -208                if "userThemeDescription" in entry
    -209                else undefined.Undefined,
    -210            )
    -211            for entry in payload
    -212        ]
    -
    - - - - -
    -
    - +
    +
    - def - deserialize_user_themes( self, payload: list[typing.Any]) -> collections.abc.Sequence[aiobungie.crates.user.UserThemes]: + async def + fetch_player( self, name: str, code: int, /, type: Union[int, aiobungie.MembershipType] = <MembershipType.ALL: -1>) -> collections.abc.Sequence[aiobungie.crates.user.DestinyMembership]: - +
    - -
    214    def deserialize_user_themes(
    -215        self, payload: typedefs.JSONArray
    -216    ) -> collections.Sequence[user.UserThemes]:
    -217        return list(self.set_themese_attrs(payload))
    +    
    +            
    430    async def fetch_player(
    +431        self,
    +432        name: str,
    +433        code: int,
    +434        /,
    +435        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
    +436    ) -> collections.Sequence[user.DestinyMembership]:
    +437        """Fetch a Destiny 2 player's memberships.
    +438
    +439        Parameters
    +440        -----------
    +441        name: `str`
    +442            The unique Bungie player name.
    +443        code : `int`
    +444            The unique Bungie display name code.
    +445        type: `aiobungie.internal.enums.MembershipType`
    +446            The player's membership type, e,g. XBOX, STEAM, PSN
    +447
    +448        Returns
    +449        --------
    +450        `collections.Sequence[aiobungie.crates.DestinyMembership]`
    +451            A sequence of the found Destiny 2 player memberships.
    +452            An empty sequence will be returned if no one found.
    +453
    +454        Raises
    +455        ------
    +456        `aiobungie.MembershipTypeError`
    +457            The provided membership type was invalid.
    +458        """
    +459        resp = await self.rest.fetch_player(name, code, type)
    +460
    +461        return self.factory.deserialize_destiny_memberships(resp)
     
    -

    Deserialize a raw JSON array of Bungie user themes.

    +

    Fetch a Destiny 2 player's memberships.

    Parameters
    Returns
      -
    • collections.Sequence[aiobungie.crates.user.UserThemes]: A sequence of bungie user themes.
    • +
    • collections.Sequence[aiobungie.crates.DestinyMembership]: A sequence of the found Destiny 2 player memberships. +An empty sequence will be returned if no one found.
    • +
    + +
    Raises
    + +
    -
    - +
    +
    - def - deserialize_clan(self, payload: dict[str, typing.Any]) -> aiobungie.crates.clans.Clan: + async def + fetch_character( self, member_id: int, membership_type: Union[int, aiobungie.MembershipType], character_id: int, components: list[aiobungie.ComponentType], auth: Optional[str] = None) -> aiobungie.crates.components.CharacterComponent: - +
    - -
    219    def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan:
    -220
    -221        # This is kinda redundant
    -222        data = payload
    -223
    -224        # This is always outside the details.
    -225        current_user_map: typing.Optional[
    -226            collections.Mapping[str, clans.ClanMember]
    -227        ] = None
    -228        if raw_current_user_map := payload.get("currentUserMemberMap"):
    -229            current_user_map = {
    -230                membership_type: self.deserialize_clan_member(membership)
    -231                for membership_type, membership in raw_current_user_map.items()
    -232            }
    -233
    -234        try:
    -235            data = payload["detail"]
    -236        except KeyError:
    -237            pass
    -238
    -239        id = data["groupId"]
    -240        name = data["name"]
    -241        created_at = data["creationDate"]
    -242        member_count = data["memberCount"]
    -243        about = data["about"]
    -244        motto = data["motto"]
    -245        is_public = data["isPublic"]
    -246        banner = assets.Image(str(data["bannerPath"]))
    -247        avatar = assets.Image(str(data["avatarPath"]))
    -248        tags = data["tags"]
    -249        type = data["groupType"]
    -250
    -251        features = data["features"]
    -252        features_obj = clans.ClanFeatures(
    -253            max_members=features["maximumMembers"],
    -254            max_membership_types=features["maximumMembershipsOfGroupType"],
    -255            capabilities=features["capabilities"],
    -256            membership_types=features["membershipTypes"],
    -257            invite_permissions=features["invitePermissionOverride"],
    -258            update_banner_permissions=features["updateBannerPermissionOverride"],
    -259            update_culture_permissions=features["updateCulturePermissionOverride"],
    -260            join_level=features["joinLevel"],
    -261        )
    -262
    -263        information: typedefs.JSONObject = data["clanInfo"]
    -264        progression: collections.Mapping[int, progressions.Progression] = {
    -265            int(prog_hash): self.deserialize_progressions(prog)
    -266            for prog_hash, prog in information["d2ClanProgressions"].items()
    -267        }
    -268
    -269        founder: typedefs.NoneOr[clans.ClanMember] = None
    -270        if raw_founder := payload.get("founder"):
    -271            founder = self.deserialize_clan_member(raw_founder)
    -272
    -273        return clans.Clan(
    -274            net=self._net,
    -275            id=int(id),
    -276            name=name,
    -277            type=enums.GroupType(type),
    -278            created_at=time.clean_date(created_at),
    -279            member_count=member_count,
    -280            motto=motto,
    -281            about=about,
    -282            is_public=is_public,
    -283            banner=banner,
    -284            avatar=avatar,
    -285            tags=tags,
    -286            features=features_obj,
    -287            owner=founder,
    -288            progressions=progression,
    -289            call_sign=information["clanCallsign"],
    -290            banner_data=information["clanBannerData"],
    -291            chat_security=data["chatSecurity"],
    -292            conversation_id=int(data["conversationId"]),
    -293            allow_chat=data["allowChat"],
    -294            theme=data["theme"],
    -295            current_user_membership=current_user_map,
    -296        )
    +    
    +            
    463    async def fetch_character(
    +464        self,
    +465        member_id: int,
    +466        membership_type: typedefs.IntAnd[enums.MembershipType],
    +467        character_id: int,
    +468        components: list[enums.ComponentType],
    +469        auth: typing.Optional[str] = None,
    +470    ) -> components.CharacterComponent:
    +471        """Fetch a Destiny 2 character.
    +472
    +473        Parameters
    +474        ----------
    +475        member_id: `int`
    +476            A valid bungie member id.
    +477        character_id: `int`
    +478            The Destiny character id to retrieve.
    +479        membership_type: `aiobungie.internal.enums.MembershipType`
    +480            The member's membership type.
    +481        components: `list[aiobungie.ComponentType]`
    +482            Multiple arguments of character components to collect and return.
    +483
    +484        Other Parameters
    +485        ----------------
    +486        auth : `typing.Optional[str]`
    +487            A Bearer access_token to make the request with.
    +488            This is optional and limited to components that only requires an Authorization token.
    +489
    +490        Returns
    +491        -------
    +492        `aiobungie.crates.CharacterComponent`
    +493            A Bungie character component.
    +494
    +495        `aiobungie.MembershipTypeError`
    +496            The provided membership type was invalid.
    +497        """
    +498        resp = await self.rest.fetch_character(
    +499            member_id, membership_type, character_id, components, auth
    +500        )
    +501
    +502        return self.factory.deserialize_character_component(resp)
     
    -

    Deserialize a raw JSON payload of Bungie clan information.

    +

    Fetch a Destiny 2 character.

    Parameters
    + +
    Other Parameters
    + +
      +
    • auth (typing.Optional[str]): +A Bearer access_token to make the request with. +This is optional and limited to components that only requires an Authorization token.
    Returns
    -
    - +
    +
    - def - deserialize_clan_member( self, data: dict[str, typing.Any], /) -> aiobungie.crates.clans.ClanMember: + async def + fetch_unique_weapon_history( self, membership_id: int, character_id: int, membership_type: Union[int, aiobungie.MembershipType]) -> collections.abc.Sequence[aiobungie.crates.activity.ExtendedWeaponValues]: - +
    - -
    298    def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember:
    -299        destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"])
    -300        return clans.ClanMember(
    -301            net=self._net,
    -302            last_seen_name=destiny_user.last_seen_name,
    -303            id=destiny_user.id,
    -304            name=destiny_user.name,
    -305            icon=destiny_user.icon,
    -306            last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])),
    -307            group_id=int(data["groupId"]),
    -308            joined_at=time.clean_date(data["joinDate"]),
    -309            types=destiny_user.types,
    -310            is_public=destiny_user.is_public,
    -311            type=destiny_user.type,
    -312            code=destiny_user.code,
    -313            is_online=data["isOnline"],
    -314            crossave_override=destiny_user.crossave_override,
    -315            bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"])
    -316            if "bungieNetUserInfo" in data
    -317            else None,
    -318            member_type=enums.ClanMemberType(int(data["memberType"])),
    -319        )
    +    
    +            
    504    async def fetch_unique_weapon_history(
    +505        self,
    +506        membership_id: int,
    +507        character_id: int,
    +508        membership_type: typedefs.IntAnd[enums.MembershipType],
    +509    ) -> collections.Sequence[activity.ExtendedWeaponValues]:
    +510        """Fetch details about unique weapon usage for a character. Includes all exotics.
    +511
    +512        Parameters
    +513        ----------
    +514        membership_id : `int`
    +515            The Destiny user membership id.
    +516        character_id : `int`
    +517            The character id to retrieve.
    +518        membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    +519            The Destiny user's membership type.
    +520
    +521        Returns
    +522        -------
    +523        `collections.Sequence[aiobungie.crates.ExtendedWeaponValues]`
    +524            A sequence of the weapon's extended values.
    +525        """
    +526        resp = await self._rest.fetch_unique_weapon_history(
    +527            membership_id, character_id, membership_type
    +528        )
    +529
    +530        return [
    +531            self._factory.deserialize_extended_weapon_values(weapon)
    +532            for weapon in resp["weapons"]
    +533        ]
     
    -

    Deserialize a JSON payload of a clan member information.

    +

    Fetch details about unique weapon usage for a character. Includes all exotics.

    Parameters
    Returns
    -
    - +
    +
    - def - deserialize_clan_members( self, data: dict[str, typing.Any], /) -> aiobungie.FlatIterator[aiobungie.crates.clans.ClanMember]: + async def + fetch_activities( self, member_id: int, character_id: int, mode: Union[int, aiobungie.GameMode], *, membership_type: Union[int, aiobungie.MembershipType] = <MembershipType.ALL: -1>, page: int = 0, limit: int = 250) -> aiobungie.Iterator[aiobungie.crates.activity.Activity]: - +
    - -
    321    def deserialize_clan_members(
    -322        self, data: typedefs.JSONObject, /
    -323    ) -> iterators.FlatIterator[clans.ClanMember]:
    -324        return iterators.FlatIterator(
    -325            [self.deserialize_clan_member(member) for member in data["results"]]
    -326        )
    +    
    +            
    537    async def fetch_activities(
    +538        self,
    +539        member_id: int,
    +540        character_id: int,
    +541        mode: typedefs.IntAnd[enums.GameMode],
    +542        *,
    +543        membership_type: typedefs.IntAnd[
    +544            enums.MembershipType
    +545        ] = enums.MembershipType.ALL,
    +546        page: int = 0,
    +547        limit: int = 250,
    +548    ) -> iterators.Iterator[activity.Activity]:
    +549        """Fetch a Destiny 2 activity for the specified character id.
    +550
    +551        Parameters
    +552        ----------
    +553        member_id: `int`
    +554            The user id that starts with `4611`.
    +555        character_id: `int`
    +556            The id of the character to retrieve the activities for.
    +557        mode: `aiobungie.typedefs.IntAnd[aiobungie.internal.enums.GameMode]`
    +558            This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc.
    +559
    +560        Other Parameters
    +561        ----------------
    +562        membership_type: `aiobungie.internal.enums.MembershipType`
    +563            The Member ship type, if nothing was passed than it will return all.
    +564        page: int
    +565            The page number. Default is `0`
    +566        limit: int
    +567            Limit the returned result. Default is `250`.
    +568
    +569        Returns
    +570        -------
    +571        `aiobungie.iterators.Iterator[aiobungie.crates.Activity]`
    +572            An iterator of the player's activities.
    +573
    +574        Raises
    +575        ------
    +576        `aiobungie.MembershipTypeError`
    +577            The provided membership type was invalid.
    +578        """
    +579        resp = await self.rest.fetch_activities(
    +580            member_id,
    +581            character_id,
    +582            mode,
    +583            membership_type=membership_type,
    +584            page=page,
    +585            limit=limit,
    +586        )
    +587
    +588        return self.factory.deserialize_activities(resp)
     
    -

    Deserialize a JSON payload of a clan members information.

    +

    Fetch a Destiny 2 activity for the specified character id.

    Parameters
    -
    Returns
    +
    Other Parameters
      -
    • aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]: An iterator of clan members of the deserialized payload.
    • +
    • membership_type (aiobungie.MembershipType): +The Member ship type, if nothing was passed than it will return all.
    • +
    • page (int): +The page number. Default is 0
    • +
    • limit (int): +Limit the returned result. Default is 250.
    -
    - - -
    -
    - -
    - - def - deserialize_group_member( self, payload: dict[str, typing.Any]) -> aiobungie.crates.clans.GroupMember: - - - -
    - -
    328    def deserialize_group_member(
    -329        self, payload: typedefs.JSONObject
    -330    ) -> clans.GroupMember:
    -331        member = payload["member"]
    -332        return clans.GroupMember(
    -333            net=self._net,
    -334            join_date=time.clean_date(member["joinDate"]),
    -335            group_id=int(member["groupId"]),
    -336            member_type=enums.ClanMemberType(member["memberType"]),
    -337            is_online=member["isOnline"],
    -338            last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])),
    -339            inactive_memberships=payload.get("areAllMembershipsInactive", None),
    -340            member=self.deserialize_destiny_membership(member["destinyUserInfo"]),
    -341            group=self.deserialize_clan(payload["group"]),
    -342        )
    -
    - -

    Deserialize a JSON payload of group information for a member.

    - -
    Parameters
    +
    Returns
    -
    Returns
    +
    Raises
    -
    - +
    +
    - def - deserialize_clan_conversations( self, payload: list[typing.Any]) -> collections.abc.Sequence[aiobungie.crates.clans.ClanConversation]: + async def + fetch_post_activity(self, instance_id: int, /) -> aiobungie.crates.activity.PostActivity: - +
    - -
    360    def deserialize_clan_conversations(
    -361        self, payload: typedefs.JSONArray
    -362    ) -> collections.Sequence[clans.ClanConversation]:
    -363        return [self._deserialize_clan_conversation(conv) for conv in payload]
    +    
    +            
    590    async def fetch_post_activity(self, instance_id: int, /) -> activity.PostActivity:
    +591        """Fetch a post activity details.
    +592
    +593        Parameters
    +594        ----------
    +595        instance_id: `int`
    +596            The activity instance id.
    +597
    +598        Returns
    +599        -------
    +600        `aiobungie.crates.PostActivity`
    +601           A post activity object.
    +602        """
    +603        resp = await self.rest.fetch_post_activity(instance_id)
    +604
    +605        return self.factory.deserialize_post_activity(resp)
     
    -

    Deserialize a JSON array of a clan conversations information.

    +

    Fetch a post activity details.

    Parameters
    Returns
    -
    - +
    +
    - def - deserialize_app_owner( self, payload: dict[str, typing.Any]) -> aiobungie.crates.application.ApplicationOwner: + async def + fetch_aggregated_activity_stats( self, character_id: int, membership_id: int, membership_type: Union[int, aiobungie.MembershipType]) -> aiobungie.Iterator[aiobungie.crates.activity.AggregatedActivity]: - +
    - -
    365    def deserialize_app_owner(
    -366        self, payload: typedefs.JSONObject
    -367    ) -> application.ApplicationOwner:
    -368        return application.ApplicationOwner(
    -369            net=self._net,
    -370            name=payload.get("bungieGlobalDisplayName", undefined.Undefined),
    -371            id=int(payload["membershipId"]),
    -372            type=enums.MembershipType(payload["membershipType"]),
    -373            icon=assets.Image(str(payload["iconPath"])),
    -374            is_public=payload["isPublic"],
    -375            code=payload.get("bungieGlobalDisplayNameCode", None),
    -376        )
    +    
    +            
    607    async def fetch_aggregated_activity_stats(
    +608        self,
    +609        character_id: int,
    +610        membership_id: int,
    +611        membership_type: typedefs.IntAnd[enums.MembershipType],
    +612    ) -> iterators.Iterator[activity.AggregatedActivity]:
    +613        """Fetch aggregated activity stats for a character.
    +614
    +615        Parameters
    +616        ----------
    +617        character_id: `int`
    +618            The id of the character to retrieve the activities for.
    +619        membership_id: `int`
    +620            The id of the user that started with `4611`.
    +621        membership_type: `aiobungie.internal.enums.MembershipType`
    +622            The Member ship type.
    +623
    +624        Returns
    +625        -------
    +626        `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]`
    +627            An iterator of the player's activities.
    +628
    +629        Raises
    +630        ------
    +631        `aiobungie.MembershipTypeError`
    +632            The provided membership type was invalid.
    +633        """
    +634        resp = await self.rest.fetch_aggregated_activity_stats(
    +635            character_id, membership_id, membership_type
    +636        )
    +637
    +638        return self.factory.deserialize_aggregated_activities(resp)
     
    -

    Deserialize a JSON payload of Bungie Developer portal application owner information.

    +

    Fetch aggregated activity stats for a character.

    Parameters
      -
    • payload (aiobungie.typedefs.JSONObject): -The JSON payload.
    • +
    • character_id (int): +The id of the character to retrieve the activities for.
    • +
    • membership_id (int): +The id of the user that started with 4611.
    • +
    • membership_type (aiobungie.MembershipType): +The Member ship type.
    Returns
      -
    • aiobungie.crates.application.ApplicationOwner: An application owner.
    • +
    • aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]: An iterator of the player's activities.
    • +
    + +
    Raises
    + +
    -
    - +
    +
    - def - deserialize_app( self, payload: dict[str, typing.Any]) -> aiobungie.crates.application.Application: + async def + fetch_clan_from_id( self, id: int, /, access_token: Optional[str] = None) -> aiobungie.crates.clans.Clan: - +
    - -
    378    def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application:
    -379        return application.Application(
    -380            id=int(payload["applicationId"]),
    -381            name=payload["name"],
    -382            link=payload["link"],
    -383            status=payload["status"],
    -384            redirect_url=payload.get("redirectUrl", None),
    -385            created_at=time.clean_date(str(payload["creationDate"])),
    -386            published_at=time.clean_date(str(payload["firstPublished"])),
    -387            owner=self.deserialize_app_owner(payload["team"][0]["user"]),  # type: ignore
    -388            scope=payload.get("scope", undefined.Undefined),
    -389        )
    +    
    +            
    642    async def fetch_clan_from_id(
    +643        self,
    +644        id: int,
    +645        /,
    +646        access_token: typing.Optional[str] = None,
    +647    ) -> clans.Clan:
    +648        """Fetch a Bungie Clan by its id.
    +649
    +650        Parameters
    +651        -----------
    +652        id: `int`
    +653            The clan id.
    +654
    +655        Returns
    +656        --------
    +657        `aiobungie.crates.Clan`
    +658            An Bungie clan.
    +659
    +660        Raises
    +661        ------
    +662        `aiobungie.NotFound`
    +663            The clan was not found.
    +664        """
    +665        resp = await self.rest.fetch_clan_from_id(id, access_token)
    +666
    +667        return self.factory.deserialize_clan(resp)
     
    -

    Deserialize a JSON payload of Bungie Developer portal application information.

    +

    Fetch a Bungie Clan by its id.

    Parameters
    Returns
    + +
    Raises
    + +
    -
    - +
    +
    - def - deserialize_profile( self, payload: dict[str, typing.Any], /) -> Optional[aiobungie.crates.profile.Profile]: + async def + fetch_clan( self, name: str, /, access_token: Optional[str] = None, *, type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> aiobungie.crates.clans.Clan: - +
    - -
    412    def deserialize_profile(
    -413        self, payload: typedefs.JSONObject, /
    -414    ) -> typing.Optional[profile.Profile]:
    -415        if (raw_profile := payload.get("data")) is None:
    -416            return None
    -417
    -418        payload = raw_profile
    -419        id = int(payload["userInfo"]["membershipId"])
    -420        name = payload["userInfo"]["displayName"]
    -421        is_public = payload["userInfo"]["isPublic"]
    -422        type = enums.MembershipType(payload["userInfo"]["membershipType"])
    -423        last_played = time.clean_date(str(payload["dateLastPlayed"]))
    -424        character_ids = [int(cid) for cid in payload["characterIds"]]
    -425        power_cap = payload["currentSeasonRewardPowerCap"]
    -426
    -427        return profile.Profile(
    -428            id=int(id),
    -429            name=name,
    -430            is_public=is_public,
    -431            type=type,
    -432            last_played=last_played,
    -433            character_ids=character_ids,
    -434            power_cap=power_cap,
    -435            net=self._net,
    -436        )
    +    
    +            
    669    async def fetch_clan(
    +670        self,
    +671        name: str,
    +672        /,
    +673        access_token: typing.Optional[str] = None,
    +674        *,
    +675        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    +676    ) -> clans.Clan:
    +677        """Fetch a Clan by its name.
    +678        This method will return the first clan found with given name.
    +679
    +680        Parameters
    +681        ----------
    +682        name: `str`
    +683            The clan name
    +684
    +685        Other Parameters
    +686        ----------------
    +687        access_token : `typing.Optional[str]`
    +688            An optional access token to make the request with.
    +689
    +690            If the token was bound to a member of the clan,
    +691            This field `aiobungie.crates.Clan.current_user_membership` will be available
    +692            and will return the membership of the user who made this request.
    +693        type : `aiobungie.GroupType`
    +694            The group type, Default is aiobungie.GroupType.CLAN.
    +695
    +696        Returns
    +697        -------
    +698        `aiobungie.crates.Clan`
    +699            A Bungie clan.
    +700
    +701        Raises
    +702        ------
    +703        `aiobungie.NotFound`
    +704            The clan was not found.
    +705        """
    +706        resp = await self.rest.fetch_clan(name, access_token, type=type)
    +707
    +708        return self.factory.deserialize_clan(resp)
     
    -

    Deserialize a JSON payload of Bungie.net profile information.

    +

    Fetch a Clan by its name. +This method will return the first clan found with given name.

    Parameters
    + +
    Other Parameters
    + +
      +
    • access_token (typing.Optional[str]): +An optional access token to make the request with.

      + +

      If the token was bound to a member of the clan, +This field aiobungie.crates.Clan.current_user_membership will be available +and will return the membership of the user who made this request.

    • +
    • type (aiobungie.GroupType): +The group type, Default is aiobungie.GroupType.CLAN.
    Returns
    + +
    Raises
    + +
    -
    - +
    +
    - def - deserialize_profile_item( self, payload: dict[str, typing.Any]) -> aiobungie.crates.profile.ProfileItemImpl: + async def + fetch_clan_conversations( self, clan_id: int, /) -> collections.abc.Sequence[aiobungie.crates.clans.ClanConversation]: - +
    - -
    438    def deserialize_profile_item(
    -439        self, payload: typedefs.JSONObject
    -440    ) -> profile.ProfileItemImpl:
    -441
    -442        instance_id: typing.Optional[int] = None
    -443        if raw_instance_id := payload.get("itemInstanceId"):
    -444            instance_id = int(raw_instance_id)
    -445
    -446        version_number: typing.Optional[int] = None
    -447        if raw_version := payload.get("versionNumber"):
    -448            version_number = int(raw_version)
    -449
    -450        transfer_status = enums.TransferStatus(payload["transferStatus"])
    -451
    -452        return profile.ProfileItemImpl(
    -453            net=self._net,
    -454            hash=payload["itemHash"],
    -455            quantity=payload["quantity"],
    -456            bind_status=enums.ItemBindStatus(payload["bindStatus"]),
    -457            location=enums.ItemLocation(payload["location"]),
    -458            bucket=payload["bucketHash"],
    -459            transfer_status=transfer_status,
    -460            lockable=payload["lockable"],
    -461            state=enums.ItemState(payload["state"]),
    -462            dismantel_permissions=payload["dismantlePermission"],
    -463            is_wrapper=payload["isWrapper"],
    -464            instance_id=instance_id,
    -465            version_number=version_number,
    -466            ornament_id=payload.get("overrideStyleItemHash"),
    -467        )
    +    
    +            
    710    async def fetch_clan_conversations(
    +711        self, clan_id: int, /
    +712    ) -> collections.Sequence[clans.ClanConversation]:
    +713        """Fetch the conversations/chat channels of the given clan id.
    +714
    +715        Parameters
    +716        ----------
    +717        clan_id : `int`
    +718            The clan id.
    +719
    +720        Returns
    +721        `collections.Sequence[aiobungie.crates.ClanConversation]`
    +722            A sequence of the clan chat channels.
    +723        """
    +724        resp = await self.rest.fetch_clan_conversations(clan_id)
    +725
    +726        return self.factory.deserialize_clan_conversations(resp)
     
    -

    Deserialize a JSON payload of a singular profile component item.

    +

    Fetch the conversations/chat channels of the given clan id.

    Parameters
    - -
    Returns
    - -
    -
    - +
    +
    - def - deserialize_objectives( self, payload: dict[str, typing.Any]) -> aiobungie.crates.records.Objective: + async def + fetch_clan_admins( self, clan_id: int, /) -> aiobungie.Iterator[aiobungie.crates.clans.ClanMember]: - +
    - -
    469    def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective:
    -470        return records.Objective(
    -471            net=self._net,
    -472            hash=payload["objectiveHash"],
    -473            visible=payload["visible"],
    -474            complete=payload["complete"],
    -475            completion_value=payload["completionValue"],
    -476            progress=payload.get("progress"),
    -477            destination_hash=payload.get("destinationHash"),
    -478            activity_hash=payload.get("activityHash"),
    -479        )
    +    
    +            
    728    async def fetch_clan_admins(
    +729        self, clan_id: int, /
    +730    ) -> iterators.Iterator[clans.ClanMember]:
    +731        """Fetch the clan founder and admins.
    +732
    +733        Parameters
    +734        ----------
    +735        clan_id : `int`
    +736            The clan id.
    +737
    +738        Returns
    +739        -------
    +740        `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]`
    +741            An iterator over the found clan admins and founder.
    +742
    +743        Raises
    +744        ------
    +745        `aiobungie.NotFound`
    +746            The requested clan was not found.
    +747        """
    +748        resp = await self.rest.fetch_clan_admins(clan_id)
    +749
    +750        return self.factory.deserialize_clan_members(resp)
     
    -

    Deserialize a JSON payload of an objective found in a record profile component.

    +

    Fetch the clan founder and admins.

    Parameters
      -
    • payload (aiobungie.internal.helpers.JsonObject): -The JSON payload.
    • +
    • clan_id (int): +The clan id.
    Returns
      -
    • aiobungie.crates.records.Objective: A record objective object.
    • +
    • aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]: An iterator over the found clan admins and founder.
    • +
    + +
    Raises
    + +
    -
    - +
    +
    - def - deserialize_records( self, payload: dict[str, typing.Any], scores: Optional[aiobungie.crates.records.RecordScores] = None, **nodes: int) -> aiobungie.crates.records.Record: + async def + fetch_groups_for_member( self, member_id: int, member_type: Union[int, aiobungie.MembershipType], /, *, filter: int = 0, group_type: aiobungie.GroupType = <GroupType.CLAN: 1>) -> collections.abc.Sequence[aiobungie.crates.clans.GroupMember]: - +
    - -
    481    def deserialize_records(
    -482        self,
    -483        payload: typedefs.JSONObject,
    -484        scores: typing.Optional[records.RecordScores] = None,
    -485        **nodes: int,
    -486    ) -> records.Record:
    -487        objectives: typing.Optional[list[records.Objective]] = None
    -488        interval_objectives: typing.Optional[list[records.Objective]] = None
    -489        record_state: typedefs.IntAnd[records.RecordState]
    -490
    -491        record_state = records.RecordState(payload["state"])
    -492
    -493        if raw_objs := payload.get("objectives"):
    -494            objectives = [self.deserialize_objectives(obj) for obj in raw_objs]
    -495
    -496        if raw_interval_objs := payload.get("intervalObjectives"):
    -497            interval_objectives = [
    -498                self.deserialize_objectives(obj) for obj in raw_interval_objs
    -499            ]
    -500
    -501        return records.Record(
    -502            scores=scores,
    -503            categories_node_hash=nodes.get("categories_hash", undefined.Undefined),
    -504            seals_node_hash=nodes.get("seals_hash", undefined.Undefined),
    -505            state=record_state,
    -506            objectives=objectives,
    -507            interval_objectives=interval_objectives,
    -508            redeemed_count=payload.get("intervalsRedeemedCount", 0),
    -509            completion_times=payload.get("completedCount", None),
    -510            reward_visibility=payload.get("rewardVisibilty", None),
    -511        )
    +    
    +            
    752    async def fetch_groups_for_member(
    +753        self,
    +754        member_id: int,
    +755        member_type: typedefs.IntAnd[enums.MembershipType],
    +756        /,
    +757        *,
    +758        filter: int = 0,
    +759        group_type: enums.GroupType = enums.GroupType.CLAN,
    +760    ) -> collections.Sequence[clans.GroupMember]:
    +761        """Fetch information about the groups that a given member has joined.
    +762
    +763        Parameters
    +764        ----------
    +765        member_id : `int`
    +766            The member's id
    +767        member_type : `aiobungie.MembershipType`
    +768            The member's membership type.
    +769
    +770        Other Parameters
    +771        ----------------
    +772        filter : `int`
    +773            Filter apply to list of joined groups. This Default to `0`
    +774        group_type : `aiobungie.GroupType`
    +775            The group's type.
    +776            This is always set to `aiobungie.GroupType.CLAN` and should not be changed.
    +777
    +778        Returns
    +779        -------
    +780        `collections.Sequence[aiobungie.crates.GroupMember]`
    +781            A sequence of joined groups for the fetched member.
    +782        """
    +783        resp = await self.rest.fetch_groups_for_member(
    +784            member_id, member_type, filter=filter, group_type=group_type
    +785        )
    +786
    +787        return [
    +788            self.factory.deserialize_group_member(group) for group in resp["results"]
    +789        ]
     
    -

    Deserialize a JSON object of a profile record component.

    +

    Fetch information about the groups that a given member has joined.

    Parameters
      -
    • payload (aiobungie.internal.helpers.JsonObject): -The JSON object payload
    • -
    • scores (typing.Optional[records.RecordScores]): -The records scores object. -This exists only to keep the signature of aiobungie.crates.CharacterRecord with the record object. -As it will always be None in that object.
    • -
    • **nodes (int): -An int kwargs use to grab the node hashes while deserializing components.
    • +
    • member_id (int): +The member's id
    • +
    • member_type (aiobungie.MembershipType): +The member's membership type.
    • +
    + +
    Other Parameters
    + +
      +
    • filter (int): +Filter apply to list of joined groups. This Default to 0
    • +
    • group_type (aiobungie.GroupType): +The group's type. +This is always set to aiobungie.GroupType.CLAN and should not be changed.
    Returns
      -
    • aiobungie.records.Record: A standard implementation of a profile record component.
    • +
    • collections.Sequence[aiobungie.crates.GroupMember]: A sequence of joined groups for the fetched member.
    -
    - +
    +
    - def - deserialize_character_records( self, payload: dict[str, typing.Any], scores: Optional[aiobungie.crates.records.RecordScores] = None, record_hashes: Optional[list[int]] = None) -> aiobungie.crates.records.CharacterRecord: + async def + fetch_potential_groups_for_member( self, member_id: int, member_type: Union[int, aiobungie.MembershipType], /, *, filter: int = 0, group_type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> collections.abc.Sequence[aiobungie.crates.clans.GroupMember]: - +
    - -
    513    def deserialize_character_records(
    -514        self,
    -515        payload: typedefs.JSONObject,
    -516        scores: typing.Optional[records.RecordScores] = None,
    -517        record_hashes: typing.Optional[list[int]] = None,
    -518    ) -> records.CharacterRecord:
    -519
    -520        record = self.deserialize_records(payload, scores)
    -521        return records.CharacterRecord(
    -522            scores=scores,
    -523            categories_node_hash=record.categories_node_hash,
    -524            seals_node_hash=record.seals_node_hash,
    -525            state=record.state,
    -526            objectives=record.objectives,
    -527            interval_objectives=record.interval_objectives,
    -528            redeemed_count=payload.get("intervalsRedeemedCount", 0),
    -529            completion_times=payload.get("completedCount"),
    -530            reward_visibility=payload.get("rewardVisibilty"),
    -531            record_hashes=record_hashes or [],
    -532        )
    +    
    +            
    791    async def fetch_potential_groups_for_member(
    +792        self,
    +793        member_id: int,
    +794        member_type: typedefs.IntAnd[enums.MembershipType],
    +795        /,
    +796        *,
    +797        filter: int = 0,
    +798        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    +799    ) -> collections.Sequence[clans.GroupMember]:
    +800        """Fetch the potential groups for a clan member.
    +801
    +802        Parameters
    +803        ----------
    +804        member_id : `int`
    +805            The member's id
    +806        member_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    +807            The member's membership type.
    +808
    +809        Other Parameters
    +810        ----------------
    +811        filter : `int`
    +812            Filter apply to list of joined groups. This Default to `0`
    +813        group_type : `aiobungie.typedefs.IntAnd[aiobungie.GroupType]`
    +814            The group's type.
    +815            This is always set to `aiobungie.GroupType.CLAN` and should not be changed.
    +816
    +817        Returns
    +818        -------
    +819        `collections.Sequence[aiobungie.crates.GroupMember]`
    +820            A sequence of joined potential groups for the fetched member.
    +821        """
    +822        resp = await self.rest.fetch_potential_groups_for_member(
    +823            member_id, member_type, filter=filter, group_type=group_type
    +824        )
    +825
    +826        return [
    +827            self.factory.deserialize_group_member(group) for group in resp["results"]
    +828        ]
     
    -

    Deserialize a JSON object of a profile character record component.

    - -

    This almost does the same this as deserialize_records but -has more fields which can only be found in a character record.

    +

    Fetch the potential groups for a clan member.

    Parameters
    + +
    Other Parameters
    + +
      +
    • filter (int): +Filter apply to list of joined groups. This Default to 0
    • +
    • group_type (aiobungie.typedefs.IntAnd[aiobungie.GroupType]): +The group's type. +This is always set to aiobungie.GroupType.CLAN and should not be changed.
    Returns
      -
    • aiobungie.records.CharacterRecord: A standard implementation of a profile character record component.
    • +
    • collections.Sequence[aiobungie.crates.GroupMember]: A sequence of joined potential groups for the fetched member.
    -
    - +
    +
    - def - deserialize_character_dye(self, payload: dict[str, typing.Any]) -> aiobungie.crates.character.Dye: + async def + fetch_clan_members( self, clan_id: int, /, *, name: Optional[str] = None, type: Union[int, aiobungie.MembershipType] = <MembershipType.NONE: 0>) -> aiobungie.Iterator[aiobungie.crates.clans.ClanMember]: - +
    - -
    534    def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye:
    -535        return character.Dye(
    -536            channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"]
    -537        )
    +    
    +            
    830    async def fetch_clan_members(
    +831        self,
    +832        clan_id: int,
    +833        /,
    +834        *,
    +835        name: typing.Optional[str] = None,
    +836        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    +837    ) -> iterators.Iterator[clans.ClanMember]:
    +838        """Fetch Bungie clan members.
    +839
    +840        Parameters
    +841        ----------
    +842        clan_id : `int`
    +843            The clans id
    +844
    +845        Other Parameters
    +846        ----------------
    +847        name : `typing.Optional[str]`
    +848            If provided, Only players matching this name will be returned.
    +849        type : `aiobungie.MembershipType`
    +850            An optional clan member's membership type.
    +851            This parameter is used to filter the returned results
    +852            by the provided membership, For an example XBox memberships only,
    +853            Otherwise will return all memberships.
    +854
    +855        Returns
    +856        -------
    +857        `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]`
    +858            An iterator over the bungie clan members.
    +859
    +860        Raises
    +861        ------
    +862        `aiobungie.NotFound`
    +863            The clan was not found.
    +864        """
    +865        resp = await self.rest.fetch_clan_members(clan_id, type=type, name=name)
    +866
    +867        return self.factory.deserialize_clan_members(resp)
     
    -

    Deserialize a JSON payload of a character's dye information.

    +

    Fetch Bungie clan members.

    Parameters
    + +
    Other Parameters
    + +
      +
    • name (typing.Optional[str]): +If provided, Only players matching this name will be returned.
    • +
    • type (aiobungie.MembershipType): +An optional clan member's membership type. +This parameter is used to filter the returned results +by the provided membership, For an example XBox memberships only, +Otherwise will return all memberships.
    Returns
      -
    • aiobungie.crates.character.Dye: Information about a character dye object.
    • +
    • aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]: An iterator over the bungie clan members.
    • +
    + +
    Raises
    + +
    -
    - +
    +
    - def - deserialize_character_customization( self, payload: dict[str, typing.Any]) -> aiobungie.crates.character.CustomizationOptions: + async def + fetch_clan_banners(self) -> collections.abc.Sequence[aiobungie.crates.clans.ClanBanner]: - +
    - -
    539    def deserialize_character_customization(
    -540        self, payload: typedefs.JSONObject
    -541    ) -> character.CustomizationOptions:
    -542        return character.CustomizationOptions(
    -543            personality=payload["personality"],
    -544            face=payload["face"],
    -545            skin_color=payload["skinColor"],
    -546            lip_color=payload["lipColor"],
    -547            eye_color=payload["eyeColor"],
    -548            hair_colors=payload.get("hairColors", []),
    -549            feature_colors=payload.get("featureColors", []),
    -550            decal_color=payload["decalColor"],
    -551            wear_helmet=payload["wearHelmet"],
    -552            hair_index=payload["hairIndex"],
    -553            feature_index=payload["featureIndex"],
    -554            decal_index=payload["decalIndex"],
    -555        )
    +    
    +            
    869    async def fetch_clan_banners(self) -> collections.Sequence[clans.ClanBanner]:
    +870        """Fetch the clan banners.
    +871
    +872        Returns
    +873        -------
    +874        `collections.Sequence[aiobungie.crates.ClanBanner]`
    +875            A sequence of the clan banners.
    +876        """
    +877        resp = await self.rest.fetch_clan_banners()
    +878
    +879        return self.factory.deserialize_clan_banners(resp)
     
    -

    Deserialize a JSON payload of a character customization information found in character -render data profile component.

    - -
    Parameters
    - - +

    Fetch the clan banners.

    Returns
      -
    • aiobungie.crates.character.CustomizationOptions: Information about a character customs object.
    • +
    • collections.Sequence[aiobungie.crates.ClanBanner]: A sequence of the clan banners.
    -
    - +
    +
    - def - deserialize_character_minimal_equipments( self, payload: dict[str, typing.Any]) -> aiobungie.crates.character.MinimalEquipments: + async def + kick_clan_member( self, access_token: str, /, group_id: int, membership_id: int, membership_type: Union[int, aiobungie.MembershipType]) -> aiobungie.crates.clans.Clan: - +
    - -
    557    def deserialize_character_minimal_equipments(
    -558        self, payload: typedefs.JSONObject
    -559    ) -> character.MinimalEquipments:
    -560        dyes = None
    -561        if raw_dyes := payload.get("dyes"):
    -562            if raw_dyes:
    -563                dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes]
    -564        return character.MinimalEquipments(
    -565            net=self._net, item_hash=payload["itemHash"], dyes=dyes
    -566        )
    +    
    +            
    882    async def kick_clan_member(
    +883        self,
    +884        access_token: str,
    +885        /,
    +886        group_id: int,
    +887        membership_id: int,
    +888        membership_type: typedefs.IntAnd[enums.MembershipType],
    +889    ) -> clans.Clan:
    +890        """Kick a member from the clan.
    +891
    +892        .. note::
    +893            This request requires OAuth2: oauth2: `AdminGroups` scope.
    +894
    +895        Parameters
    +896        ----------
    +897        access_token : `str`
    +898            The bearer access token associated with the bungie account.
    +899        group_id: `int`
    +900            The group id.
    +901        membership_id : `int`
    +902            The member id to kick.
    +903        membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]`
    +904            The member's membership type.
    +905
    +906        Returns
    +907        -------
    +908        `aiobungie.crates.clan.Clan`
    +909            The clan that the member was kicked from.
    +910        """
    +911        resp = await self.rest.kick_clan_member(
    +912            access_token,
    +913            group_id=group_id,
    +914            membership_id=membership_id,
    +915            membership_type=membership_type,
    +916        )
    +917
    +918        return self.factory.deserialize_clan(resp)
     
    -

    Deserialize a singular JSON peer view of equipment found in character render data profile component.

    +

    Kick a member from the clan.

    + +
    + +

    This request requires OAuth2: oauth2: AdminGroups scope.

    + +
    Parameters
    Returns
      -
    • aiobungie.crates.character.MinimalEquipments: A minimal equipment object.
    • +
    • aiobungie.crates.clan.Clan: The clan that the member was kicked from.
    -
    - +
    +
    - def - deserialize_character_render_data( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.character.RenderedData: + async def + fetch_clan_weekly_rewards(self, clan_id: int) -> aiobungie.crates.milestones.Milestone: - +
    - -
    568    def deserialize_character_render_data(
    -569        self, payload: typedefs.JSONObject, /
    -570    ) -> character.RenderedData:
    -571        return character.RenderedData(
    -572            net=self._net,
    -573            customization=self.deserialize_character_customization(
    -574                payload["customization"]
    -575            ),
    -576            custom_dyes=[
    -577                self.deserialize_character_dye(dye)
    -578                for dye in payload["customDyes"]
    -579                if dye
    -580            ],
    -581            equipment=[
    -582                self.deserialize_character_minimal_equipments(equipment)
    -583                for equipment in payload["peerView"]["equipment"]
    -584            ],
    -585        )
    +    
    +            
    920    async def fetch_clan_weekly_rewards(self, clan_id: int) -> milestones.Milestone:
    +921        """Fetch a Bungie clan's weekly reward state.
    +922
    +923        Parameters
    +924        ----------
    +925        clan_id : `int`
    +926            The clan's id.
    +927
    +928        Returns
    +929        -------
    +930        `aiobungie.crates.Milestone`
    +931            A runtime status of the clan's milestone data.
    +932        """
    +933
    +934        resp = await self.rest.fetch_clan_weekly_rewards(clan_id)
    +935
    +936        return self.factory.deserialize_milestone(resp)
     
    -

    Deserialize a JSON payload of a profile character render data component.

    +

    Fetch a Bungie clan's weekly reward state.

    Parameters
    Returns
    -
    - +
    +
    - def - deserialize_available_activity( self, payload: dict[str, typing.Any]) -> aiobungie.crates.activity.AvailableActivity: + async def + fetch_inventory_item(self, hash: int, /) -> aiobungie.crates.entity.InventoryEntity: - +
    - -
    587    def deserialize_available_activity(
    -588        self, payload: typedefs.JSONObject
    -589    ) -> activity.AvailableActivity:
    -590        return activity.AvailableActivity(
    -591            hash=payload["activityHash"],
    -592            is_new=payload["isNew"],
    -593            is_completed=payload["isCompleted"],
    -594            is_visible=payload["isVisible"],
    -595            display_level=payload.get("displayLevel"),
    -596            recommended_light=payload.get("recommendedLight"),
    -597            difficulty=activity.Difficulty(payload["difficultyTier"]),
    -598            can_join=payload["canJoin"],
    -599            can_lead=payload["canLead"],
    -600        )
    +    
    +            
    940    async def fetch_inventory_item(self, hash: int, /) -> entity.InventoryEntity:
    +941        """Fetch a static inventory item entity given a its hash.
    +942
    +943        Parameters
    +944        ----------
    +945        hash: `int`
    +946            Inventory item's hash.
    +947
    +948        Returns
    +949        -------
    +950        `aiobungie.crates.InventoryEntity`
    +951            A bungie inventory item.
    +952        """
    +953        resp = await self.rest.fetch_inventory_item(hash)
    +954
    +955        return self.factory.deserialize_inventory_entity(resp)
     
    -

    Deserialize a JSON payload of an available activities.

    - -

    This method is used to deserialize an array of aiobungie.crates.CharacterActivity.available_activities.

    +

    Fetch a static inventory item entity given a its hash.

    Parameters
    Returns
    -
    - +
    +
    - def - deserialize_character_activity( self, payload: dict[str, typing.Any]) -> aiobungie.crates.activity.CharacterActivity: + async def + fetch_objective_entity(self, hash: int, /) -> aiobungie.crates.entity.ObjectiveEntity: - +
    - -
    602    def deserialize_character_activity(
    -603        self, payload: typedefs.JSONObject
    -604    ) -> activity.CharacterActivity:
    -605        current_mode: typing.Optional[enums.GameMode] = None
    -606        if raw_current_mode := payload.get("currentActivityModeType"):
    -607            current_mode = enums.GameMode(raw_current_mode)
    -608
    -609        current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None
    -610        if raw_current_modes := payload.get("currentActivityModeTypes"):
    -611            current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes]
    -612
    -613        return activity.CharacterActivity(
    -614            date_started=time.clean_date(payload["dateActivityStarted"]),
    -615            current_hash=payload["currentActivityHash"],
    -616            current_mode_hash=payload["currentActivityModeHash"],
    -617            current_mode=current_mode,
    -618            current_mode_hashes=payload.get("currentActivityModeHashes"),
    -619            current_mode_types=current_mode_types,
    -620            current_playlist_hash=payload.get("currentPlaylistActivityHash"),
    -621            last_story_hash=payload["lastCompletedStoryHash"],
    -622            available_activities=[
    -623                self.deserialize_available_activity(activity_)
    -624                for activity_ in payload["availableActivities"]
    -625            ],
    -626        )
    +    
    +            
    957    async def fetch_objective_entity(self, hash: int, /) -> entity.ObjectiveEntity:
    +958        """Fetch a Destiny objective entity given a its hash.
    +959
    +960        Parameters
    +961        ----------
    +962        hash: `int`
    +963            objective's hash.
    +964
    +965        Returns
    +966        -------
    +967        `aiobungie.crates.ObjectiveEntity`
    +968            An objective entity item.
    +969        """
    +970        resp = await self.rest.fetch_objective_entity(hash)
    +971
    +972        return self.factory.deserialize_objective_entity(resp)
     
    -

    Deserialize a JSON payload of character activity profile component.

    +

    Fetch a Destiny objective entity given a its hash.

    Parameters
    Returns
    -
    - +
    +
    - def - deserialize_profile_items( self, payload: dict[str, typing.Any], /) -> list[aiobungie.crates.profile.ProfileItemImpl]: + async def + search_entities( self, name: str, entity_type: str, *, page: int = 0) -> aiobungie.Iterator[aiobungie.crates.entity.SearchableEntity]: - +
    - -
    628    def deserialize_profile_items(
    -629        self, payload: typedefs.JSONObject, /
    -630    ) -> list[profile.ProfileItemImpl]:
    -631        return [self.deserialize_profile_item(item) for item in payload["items"]]
    +    
    +            
    974    async def search_entities(
    +975        self, name: str, entity_type: str, *, page: int = 0
    +976    ) -> iterators.Iterator[entity.SearchableEntity]:
    +977        """Search for Destiny2 entities given a name and its type.
    +978
    +979        Parameters
    +980        ----------
    +981        name : `str`
    +982            The name of the entity, i.e., Thunderlord, One thousand voices.
    +983        entity_type : `str`
    +984            The type of the entity, AKA Definition,
    +985            For an example `DestinyInventoryItemDefinition` for emblems, weapons, and other inventory items.
    +986
    +987        Other Parameters
    +988        ----------------
    +989        page : `int`
    +990            An optional page to return. Default to 0.
    +991
    +992        Returns
    +993        -------
    +994        `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]`
    +995            An iterator over the found results matching the provided name.
    +996        """
    +997        resp = await self.rest.search_entities(name, entity_type, page=page)
    +998
    +999        return self.factory.deserialize_inventory_results(resp)
     
    -

    Deserialize a JSON payload of profile items component information.

    - -

    This may deserialize profileInventories or profileCurrencies or any -other alternatives.

    +

    Search for Destiny2 entities given a name and its type.

    Parameters
      -
    • payload (aiobungie.typedefs.JSONObject): -The JSON payload.
    • +
    • name (str): +The name of the entity, i.e., Thunderlord, One thousand voices.
    • +
    • entity_type (str): +The type of the entity, AKA Definition, +For an example DestinyInventoryItemDefinition for emblems, weapons, and other inventory items.
    • +
    + +
    Other Parameters
    + +
      +
    • page (int): +An optional page to return. Default to 0.
    Returns
    -
    - +
    +
    - def - deserialize_progressions( self, payload: dict[str, typing.Any]) -> aiobungie.crates.progressions.Progression: + async def + fetch_fireteams( self, activity_type: Union[int, aiobungie.FireteamActivity], *, platform: Union[int, aiobungie.FireteamPlatform] = <FireteamPlatform.ANY: 0>, language: Union[aiobungie.FireteamLanguage, str] = <FireteamLanguage.ALL: >, date_range: int = 0, page: int = 0, slots_filter: int = 0) -> Optional[collections.abc.Sequence[aiobungie.crates.fireteams.Fireteam]]: - +
    - -
    674    def deserialize_progressions(
    -675        self, payload: typedefs.JSONObject
    -676    ) -> progressions.Progression:
    -677        return progressions.Progression(
    -678            hash=int(payload["progressionHash"]),
    -679            level=int(payload["level"]),
    -680            cap=int(payload["levelCap"]),
    -681            daily_limit=int(payload["dailyLimit"]),
    -682            weekly_limit=int(payload["weeklyLimit"]),
    -683            current_progress=int(payload["currentProgress"]),
    -684            daily_progress=int(payload["dailyProgress"]),
    -685            needed=int(payload["progressToNextLevel"]),
    -686            next_level=int(payload["nextLevelAt"]),
    -687        )
    +    
    +            
    1003    async def fetch_fireteams(
    +1004        self,
    +1005        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    +1006        *,
    +1007        platform: typedefs.IntAnd[
    +1008            fireteams.FireteamPlatform
    +1009        ] = fireteams.FireteamPlatform.ANY,
    +1010        language: typing.Union[
    +1011            fireteams.FireteamLanguage, str
    +1012        ] = fireteams.FireteamLanguage.ALL,
    +1013        date_range: int = 0,
    +1014        page: int = 0,
    +1015        slots_filter: int = 0,
    +1016    ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]:
    +1017        """Fetch public Bungie fireteams with open slots.
    +1018
    +1019        Parameters
    +1020        ----------
    +1021        activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]`
    +1022            The fireteam activity type.
    +1023
    +1024        Other Parameters
    +1025        ----------------
    +1026        platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]`
    +1027            If this is provided. Then the results will be filtered with the given platform.
    +1028            Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms.
    +1029        language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]`
    +1030            A locale language to filter the used language in that fireteam.
    +1031            Defaults to `aiobungie.crates.FireteamLanguage.ALL`
    +1032        date_range : `int`
    +1033            An integer to filter the date range of the returned fireteams. Defaults to `aiobungie.FireteamDate.ALL`.
    +1034        page : `int`
    +1035            The page number. By default its `0` which returns all available activities.
    +1036        slots_filter : `int`
    +1037            Filter the returned fireteams based on available slots. Default is `0`
    +1038
    +1039        Returns
    +1040        -------
    +1041        `typing.Optional[collections.Sequence[fireteams.Fireteam]]`
    +1042            A sequence of `aiobungie.crates.Fireteam` or `None`.
    +1043        """
    +1044
    +1045        resp = await self.rest.fetch_fireteams(
    +1046            activity_type,
    +1047            platform=platform,
    +1048            language=language,
    +1049            date_range=date_range,
    +1050            page=page,
    +1051            slots_filter=slots_filter,
    +1052        )
    +1053
    +1054        return self.factory.deserialize_fireteams(resp)
     
    - +

    Fetch public Bungie fireteams with open slots.

    -
    -
    - -
    - - def - deserialize_milestone( self, payload: dict[str, typing.Any]) -> aiobungie.crates.milestones.Milestone: +
    Parameters
    - + + +
    Other Parameters
    + +
      +
    • platform (aiobungie.typedefs.IntAnd[aiobungie.FireteamPlatform]): +If this is provided. Then the results will be filtered with the given platform. +Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
    • +
    • language (typing.Union[aiobungie.FireteamLanguage, str]): +A locale language to filter the used language in that fireteam. +Defaults to aiobungie.crates.FireteamLanguage.ALL
    • +
    • date_range (int): +An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
    • +
    • page (int): +The page number. By default its 0 which returns all available activities.
    • +
    • slots_filter (int): +Filter the returned fireteams based on available slots. Default is 0
    • +
    -
    - -
    775    def deserialize_milestone(
    -776        self, payload: typedefs.JSONObject
    -777    ) -> milestones.Milestone:
    -778        start_date: typing.Optional[datetime.datetime] = None
    -779        if raw_start_date := payload.get("startDate"):
    -780            start_date = time.clean_date(raw_start_date)
    -781
    -782        end_date: typing.Optional[datetime.datetime] = None
    -783        if raw_end_date := payload.get("endDate"):
    -784            end_date = time.clean_date(raw_end_date)
    -785
    -786        rewards: typing.Optional[
    -787            collections.Collection[milestones.MilestoneReward]
    -788        ] = None
    -789        if raw_rewards := payload.get("rewards"):
    -790            rewards = [
    -791                self._deserialize_milestone_rewards(reward) for reward in raw_rewards
    -792            ]
    -793
    -794        activities: typing.Optional[
    -795            collections.Sequence[milestones.MilestoneActivity]
    -796        ] = None
    -797        if raw_activities := payload.get("activities"):
    -798            activities = [
    -799                self._deserialize_milestone_activity(active)
    -800                for active in raw_activities
    -801            ]
    -802
    -803        quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None
    -804        if raw_quests := payload.get("availableQuests"):
    -805            quests = [
    -806                self._deserialize_milestone_available_quest(quest)
    -807                for quest in raw_quests
    -808            ]
    -809
    -810        vendors: typing.Optional[
    -811            collections.Sequence[milestones.MilestoneVendor]
    -812        ] = None
    -813        if raw_vendors := payload.get("vendors"):
    -814            vendors = [
    -815                milestones.MilestoneVendor(
    -816                    vendor_hash=vendor["vendorHash"],
    -817                    preview_itemhash=vendor.get("previewItemHash"),
    -818                )
    -819                for vendor in raw_vendors
    -820            ]
    -821
    -822        return milestones.Milestone(
    -823            hash=payload["milestoneHash"],
    -824            start_date=start_date,
    -825            end_date=end_date,
    -826            order=payload["order"],
    -827            rewards=rewards,
    -828            available_quests=quests,
    -829            activities=activities,
    -830            vendors=vendors,
    -831        )
    -
    +
    Returns
    + +
    -
    -
    - +
    +
    - def - deserialize_characters( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.character.Character]: + async def + fetch_avaliable_clan_fireteams( self, access_token: str, group_id: int, activity_type: Union[int, aiobungie.FireteamActivity], *, platform: Union[int, aiobungie.FireteamPlatform], language: Union[aiobungie.FireteamLanguage, str], date_range: int = 0, page: int = 0, public_only: bool = False, slots_filter: int = 0) -> Optional[collections.abc.Sequence[aiobungie.crates.fireteams.Fireteam]]: - +
    - -
    848    def deserialize_characters(
    -849        self, payload: typedefs.JSONObject
    -850    ) -> collections.Mapping[int, character.Character]:
    -851        return {
    -852            int(char_id): self._set_character_attrs(char)
    -853            for char_id, char in payload["data"].items()
    -854        }
    +    
    +            
    1056    async def fetch_avaliable_clan_fireteams(
    +1057        self,
    +1058        access_token: str,
    +1059        group_id: int,
    +1060        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    +1061        *,
    +1062        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    +1063        language: typing.Union[fireteams.FireteamLanguage, str],
    +1064        date_range: int = 0,
    +1065        page: int = 0,
    +1066        public_only: bool = False,
    +1067        slots_filter: int = 0,
    +1068    ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]:
    +1069        """Fetch a clan's fireteams with open slots.
    +1070
    +1071        .. note::
    +1072            This method requires OAuth2: ReadGroups scope.
    +1073
    +1074        Parameters
    +1075        ----------
    +1076        access_token : `str`
    +1077            The bearer access token associated with the bungie account.
    +1078        group_id : `int`
    +1079            The group/clan id of the fireteam.
    +1080        activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]`
    +1081            The fireteam activity type.
    +1082
    +1083        Other Parameters
    +1084        ----------------
    +1085        platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]`
    +1086            If this is provided. Then the results will be filtered with the given platform.
    +1087            Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms.
    +1088        language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]`
    +1089            A locale language to filter the used language in that fireteam.
    +1090            Defaults to `aiobungie.crates.FireteamLanguage.ALL`
    +1091        date_range : `int`
    +1092            An integer to filter the date range of the returned fireteams. Defaults to `0`.
    +1093        page : `int`
    +1094            The page number. By default its `0` which returns all available activities.
    +1095        public_only: `bool`
    +1096            If set to True, Then only public fireteams will be returned.
    +1097        slots_filter : `int`
    +1098            Filter the returned fireteams based on available slots. Default is `0`
    +1099
    +1100        Returns
    +1101        -------
    +1102        `typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]`
    +1103            A sequence of  fireteams found in the clan.
    +1104            `None` will be returned if nothing was found.
    +1105        """
    +1106        resp = await self.rest.fetch_avaliable_clan_fireteams(
    +1107            access_token,
    +1108            group_id,
    +1109            activity_type,
    +1110            platform=platform,
    +1111            language=language,
    +1112            date_range=date_range,
    +1113            page=page,
    +1114            public_only=public_only,
    +1115            slots_filter=slots_filter,
    +1116        )
    +1117
    +1118        return self.factory.deserialize_fireteams(resp)
     
    - +

    Fetch a clan's fireteams with open slots.

    -
    -
    - -
    - - def - deserialize_character( self, payload: dict[str, typing.Any]) -> aiobungie.crates.character.Character: +
    - +

    This method requires OAuth2: ReadGroups scope.

    -
    - -
    856    def deserialize_character(
    -857        self, payload: typedefs.JSONObject
    -858    ) -> character.Character:
    -859        return self._set_character_attrs(payload)
    -
    +
    +
    Parameters
    - +
      +
    • access_token (str): +The bearer access token associated with the bungie account.
    • +
    • group_id (int): +The group/clan id of the fireteam.
    • +
    • activity_type (aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]): +The fireteam activity type.
    • +
    -
    -
    - -
    - - def - deserialize_character_equipments( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, collections.abc.Sequence[aiobungie.crates.profile.ProfileItemImpl]]: +
    Other Parameters
    - +
      +
    • platform (aiobungie.typedefs.IntAnd[aiobungie.FireteamPlatform]): +If this is provided. Then the results will be filtered with the given platform. +Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
    • +
    • language (typing.Union[aiobungie.FireteamLanguage, str]): +A locale language to filter the used language in that fireteam. +Defaults to aiobungie.crates.FireteamLanguage.ALL
    • +
    • date_range (int): +An integer to filter the date range of the returned fireteams. Defaults to 0.
    • +
    • page (int): +The page number. By default its 0 which returns all available activities.
    • +
    • public_only (bool): +If set to True, Then only public fireteams will be returned.
    • +
    • slots_filter (int): +Filter the returned fireteams based on available slots. Default is 0
    • +
    -
    - -
    861    def deserialize_character_equipments(
    -862        self, payload: typedefs.JSONObject
    -863    ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]:
    -864        return {
    -865            int(char_id): self.deserialize_profile_items(item)
    -866            for char_id, item in payload["data"].items()
    -867        }
    -
    +
    Returns
    +
      +
    • typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]: A sequence of fireteams found in the clan. +None will be returned if nothing was found.
    • +
    +
    -
    -
    - +
    +
    - def - deserialize_character_activities( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.activity.CharacterActivity]: + async def + fetch_clan_fireteam( self, access_token: str, fireteam_id: int, group_id: int) -> aiobungie.crates.fireteams.AvailableFireteam: - +
    - -
    869    def deserialize_character_activities(
    -870        self, payload: typedefs.JSONObject
    -871    ) -> collections.Mapping[int, activity.CharacterActivity]:
    -872        return {
    -873            int(char_id): self.deserialize_character_activity(data)
    -874            for char_id, data in payload["data"].items()
    -875        }
    +    
    +            
    1120    async def fetch_clan_fireteam(
    +1121        self, access_token: str, fireteam_id: int, group_id: int
    +1122    ) -> fireteams.AvailableFireteam:
    +1123        """Fetch a specific clan fireteam.
    +1124
    +1125        .. note::
    +1126            This method requires OAuth2: ReadGroups scope.
    +1127
    +1128        Parameters
    +1129        ----------
    +1130        access_token : `str`
    +1131            The bearer access token associated with the bungie account.
    +1132        group_id : `int`
    +1133            The group/clan id to fetch the fireteam from.
    +1134        fireteam_id : `int`
    +1135            The fireteam id to fetch.
    +1136
    +1137        Returns
    +1138        -------
    +1139        `typing.Optional[aiobungie.crates.AvailableFireteam]`
    +1140            A sequence of available fireteams objects if exists. else `None` will be returned.
    +1141        """
    +1142        resp = await self.rest.fetch_clan_fireteam(access_token, fireteam_id, group_id)
    +1143
    +1144        return self.factory.deserialize_available_fireteams(
    +1145            resp, no_results=True
    +1146        )  # type: ignore[return-value]
     
    - - -
    -
    - -
    - - def - deserialize_characters_render_data( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.character.RenderedData]: - - +

    Fetch a specific clan fireteam.

    -
    - -
    877    def deserialize_characters_render_data(
    -878        self, payload: typedefs.JSONObject
    -879    ) -> collections.Mapping[int, character.RenderedData]:
    -880        return {
    -881            int(char_id): self.deserialize_character_render_data(data)
    -882            for char_id, data in payload["data"].items()
    -883        }
    -
    +
    +

    This method requires OAuth2: ReadGroups scope.

    - +
    -
    -
    - -
    - - def - deserialize_character_progressions( self, payload: dict[str, typing.Any]) -> aiobungie.crates.character.CharacterProgression: +
    Parameters
    - +
      +
    • access_token (str): +The bearer access token associated with the bungie account.
    • +
    • group_id (int): +The group/clan id to fetch the fireteam from.
    • +
    • fireteam_id (int): +The fireteam id to fetch.
    • +
    -
    - -
    885    def deserialize_character_progressions(
    -886        self, payload: typedefs.JSONObject
    -887    ) -> character.CharacterProgression:
    -888        progressions_ = {
    -889            int(prog_id): self.deserialize_progressions(prog)
    -890            for prog_id, prog in payload["progressions"].items()
    -891        }
    -892
    -893        factions = {
    -894            int(faction_id): self._deserialize_factions(faction)
    -895            for faction_id, faction in payload["factions"].items()
    -896        }
    -897
    -898        milestones_ = {
    -899            int(milestone_hash): self.deserialize_milestone(milestone)
    -900            for milestone_hash, milestone in payload["milestones"].items()
    -901        }
    -902
    -903        uninstanced_item_objectives = {
    -904            int(item_hash): [self.deserialize_objectives(ins) for ins in obj]
    -905            for item_hash, obj in payload["uninstancedItemObjectives"].items()
    -906        }
    -907
    -908        artifact = payload["seasonalArtifact"]
    -909        seasonal_artifact = season.CharacterScopedArtifact(
    -910            hash=artifact["artifactHash"],
    -911            points_used=artifact["pointsUsed"],
    -912            reset_count=artifact["resetCount"],
    -913            tiers=[
    -914                self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"]
    -915            ],
    -916        )
    -917        checklists = payload["checklists"]
    -918
    -919        return character.CharacterProgression(
    -920            progressions=progressions_,
    -921            factions=factions,
    -922            checklists=checklists,
    -923            milestones=milestones_,
    -924            seasonal_artifact=seasonal_artifact,
    -925            uninstanced_item_objectives=uninstanced_item_objectives,
    -926        )
    -
    +
    Returns
    + +
    -
    -
    - +
    +
    - def - deserialize_character_progressions_mapping( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.character.CharacterProgression]: + async def + fetch_my_clan_fireteams( self, access_token: str, group_id: int, *, include_closed: bool = True, platform: Union[int, aiobungie.FireteamPlatform], language: Union[aiobungie.FireteamLanguage, str], filtered: bool = True, page: int = 0) -> collections.abc.Sequence[aiobungie.crates.fireteams.AvailableFireteam]: - +
    - -
    928    def deserialize_character_progressions_mapping(
    -929        self, payload: typedefs.JSONObject
    -930    ) -> collections.Mapping[int, character.CharacterProgression]:
    -931        character_progressions: collections.Mapping[
    -932            int, character.CharacterProgression
    -933        ] = {}
    -934        for char_id, data in payload["data"].items():
    -935            # A little hack to stop mypy complaining about Mapping <-> dict
    -936            character_progressions[int(char_id)] = self.deserialize_character_progressions(data)  # type: ignore[index]
    -937        return character_progressions
    +    
    +            
    1148    async def fetch_my_clan_fireteams(
    +1149        self,
    +1150        access_token: str,
    +1151        group_id: int,
    +1152        *,
    +1153        include_closed: bool = True,
    +1154        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    +1155        language: typing.Union[fireteams.FireteamLanguage, str],
    +1156        filtered: bool = True,
    +1157        page: int = 0,
    +1158    ) -> collections.Sequence[fireteams.AvailableFireteam]:
    +1159        """A method that's similar to `fetch_fireteams` but requires OAuth2.
    +1160
    +1161        .. note::
    +1162            This method requires OAuth2: ReadGroups scope.
    +1163
    +1164        Parameters
    +1165        ----------
    +1166        access_token : str
    +1167            The bearer access token associated with the bungie account.
    +1168        group_id : int
    +1169            The group/clan id to fetch.
    +1170
    +1171        Other Parameters
    +1172        ----------------
    +1173        include_closed : bool
    +1174            If provided and set to True, It will also return closed fireteams.
    +1175            If provided and set to False, It will only return public fireteams. Default is True.
    +1176        platform : aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]
    +1177            If this is provided. Then the results will be filtered with the given platform.
    +1178            Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
    +1179        language : typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]
    +1180            A locale language to filter the used language in that fireteam.
    +1181            Defaults to aiobungie.crates.FireteamLanguage.ALL
    +1182        filtered : bool
    +1183            If set to True, it will filter by clan. Otherwise not. Default is True.
    +1184        page : int
    +1185            The page number. By default its 0 which returns all available activities.
    +1186
    +1187        Returns
    +1188        -------
    +1189        `collections.Sequence[aiobungie.crates.AvailableFireteam]`
    +1190            A sequence of available fireteams objects if exists. else `None` will be returned.
    +1191        """
    +1192        resp = await self.rest.fetch_my_clan_fireteams(
    +1193            access_token,
    +1194            group_id,
    +1195            include_closed=include_closed,
    +1196            platform=platform,
    +1197            language=language,
    +1198            filtered=filtered,
    +1199            page=page,
    +1200        )
    +1201
    +1202        return self.factory.deserialize_available_fireteams(resp)  # type: ignore[return-value]
     
    - +

    A method that's similar to fetch_fireteams but requires OAuth2.

    -
    -
    - -
    - - def - deserialize_characters_records( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.records.CharacterRecord]: +
    - +

    This method requires OAuth2: ReadGroups scope.

    -
    - -
    939    def deserialize_characters_records(
    -940        self,
    -941        payload: typedefs.JSONObject,
    -942    ) -> collections.Mapping[int, records.CharacterRecord]:
    -943
    -944        return {
    -945            int(rec_id): self.deserialize_character_records(
    -946                rec, record_hashes=payload.get("featuredRecordHashes")
    -947            )
    -948            for rec_id, rec in payload["records"].items()
    -949        }
    -
    +
    +
    Parameters
    - +
      +
    • access_token (str): +The bearer access token associated with the bungie account.
    • +
    • group_id (int): +The group/clan id to fetch.
    • +
    -
    -
    - -
    - - def - deserialize_profile_records( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.records.Record]: +
    Other Parameters
    - +
      +
    • include_closed (bool): +If provided and set to True, It will also return closed fireteams. +If provided and set to False, It will only return public fireteams. Default is True.
    • +
    • platform (aiobungie.typedefs.IntAnd[aiobungie.FireteamPlatform]): +If this is provided. Then the results will be filtered with the given platform. +Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
    • +
    • language (typing.Union[aiobungie.FireteamLanguage, str]): +A locale language to filter the used language in that fireteam. +Defaults to aiobungie.crates.FireteamLanguage.ALL
    • +
    • filtered (bool): +If set to True, it will filter by clan. Otherwise not. Default is True.
    • +
    • page (int): +The page number. By default its 0 which returns all available activities.
    • +
    -
    - -
    951    def deserialize_profile_records(
    -952        self, payload: typedefs.JSONObject
    -953    ) -> collections.Mapping[int, records.Record]:
    -954        raw_profile_records = payload["data"]
    -955        scores = records.RecordScores(
    -956            current_score=raw_profile_records["score"],
    -957            legacy_score=raw_profile_records["legacyScore"],
    -958            lifetime_score=raw_profile_records["lifetimeScore"],
    -959        )
    -960        return {
    -961            int(record_id): self.deserialize_records(
    -962                record,
    -963                scores,
    -964                categories_hash=raw_profile_records["recordCategoriesRootNodeHash"],
    -965                seals_hash=raw_profile_records["recordSealsRootNodeHash"],
    -966            )
    -967            for record_id, record in raw_profile_records["records"].items()
    -968        }
    -
    +
    Returns
    + +
    -
    -
    - +
    +
    - def - deserialize_craftables_component( self, payload: dict[str, typing.Any]) -> aiobungie.crates.components.CraftablesComponent: + async def + fetch_friends( self, access_token: str, /) -> collections.abc.Sequence[aiobungie.crates.friends.Friend]: - +
    - -
    1005    def deserialize_craftables_component(
    -1006        self, payload: typedefs.JSONObject
    -1007    ) -> components.CraftablesComponent:
    -1008        return components.CraftablesComponent(
    -1009            net=self._net,
    -1010            craftables={
    -1011                int(item_id): self._deserialize_craftable_item(item)
    -1012                for item_id, item in payload["craftables"].items()
    -1013                if item is not None
    -1014            },
    -1015            crafting_root_node_hash=payload["craftingRootNodeHash"],
    -1016        )
    +    
    +            
    1206    async def fetch_friends(
    +1207        self, access_token: str, /
    +1208    ) -> collections.Sequence[friends.Friend]:
    +1209        """Fetch bungie friend list.
    +1210
    +1211        .. note::
    +1212            This requests OAuth2: ReadUserData scope.
    +1213
    +1214        Parameters
    +1215        -----------
    +1216        access_token : `str`
    +1217            The bearer access token associated with the bungie account.
    +1218
    +1219        Returns
    +1220        -------
    +1221        `collections.Sequence[aiobungie.crates.Friend]`
    +1222            A sequence of the friends associated with that access token.
    +1223        """
    +1224
    +1225        resp = await self.rest.fetch_friends(access_token)
    +1226
    +1227        return self.factory.deserialize_friends(resp)
     
    - - -
    -
    - -
    - - def - deserialize_components( self, payload: dict[str, typing.Any]) -> aiobungie.crates.components.Component: - - +

    Fetch bungie friend list.

    -
    - -
    1018    def deserialize_components(  # noqa: C901 Too complex.
    -1019        self, payload: typedefs.JSONObject
    -1020    ) -> components.Component:
    -1021
    -1022        profile_: typing.Optional[profile.Profile] = None
    -1023        if raw_profile := payload.get("profile"):
    -1024            profile_ = self.deserialize_profile(raw_profile)
    -1025
    -1026        profile_progression: typing.Optional[profile.ProfileProgression] = None
    -1027        if raw_profile_progression := payload.get("profileProgression"):
    -1028            profile_progression = self.deserialize_profile_progression(
    -1029                raw_profile_progression
    -1030            )
    -1031
    -1032        profile_currencies: typing.Optional[
    -1033            collections.Sequence[profile.ProfileItemImpl]
    -1034        ] = None
    -1035        if raw_profile_currencies := payload.get("profileCurrencies"):
    -1036            if "data" in raw_profile_currencies:
    -1037                profile_currencies = self.deserialize_profile_items(
    -1038                    raw_profile_currencies["data"]
    -1039                )
    -1040
    -1041        profile_inventories: typing.Optional[
    -1042            collections.Sequence[profile.ProfileItemImpl]
    -1043        ] = None
    -1044        if raw_profile_inventories := payload.get("profileInventory"):
    -1045            if "data" in raw_profile_inventories:
    -1046                profile_inventories = self.deserialize_profile_items(
    -1047                    raw_profile_inventories["data"]
    -1048                )
    -1049
    -1050        profile_records: typing.Optional[
    -1051            collections.Mapping[int, records.Record]
    -1052        ] = None
    -1053
    -1054        if raw_profile_records_ := payload.get("profileRecords"):
    -1055            profile_records = self.deserialize_profile_records(raw_profile_records_)
    -1056
    -1057        characters: typing.Optional[typing.Mapping[int, character.Character]] = None
    -1058        if raw_characters := payload.get("characters"):
    -1059            characters = self.deserialize_characters(raw_characters)
    -1060
    -1061        character_records: typing.Optional[
    -1062            collections.Mapping[int, records.CharacterRecord]
    -1063        ] = None
    -1064
    -1065        if raw_character_records := payload.get("characterRecords"):
    -1066            # Had to do it in two steps..
    -1067            to_update: typedefs.JSONObject = {}
    -1068            for _, data in raw_character_records["data"].items():
    -1069                for record_id, record in data.items():
    -1070                    to_update[record_id] = record
    -1071
    -1072            character_records = {
    -1073                int(rec_id): self.deserialize_character_records(
    -1074                    rec, record_hashes=to_update.get("featuredRecordHashes")
    -1075                )
    -1076                for rec_id, rec in to_update["records"].items()
    -1077            }
    -1078
    -1079        character_equipments: typing.Optional[
    -1080            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
    -1081        ] = None
    -1082        if raw_character_equips := payload.get("characterEquipment"):
    -1083            character_equipments = self.deserialize_character_equipments(
    -1084                raw_character_equips
    -1085            )
    -1086
    -1087        character_inventories: typing.Optional[
    -1088            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
    -1089        ] = None
    -1090        if raw_character_inventories := payload.get("characterInventories"):
    -1091            if "data" in raw_character_inventories:
    -1092                character_inventories = self.deserialize_character_equipments(
    -1093                    raw_character_inventories
    -1094                )
    -1095
    -1096        character_activities: typing.Optional[
    -1097            collections.Mapping[int, activity.CharacterActivity]
    -1098        ] = None
    -1099        if raw_char_acts := payload.get("characterActivities"):
    -1100            character_activities = self.deserialize_character_activities(raw_char_acts)
    -1101
    -1102        character_render_data: typing.Optional[
    -1103            collections.Mapping[int, character.RenderedData]
    -1104        ] = None
    -1105        if raw_character_render_data := payload.get("characterRenderData"):
    -1106            character_render_data = self.deserialize_characters_render_data(
    -1107                raw_character_render_data
    -1108            )
    -1109
    -1110        character_progressions: typing.Optional[
    -1111            collections.Mapping[int, character.CharacterProgression]
    -1112        ] = None
    -1113
    -1114        if raw_character_progressions := payload.get("characterProgressions"):
    -1115            character_progressions = self.deserialize_character_progressions_mapping(
    -1116                raw_character_progressions
    -1117            )
    -1118
    -1119        profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None
    -1120        if raw_profile_string_vars := payload.get("profileStringVariables"):
    -1121            profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"]
    -1122
    -1123        character_string_vars: typing.Optional[
    -1124            collections.Mapping[int, collections.Mapping[int, int]]
    -1125        ] = None
    -1126        if raw_character_string_vars := payload.get("characterStringVariables"):
    -1127            character_string_vars = {
    -1128                int(char_id): data["integerValuesByHash"]
    -1129                for char_id, data in raw_character_string_vars["data"].items()
    -1130            }
    -1131
    -1132        metrics: typing.Optional[
    -1133            collections.Sequence[
    -1134                collections.Mapping[
    -1135                    int, tuple[bool, typing.Optional[records.Objective]]
    -1136                ]
    -1137            ]
    -1138        ] = None
    -1139        root_node_hash: typing.Optional[int] = None
    -1140
    -1141        if raw_metrics := payload.get("metrics"):
    -1142            root_node_hash = raw_metrics["data"]["metricsRootNodeHash"]
    -1143            metrics = [
    -1144                {
    -1145                    int(metrics_hash): (
    -1146                        data["invisible"],
    -1147                        self.deserialize_objectives(data["objectiveProgress"])
    -1148                        if "objectiveProgress" in data
    -1149                        else None,
    -1150                    )
    -1151                    for metrics_hash, data in raw_metrics["data"]["metrics"].items()
    -1152                }
    -1153            ]
    -1154        transitory: typing.Optional[fireteams.FireteamParty] = None
    -1155        if raw_transitory := payload.get("profileTransitoryData"):
    -1156            if "data" in raw_transitory:
    -1157                transitory = self.deserialize_fireteam_party(raw_transitory["data"])
    -1158
    -1159        item_components: typing.Optional[components.ItemsComponent] = None
    -1160        if raw_item_components := payload.get("itemComponents"):
    -1161            item_components = self.deserialize_items_component(raw_item_components)
    -1162
    -1163        profile_plugsets: typing.Optional[
    -1164            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    -1165        ] = None
    -1166
    -1167        if raw_profile_plugs := payload.get("profilePlugSets"):
    -1168            profile_plugsets = {
    -1169                int(index): [self.deserialize_plug_item_state(state) for state in data]
    -1170                for index, data in raw_profile_plugs["data"]["plugs"].items()
    -1171            }
    -1172
    -1173        character_plugsets: typing.Optional[
    -1174            collections.Mapping[
    -1175                int, collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    -1176            ]
    -1177        ] = None
    -1178        if raw_char_plugsets := payload.get("characterPlugSets"):
    -1179            character_plugsets = {
    -1180                int(char_id): {
    -1181                    int(index): [
    -1182                        self.deserialize_plug_item_state(state) for state in data
    -1183                    ]
    -1184                    for index, data in inner["plugs"].items()
    -1185                }
    -1186                for char_id, inner in raw_char_plugsets["data"].items()
    -1187            }
    -1188
    -1189        character_collectibles: typing.Optional[
    -1190            collections.Mapping[int, items.Collectible]
    -1191        ] = None
    -1192        if raw_character_collectibles := payload.get("characterCollectibles"):
    -1193            character_collectibles = {
    -1194                int(char_id): self._deserialize_collectible(data)
    -1195                for char_id, data in raw_character_collectibles["data"].items()
    -1196            }
    -1197
    -1198        profile_collectibles: typing.Optional[items.Collectible] = None
    -1199        if raw_profile_collectibles := payload.get("profileCollectibles"):
    -1200            profile_collectibles = self._deserialize_collectible(
    -1201                raw_profile_collectibles["data"]
    -1202            )
    -1203
    -1204        profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
    -1205        if raw_profile_nodes := payload.get("profilePresentationNodes"):
    -1206            profile_nodes = {
    -1207                int(node_hash): self._deserialize_node(node)
    -1208                for node_hash, node in raw_profile_nodes["data"]["nodes"].items()
    -1209            }
    -1210
    -1211        character_nodes: typing.Optional[
    -1212            collections.Mapping[int, collections.Mapping[int, records.Node]]
    -1213        ] = None
    -1214        if raw_character_nodes := payload.get("characterPresentationNodes"):
    -1215            character_nodes = {
    -1216                int(char_id): {
    -1217                    int(node_hash): self._deserialize_node(node)
    -1218                    for node_hash, node in each_character["nodes"].items()
    -1219                }
    -1220                for char_id, each_character in raw_character_nodes["data"].items()
    -1221            }
    -1222
    -1223        platform_silver: typing.Optional[
    -1224            collections.Mapping[str, profile.ProfileItemImpl]
    -1225        ] = None
    -1226        if raw_platform_silver := payload.get("platformSilver"):
    -1227            if "data" in raw_platform_silver:
    -1228                platform_silver = {
    -1229                    platform_name: self.deserialize_profile_item(item)
    -1230                    for platform_name, item in raw_platform_silver["data"][
    -1231                        "platformSilver"
    -1232                    ].items()
    -1233                }
    -1234
    -1235        character_currency_lookups: typing.Optional[
    -1236            collections.Mapping[int, collections.Sequence[items.Currency]]
    -1237        ] = None
    -1238        if raw_char_lookups := payload.get("characterCurrencyLookups"):
    -1239            if "data" in raw_char_lookups:
    -1240                character_currency_lookups = {
    -1241                    int(char_id): self._deserialize_currencies(currencie)
    -1242                    for char_id, currencie in raw_char_lookups["data"].items()
    -1243                }
    -1244
    -1245        character_craftables: typing.Optional[
    -1246            collections.Mapping[int, components.CraftablesComponent]
    -1247        ] = None
    -1248        if raw_character_craftables := payload.get("characterCraftables"):
    -1249
    -1250            if "data" in raw_character_craftables:
    -1251                character_craftables = {
    -1252                    int(char_id): self.deserialize_craftables_component(craftable)
    -1253                    for char_id, craftable in raw_character_craftables["data"].items()
    -1254                }
    -1255
    -1256        return components.Component(
    -1257            profiles=profile_,
    -1258            profile_progression=profile_progression,
    -1259            profile_currencies=profile_currencies,
    -1260            profile_inventories=profile_inventories,
    -1261            profile_records=profile_records,
    -1262            characters=characters,
    -1263            character_records=character_records,
    -1264            character_equipments=character_equipments,
    -1265            character_inventories=character_inventories,
    -1266            character_activities=character_activities,
    -1267            character_render_data=character_render_data,
    -1268            character_progressions=character_progressions,
    -1269            profile_string_variables=profile_string_vars,
    -1270            character_string_variables=character_string_vars,
    -1271            metrics=metrics,
    -1272            root_node_hash=root_node_hash,
    -1273            transitory=transitory,
    -1274            item_components=item_components,
    -1275            profile_plugsets=profile_plugsets,
    -1276            character_plugsets=character_plugsets,
    -1277            character_collectibles=character_collectibles,
    -1278            profile_collectibles=profile_collectibles,
    -1279            profile_nodes=profile_nodes,
    -1280            character_nodes=character_nodes,
    -1281            platform_silver=platform_silver,
    -1282            character_currency_lookups=character_currency_lookups,
    -1283            character_craftables=character_craftables,
    -1284        )
    -
    +
    +

    This requests OAuth2: ReadUserData scope.

    -

    Deserialize a JSON payload of Bungie.net profile components information.

    +
    Parameters
      -
    • payload (aiobungie.internal.helpers.JsonObject): -The JSON payload.
    • +
    • access_token (str): +The bearer access token associated with the bungie account.
    Returns
    -
    - +
    +
    - def - deserialize_items_component( self, payload: dict[str, typing.Any]) -> aiobungie.crates.components.ItemsComponent: + async def + fetch_friend_requests(self, access_token: str, /) -> aiobungie.crates.friends.FriendRequestView: - +
    - -
    1286    def deserialize_items_component(
    -1287        self, payload: typedefs.JSONObject
    -1288    ) -> components.ItemsComponent:
    -1289        instances: typing.Optional[
    -1290            collections.Sequence[collections.Mapping[int, items.ItemInstance]]
    -1291        ] = None
    -1292        if raw_instances := payload.get("instances"):
    -1293            instances = [
    -1294                {
    -1295                    int(ins_id): self.deserialize_instanced_item(item)
    -1296                    for ins_id, item in raw_instances["data"].items()
    -1297                }
    -1298            ]
    -1299
    -1300        render_data: typing.Optional[
    -1301            collections.Mapping[int, tuple[bool, dict[int, int]]]
    -1302        ] = None
    -1303        if raw_render_data := payload.get("renderData"):
    -1304            render_data = {
    -1305                int(ins_id): (data["useCustomDyes"], data["artRegions"])
    -1306                for ins_id, data in raw_render_data["data"].items()
    -1307            }
    -1308
    -1309        stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None
    -1310        if raw_stats := payload.get("stats"):
    -1311            builder: collections.Mapping[int, items.ItemStatsView] = {}
    -1312            for ins_id, stat in raw_stats["data"].items():
    -1313                for _, items_ in stat.items():
    -1314                    builder[int(ins_id)] = self.deserialize_item_stats_view(items_)  # type: ignore[index]
    -1315            stats = builder
    -1316
    -1317        sockets: typing.Optional[
    -1318            collections.Mapping[int, collections.Sequence[items.ItemSocket]]
    -1319        ] = None
    -1320        if raw_sockets := payload.get("sockets"):
    -1321            sockets = {
    -1322                int(ins_id): [
    -1323                    self.deserialize_item_socket(socket) for socket in item["sockets"]
    -1324                ]
    -1325                for ins_id, item in raw_sockets["data"].items()
    -1326            }
    -1327
    -1328        objeectives: typing.Optional[
    -1329            collections.Mapping[int, collections.Sequence[records.Objective]]
    -1330        ] = None
    -1331        if raw_objectives := payload.get("objectives"):
    -1332            objeectives = {
    -1333                int(ins_id): [self.deserialize_objectives(objective)]
    -1334                for ins_id, data in raw_objectives["data"].items()
    -1335                for objective in data["objectives"]
    -1336            }
    -1337
    -1338        perks: typing.Optional[
    -1339            collections.Mapping[int, collections.Collection[items.ItemPerk]]
    -1340        ] = None
    -1341        if raw_perks := payload.get("perks"):
    -1342            perks = {
    -1343                int(ins_id): [
    -1344                    self.deserialize_item_perk(perk) for perk in item["perks"]
    -1345                ]
    -1346                for ins_id, item in raw_perks["data"].items()
    -1347            }
    -1348
    -1349        plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None
    -1350        if raw_plug_states := payload.get("plugStates"):
    -1351            pending_states: list[items.PlugItemState] = []
    -1352            for _, plug in raw_plug_states["data"].items():
    -1353                pending_states.append(self.deserialize_plug_item_state(plug))
    -1354            plug_states = pending_states
    -1355
    -1356        reusable_plugs: typing.Optional[
    -1357            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    -1358        ] = None
    -1359        if raw_re_plugs := payload.get("reusablePlugs"):
    -1360            reusable_plugs = {
    -1361                int(ins_id): [
    -1362                    self.deserialize_plug_item_state(state) for state in inner
    -1363                ]
    -1364                for ins_id, plug in raw_re_plugs["data"].items()
    -1365                for inner in list(plug["plugs"].values())
    -1366            }
    -1367
    -1368        plug_objectives: typing.Optional[
    -1369            collections.Mapping[
    -1370                int, collections.Mapping[int, collections.Collection[records.Objective]]
    -1371            ]
    -1372        ] = None
    -1373        if raw_plug_objectives := payload.get("plugObjectives"):
    -1374            plug_objectives = {
    -1375                int(ins_id): {
    -1376                    int(obj_hash): [self.deserialize_objectives(obj) for obj in objs]
    -1377                    for obj_hash, objs in inner["objectivesPerPlug"].items()
    -1378                }
    -1379                for ins_id, inner in raw_plug_objectives["data"].items()
    -1380            }
    -1381
    -1382        return components.ItemsComponent(
    -1383            sockets=sockets,
    -1384            stats=stats,
    -1385            render_data=render_data,
    -1386            instances=instances,
    -1387            objectives=objeectives,
    -1388            perks=perks,
    -1389            plug_states=plug_states,
    -1390            reusable_plugs=reusable_plugs,
    -1391            plug_objectives=plug_objectives,
    -1392        )
    +    
    +            
    1229    async def fetch_friend_requests(
    +1230        self, access_token: str, /
    +1231    ) -> friends.FriendRequestView:
    +1232        """Fetch pending bungie friend requests queue.
    +1233
    +1234        .. note::
    +1235            This requests OAuth2: ReadUserData scope.
    +1236
    +1237        Parameters
    +1238        -----------
    +1239        access_token : `str`
    +1240            The bearer access token associated with the bungie account.
    +1241
    +1242        Returns
    +1243        -------
    +1244        `aiobungie.crates.FriendRequestView`
    +1245            A friend requests view of that associated access token.
    +1246        """
    +1247
    +1248        resp = await self.rest.fetch_friend_requests(access_token)
    +1249
    +1250        return self.factory.deserialize_friend_requests(resp)
     
    -

    Deserialize a JSON objects within the itemComponents key.`

    -
    - - -
    -
    - -
    - - def - deserialize_character_component( self, payload: dict[str, typing.Any]) -> aiobungie.crates.components.CharacterComponent: - - +

    Fetch pending bungie friend requests queue.

    -
    - -
    1394    def deserialize_character_component(  # type: ignore[call-arg]
    -1395        self, payload: typedefs.JSONObject
    -1396    ) -> components.CharacterComponent:
    -1397
    -1398        character_: typing.Optional[character.Character] = None
    -1399        if raw_singuler_character := payload.get("character"):
    -1400            character_ = self.deserialize_character(raw_singuler_character["data"])
    -1401
    -1402        inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
    -1403        if raw_inventory := payload.get("inventory"):
    -1404            if "data" in raw_inventory:
    -1405                inventory = self.deserialize_profile_items(raw_inventory["data"])
    -1406
    -1407        activities: typing.Optional[activity.CharacterActivity] = None
    -1408        if raw_activities := payload.get("activities"):
    -1409            activities = self.deserialize_character_activity(raw_activities["data"])
    -1410
    -1411        equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
    -1412        if raw_equipments := payload.get("equipment"):
    -1413            equipment = self.deserialize_profile_items(raw_equipments["data"])
    -1414
    -1415        progressions_: typing.Optional[character.CharacterProgression] = None
    -1416        if raw_progressions := payload.get("progressions"):
    -1417            progressions_ = self.deserialize_character_progressions(
    -1418                raw_progressions["data"]
    -1419            )
    -1420
    -1421        render_data: typing.Optional[character.RenderedData] = None
    -1422        if raw_render_data := payload.get("renderData"):
    -1423            render_data = self.deserialize_character_render_data(
    -1424                raw_render_data["data"]
    -1425            )
    -1426
    -1427        character_records: typing.Optional[
    -1428            collections.Mapping[int, records.CharacterRecord]
    -1429        ] = None
    -1430        if raw_char_records := payload.get("records"):
    -1431            character_records = self.deserialize_characters_records(
    -1432                raw_char_records["data"]
    -1433            )
    -1434
    -1435        item_components: typing.Optional[components.ItemsComponent] = None
    -1436        if raw_item_components := payload.get("itemComponents"):
    -1437            item_components = self.deserialize_items_component(raw_item_components)
    -1438
    -1439        nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
    -1440        if raw_nodes := payload.get("presentationNodes"):
    -1441            nodes = {
    -1442                int(node_hash): self._deserialize_node(node)
    -1443                for node_hash, node in raw_nodes["data"]["nodes"].items()
    -1444            }
    -1445
    -1446        collectibles: typing.Optional[items.Collectible] = None
    -1447        if raw_collectibles := payload.get("collectibles"):
    -1448            collectibles = self._deserialize_collectible(raw_collectibles["data"])
    -1449
    -1450        currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None
    -1451        if raw_currencies := payload.get("currencyLookups"):
    -1452            if "data" in raw_currencies:
    -1453                currency_lookups = self._deserialize_currencies(raw_currencies)
    -1454
    -1455        return components.CharacterComponent(
    -1456            activities=activities,
    -1457            equipment=equipment,
    -1458            inventory=inventory,
    -1459            progressions=progressions_,
    -1460            render_data=render_data,
    -1461            character=character_,
    -1462            character_records=character_records,
    -1463            profile_records=None,
    -1464            item_components=item_components,
    -1465            currency_lookups=currency_lookups,
    -1466            collectibles=collectibles,
    -1467            nodes=nodes,
    -1468        )
    -
    +
    +

    This requests OAuth2: ReadUserData scope.

    -

    Deserialize a JSON payload of Destiny 2 character component.

    +
    Parameters
    Returns
    -
    - +
    +
    - def - deserialize_inventory_results( self, payload: dict[str, typing.Any]) -> aiobungie.FlatIterator[aiobungie.crates.entity.SearchableEntity]: + async def + fetch_application(self, appid: int, /) -> aiobungie.crates.application.Application: - +
    - -
    1496    def deserialize_inventory_results(
    -1497        self, payload: typedefs.JSONObject
    -1498    ) -> iterators.FlatIterator[entity.SearchableEntity]:
    -1499        suggested_words: list[str] = payload["suggestedWords"]
    -1500
    -1501        def _check_unknown(s: str) -> undefined.UndefinedOr[str]:
    -1502            return s if not typedefs.is_unknown(s) else undefined.Undefined
    -1503
    -1504        return iterators.FlatIterator(
    -1505            [
    -1506                entity.SearchableEntity(
    -1507                    net=self._net,
    -1508                    hash=data["hash"],
    -1509                    entity_type=data["entityType"],
    -1510                    weight=data["weight"],
    -1511                    suggested_words=suggested_words,
    -1512                    name=data["displayProperties"]["name"],
    -1513                    has_icon=data["displayProperties"]["hasIcon"],
    -1514                    description=_check_unknown(
    -1515                        data["displayProperties"]["description"]
    -1516                    ),
    -1517                    icon=assets.Image(data["displayProperties"]["icon"]),
    -1518                )
    -1519                for data in payload["results"]["results"]
    -1520            ]
    -1521        )
    +    
    +            
    1254    async def fetch_application(self, appid: int, /) -> application.Application:
    +1255        """Fetch a Bungie application.
    +1256
    +1257        Parameters
    +1258        -----------
    +1259        appid: `int`
    +1260            The application id.
    +1261
    +1262        Returns
    +1263        --------
    +1264        `aiobungie.crates.Application`
    +1265            A Bungie application.
    +1266        """
    +1267        resp = await self.rest.fetch_application(appid)
    +1268
    +1269        return self.factory.deserialize_app(resp)
     
    -

    Deserialize results of searched Destiny2 entities.

    +

    Fetch a Bungie application.

    Parameters
    Returns
    -
    - +
    +
    - def - deserialize_inventory_entity( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.entity.InventoryEntity: + async def + fetch_public_milestone_content( self, milestone_hash: int, /) -> aiobungie.crates.milestones.MilestoneContent: - +
    - -
    1550    def deserialize_inventory_entity(  # noqa: C901 Too complex.
    -1551        self, payload: typedefs.JSONObject, /
    -1552    ) -> entity.InventoryEntity:
    -1553
    -1554        props = self._set_entity_attrs(payload)
    -1555        objects = self._deserialize_inventory_item_objects(payload)
    -1556
    -1557        collectible_hash: typing.Optional[int] = None
    -1558        if raw_collectible_hash := payload.get("collectibleHash"):
    -1559            collectible_hash = int(raw_collectible_hash)
    -1560
    -1561        secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    -1562        if raw_second_icon := payload.get("secondaryIcon"):
    -1563            secondary_icon = assets.Image(raw_second_icon)
    -1564
    -1565        secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    -1566        if raw_second_overlay := payload.get("secondaryOverlay"):
    -1567            secondary_overlay = assets.Image(raw_second_overlay)
    -1568
    -1569        secondary_special: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    -1570        if raw_second_special := payload.get("secondarySpecial"):
    -1571            secondary_special = assets.Image(raw_second_special)
    -1572
    -1573        screenshot: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    -1574        if raw_screenshot := payload.get("screenshot"):
    -1575            screenshot = assets.Image(raw_screenshot)
    -1576
    -1577        watermark_icon: typing.Optional[assets.Image] = None
    -1578        if raw_watermark_icon := payload.get("iconWatermark"):
    -1579            watermark_icon = assets.Image(raw_watermark_icon)
    -1580
    -1581        watermark_shelved: typing.Optional[assets.Image] = None
    -1582        if raw_watermark_shelved := payload.get("iconWatermarkShelved"):
    -1583            watermark_shelved = assets.Image(raw_watermark_shelved)
    -1584
    -1585        about: undefined.UndefinedOr[str] = undefined.Undefined
    -1586        if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown(
    -1587            raw_about
    -1588        ):
    -1589            about = raw_about
    -1590
    -1591        ui_item_style: undefined.UndefinedOr[str] = undefined.Undefined
    -1592        if (
    -1593            raw_ui_style := payload.get("uiItemDisplayStyle")
    -1594        ) and not typedefs.is_unknown(raw_ui_style):
    -1595            ui_item_style = raw_ui_style
    -1596
    -1597        tier_and_name: undefined.UndefinedOr[str] = undefined.Undefined
    -1598        if (
    -1599            raw_tier_and_name := payload.get("itemTypeAndTierDisplayName")
    -1600        ) and not typedefs.is_unknown(raw_tier_and_name):
    -1601            tier_and_name = raw_tier_and_name
    -1602
    -1603        type_name: undefined.UndefinedOr[str] = undefined.Undefined
    -1604        if (
    -1605            raw_type_name := payload.get("itemTypeDisplayName")
    -1606        ) and not typedefs.is_unknown(raw_type_name):
    -1607            type_name = raw_type_name
    -1608
    -1609        display_source: undefined.UndefinedOr[str] = undefined.Undefined
    -1610        if (
    -1611            raw_display_source := payload.get("displaySource")
    -1612        ) and not typedefs.is_unknown(raw_display_source):
    -1613            display_source = raw_display_source
    -1614
    -1615        lorehash: typing.Optional[int] = None
    -1616        if raw_lore_hash := payload.get("loreHash"):
    -1617            lorehash = int(raw_lore_hash)
    -1618
    -1619        summary_hash: typing.Optional[int] = None
    -1620        if raw_summary_hash := payload.get("summaryItemHash"):
    -1621            summary_hash = raw_summary_hash
    -1622
    -1623        breaker_type_hash: typing.Optional[int] = None
    -1624        if raw_breaker_type_hash := payload.get("breakerTypeHash"):
    -1625            breaker_type_hash = int(raw_breaker_type_hash)
    -1626
    -1627        damage_types: typing.Optional[collections.Sequence[int]] = None
    -1628        if raw_damage_types := payload.get("damageTypes"):
    -1629            damage_types = [int(type_) for type_ in raw_damage_types]
    -1630
    -1631        damagetype_hashes: typing.Optional[collections.Sequence[int]] = None
    -1632        if raw_damagetype_hashes := payload.get("damageTypeHashes"):
    -1633            damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes]
    -1634
    -1635        default_damagetype_hash: typing.Optional[int] = None
    -1636        if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"):
    -1637            default_damagetype_hash = int(raw_defaultdmg_hash)
    -1638
    -1639        emblem_objective_hash: typing.Optional[int] = None
    -1640        if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"):
    -1641            emblem_objective_hash = int(raw_emblem_obj_hash)
    -1642
    -1643        tier_type: typing.Optional[enums.TierType] = None
    -1644        tier: typing.Optional[enums.ItemTier] = None
    -1645        bucket_hash: typing.Optional[int] = None
    -1646        recovery_hash: typing.Optional[int] = None
    -1647        tier_name: undefined.UndefinedOr[str] = undefined.Undefined
    -1648        isinstance_item: bool = False
    -1649        expire_tool_tip: undefined.UndefinedOr[str] = undefined.Undefined
    -1650        expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.Undefined
    -1651        suppress_expiration: bool = False
    -1652        max_stack_size: typing.Optional[int] = None
    -1653        stack_label: undefined.UndefinedOr[str] = undefined.Undefined
    -1654
    -1655        if inventory := payload.get("inventory"):
    -1656            tier_type = enums.TierType(int(inventory["tierType"]))
    -1657            tier = enums.ItemTier(int(inventory["tierTypeHash"]))
    -1658            bucket_hash = int(inventory["bucketTypeHash"])
    -1659            recovery_hash = int(inventory["recoveryBucketTypeHash"])
    -1660            tier_name = inventory["tierTypeName"]
    -1661            isinstance_item = inventory["isInstanceItem"]
    -1662            suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"]
    -1663            max_stack_size = int(inventory["maxStackSize"])
    -1664
    -1665            try:
    -1666                stack_label = inventory["stackUniqueLabel"]
    -1667            except KeyError:
    -1668                pass
    -1669
    -1670        return entity.InventoryEntity(
    -1671            net=self._net,
    -1672            collectible_hash=collectible_hash,
    -1673            name=props.name,
    -1674            about=about,
    -1675            emblem_objective_hash=emblem_objective_hash,
    -1676            suppress_expiration=suppress_expiration,
    -1677            max_stack_size=max_stack_size,
    -1678            stack_label=stack_label,
    -1679            tier=tier,
    -1680            tier_type=tier_type,
    -1681            tier_name=tier_name,
    -1682            bucket_hash=bucket_hash,
    -1683            recovery_bucket_hash=recovery_hash,
    -1684            isinstance_item=isinstance_item,
    -1685            expire_in_orbit_message=expire_in_orbit_message,
    -1686            expiration_tooltip=expire_tool_tip,
    -1687            lore_hash=lorehash,
    -1688            type_and_tier_name=tier_and_name,
    -1689            summary_hash=summary_hash,
    -1690            ui_display_style=ui_item_style,
    -1691            type_name=type_name,
    -1692            breaker_type_hash=breaker_type_hash,
    -1693            description=props.description,
    -1694            display_source=display_source,
    -1695            hash=props.hash,
    -1696            damage_types=damage_types,
    -1697            index=props.index,
    -1698            icon=props.icon,
    -1699            has_icon=props.has_icon,
    -1700            screenshot=screenshot,
    -1701            watermark_icon=watermark_icon,
    -1702            watermark_shelved=watermark_shelved,
    -1703            secondary_icon=secondary_icon,
    -1704            secondary_overlay=secondary_overlay,
    -1705            secondary_special=secondary_special,
    -1706            type=enums.ItemType(int(payload["itemType"])),
    -1707            trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])],
    -1708            trait_ids=[trait for trait in payload.get("traitIds", [])],
    -1709            category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]],
    -1710            item_class=enums.Class(int(payload["classType"])),
    -1711            sub_type=enums.ItemSubType(int(payload["itemSubType"])),
    -1712            breaker_type=int(payload["breakerType"]),
    -1713            default_damagetype=int(payload["defaultDamageType"]),
    -1714            default_damagetype_hash=default_damagetype_hash,
    -1715            damagetype_hashes=damagetype_hashes,
    -1716            tooltip_notifications=payload["tooltipNotifications"],
    -1717            not_transferable=payload["nonTransferrable"],
    -1718            allow_actions=payload["allowActions"],
    -1719            is_equippable=payload["equippable"],
    -1720            objects=objects,
    -1721            background_colors=payload.get("backgroundColor", {}),
    -1722            season_hash=payload.get("seasonHash"),
    -1723            has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"],
    -1724        )
    +    
    +            
    1273    async def fetch_public_milestone_content(
    +1274        self, milestone_hash: int, /
    +1275    ) -> milestones.MilestoneContent:
    +1276        """Fetch the milestone content given its hash.
    +1277
    +1278        Parameters
    +1279        ----------
    +1280        milestone_hash : `int`
    +1281            The milestone hash.
    +1282
    +1283        Returns
    +1284        -------
    +1285        `aiobungie.crates.milestones.MilestoneContent`
    +1286            A milestone content object.
    +1287        """
    +1288        resp = await self.rest.fetch_public_milestone_content(milestone_hash)
    +1289
    +1290        return self.factory.deserialize_public_milestone_content(resp)
     
    -

    Deserialize a JSON payload of an inventory entity item information.

    - -

    This can be any item from DestinyInventoryItemDefinition definition.

    +

    Fetch the milestone content given its hash.

    Parameters
    Returns
    -
    - -
    - - def - deserialize_objective_entity( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.entity.ObjectiveEntity: +
    +
    + +
    +
    @typing.final
    - + class + ClosedReasons(aiobungie.Flag): + +
    - -
    1726    def deserialize_objective_entity(
    -1727        self, payload: typedefs.JSONObject, /
    -1728    ) -> entity.ObjectiveEntity:
    -1729        props = self._set_entity_attrs(payload)
    -1730        return entity.ObjectiveEntity(
    -1731            net=self._net,
    -1732            hash=props.hash,
    -1733            index=props.index,
    -1734            description=props.description,
    -1735            name=props.name,
    -1736            has_icon=props.has_icon,
    -1737            icon=props.icon,
    -1738            unlock_value_hash=payload["unlockValueHash"],
    -1739            completion_value=payload["completionValue"],
    -1740            scope=entity.GatingScope(int(payload["scope"])),
    -1741            location_hash=payload["locationHash"],
    -1742            allowed_negative_value=payload["allowNegativeValue"],
    -1743            allowed_value_change=payload["allowValueChangeWhenCompleted"],
    -1744            counting_downward=payload["isCountingDownward"],
    -1745            value_style=entity.ValueUIStyle(int(payload["valueStyle"])),
    -1746            progress_description=payload["progressDescription"],
    -1747            perks=payload["perks"],
    -1748            stats=payload["stats"],
    -1749            minimum_visibility=payload["minimumVisibilityThreshold"],
    -1750            allow_over_completion=payload["allowOvercompletion"],
    -1751            show_value_style=payload["showValueOnComplete"],
    -1752            display_only_objective=payload["isDisplayOnlyObjective"],
    -1753            complete_value_style=entity.ValueUIStyle(
    -1754                int(payload["completedValueStyle"])
    -1755            ),
    -1756            progress_value_style=entity.ValueUIStyle(
    -1757                int(payload["inProgressValueStyle"])
    -1758            ),
    -1759            ui_label=payload["uiLabel"],
    -1760            ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])),
    -1761        )
    +    
    +            
    779@typing.final
    +780class ClosedReasons(Flag):
    +781    """A Flags enumeration representing the reasons why a person can't join this user's fireteam."""
    +782
    +783    NONE = 0
    +784    MATCHMAKING = 1 << 0
    +785    LOADING = 1 << 1
    +786    SOLO = 1 << 2
    +787    """The activity is required to be played solo."""
    +788    INTERNAL_REASONS = 1 << 3
    +789    """
    +790    The user can't be joined for one of a variety of internal reasons.
    +791    Basically, the game can't let you join at this time,
    +792    but for reasons that aren't under the control of this user
    +793    """
    +794    DISALLOWED_BY_GAME_STATE = 1 << 4
    +795    """The user's current activity/quest/other transitory game state is preventing joining."""
    +796    OFFLINE = 32768
    +797    """The user appears offline."""
     
    -

    Deserialize a JSON payload of an objective entity information.

    +

    A Flags enumeration representing the reasons why a person can't join this user's fireteam.

    +
    -
    Parameters
    - +
    +
    + SOLO = <ClosedReasons.SOLO: 4> -
    Returns
    + +
    + + +

    The activity is required to be played solo.

    +
    - + +
    +
    +
    + INTERNAL_REASONS = <ClosedReasons.INTERNAL_REASONS: 8> + + +
    + + +

    The user can't be joined for one of a variety of internal reasons. +Basically, the game can't let you join at this time, +but for reasons that aren't under the control of this user

    -
    - -
    - - def - deserialize_activity( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.activity.Activity: +
    +
    + DISALLOWED_BY_GAME_STATE = <ClosedReasons.DISALLOWED_BY_GAME_STATE: 16> - + +
    + + +

    The user's current activity/quest/other transitory game state is preventing joining.

    +
    + + +
    +
    +
    + OFFLINE = <ClosedReasons.OFFLINE: 32768> +
    - -
    1789    def deserialize_activity(
    -1790        self,
    -1791        payload: typedefs.JSONObject,
    -1792        /,
    -1793    ) -> activity.Activity:
    -1794        period = time.clean_date(payload["period"])
    -1795        details = payload["activityDetails"]
    -1796        ref_id = int(details["referenceId"])
    -1797        instance_id = int(details["instanceId"])
    -1798        mode = enums.GameMode(details["mode"])
    -1799        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
    -1800        is_private = details["isPrivate"]
    -1801        membership_type = enums.MembershipType(int(details["membershipType"]))
    -1802
    -1803        # Since we're using the same fields for post activity method
    -1804        # this check is required since post activity doesn't values values
    -1805        values = self._deserialize_activity_values(payload["values"])
    -1806
    -1807        return activity.Activity(
    -1808            net=self._net,
    -1809            hash=ref_id,
    -1810            instance_id=instance_id,
    -1811            mode=mode,
    -1812            modes=modes,
    -1813            is_private=is_private,
    -1814            membership_type=membership_type,
    -1815            occurred_at=period,
    -1816            values=values,
    -1817        )
    +    
    +    
    +            

    The user appears offline.

    +
    + + +
    +
    +
    Inherited Members
    +
    +
    Flag
    +
    name
    +
    value
    + +
    +
    +
    +
    +
    + +
    +
    @typing.final
    + + class + ComponentFields(aiobungie.Enum): + + + +
    + +
    74@typing.final
    +75class ComponentFields(enums.Enum):
    +76    """An enum that provides fields found in a base component response."""
    +77
    +78    PRIVACY = ComponentPrivacy
    +79    DISABLED = False
     
    -

    Deserialize a JSON payload of an activity history information.

    +

    An enum that provides fields found in a base component response.

    +
    -
    Parameters
    - +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    -
    Returns
    +
    +
    +
    +
    +
    + +
    +
    @typing.final
    - + class + ComponentPrivacy(builtins.int, aiobungie.Enum): + + + +
    + +
    65@typing.final
    +66class ComponentPrivacy(int, enums.Enum):
    +67    """An enum the provides privacy settings for profile components."""
    +68
    +69    NONE = 0
    +70    PUBLIC = 1
    +71    PRIVATE = 2
    +
    + + +

    An enum the provides privacy settings for profile components.

    +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    + +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    + +
    +
    -
    - -
    - - def - deserialize_activities( self, payload: dict[str, typing.Any]) -> aiobungie.FlatIterator[aiobungie.crates.activity.Activity]: +
    +
    + +
    +
    @typing.final
    - + class + ComponentType(aiobungie.Enum): + +
    - -
    1819    def deserialize_activities(
    -1820        self, payload: typedefs.JSONObject
    -1821    ) -> iterators.FlatIterator[activity.Activity]:
    -1822        return iterators.FlatIterator(
    -1823            [
    -1824                self.deserialize_activity(activity_)
    -1825                for activity_ in payload["activities"]
    -1826            ]
    -1827        )
    +    
    +            
    358@typing.final
    +359class ComponentType(Enum):
    +360    """An Enum for Destiny 2 profile Components."""
    +361
    +362    NONE = 0
    +363
    +364    PROFILE = 100
    +365    PROFILE_INVENTORIES = 102
    +366    PROFILE_CURRENCIES = 103
    +367    PROFILE_PROGRESSION = 104
    +368    ALL_PROFILES = (
    +369        PROFILE,
    +370        PROFILE_INVENTORIES,
    +371        PROFILE_CURRENCIES,
    +372        PROFILE_PROGRESSION,
    +373    )
    +374    """All profile components."""
    +375
    +376    VENDORS = 400
    +377    VENDOR_SALES = 402
    +378    VENDOR_RECEIPTS = 101
    +379    ALL_VENDORS = (VENDORS, VENDOR_RECEIPTS, VENDOR_SALES)
    +380    """All vendor components."""
    +381
    +382    # Items
    +383    ITEM_INSTANCES = 300
    +384    ITEM_OBJECTIVES = 301
    +385    ITEM_PERKS = 302
    +386    ITEM_RENDER_DATA = 303
    +387    ITEM_STATS = 304
    +388    ITEM_SOCKETS = 305
    +389    ITEM_TALENT_GRINDS = 306
    +390    ITEM_PLUG_STATES = 308
    +391    ITEM_PLUG_OBJECTIVES = 309
    +392    ITEM_REUSABLE_PLUGS = 310
    +393
    +394    ALL_ITEMS = (
    +395        ITEM_PLUG_OBJECTIVES,
    +396        ITEM_PLUG_STATES,
    +397        ITEM_SOCKETS,
    +398        ITEM_INSTANCES,
    +399        ITEM_OBJECTIVES,
    +400        ITEM_PERKS,
    +401        ITEM_RENDER_DATA,
    +402        ITEM_STATS,
    +403        ITEM_TALENT_GRINDS,
    +404        ITEM_REUSABLE_PLUGS,
    +405    )
    +406    """All item components."""
    +407
    +408    PLATFORM_SILVER = 105
    +409    KIOSKS = 500
    +410    CURRENCY_LOOKUPS = 600
    +411    PRESENTATION_NODES = 700
    +412    COLLECTIBLES = 800
    +413    RECORDS = 900
    +414    TRANSITORY = 1000
    +415    METRICS = 1100
    +416    INVENTORIES = 102
    +417    STRING_VARIABLES = 1200
    +418    CRAFTABLES = 1300
    +419
    +420    CHARACTERS = 200
    +421    CHARACTER_INVENTORY = 201
    +422    CHARECTER_PROGRESSION = 202
    +423    CHARACTER_RENDER_DATA = 203
    +424    CHARACTER_ACTIVITIES = 204
    +425    CHARACTER_EQUIPMENT = 205
    +426
    +427    ALL_CHARACTERS = (
    +428        CHARACTERS,
    +429        CHARACTER_INVENTORY,
    +430        CHARECTER_PROGRESSION,
    +431        CHARACTER_RENDER_DATA,
    +432        CHARACTER_ACTIVITIES,
    +433        CHARACTER_EQUIPMENT,
    +434        RECORDS,
    +435    )
    +436    """All character components."""
    +437
    +438    ALL = (
    +439        *ALL_PROFILES,  # type: ignore
    +440        *ALL_CHARACTERS,  # type: ignore
    +441        *ALL_VENDORS,  # type: ignore
    +442        *ALL_ITEMS,  # type: ignore
    +443        RECORDS,
    +444        CURRENCY_LOOKUPS,
    +445        PRESENTATION_NODES,
    +446        COLLECTIBLES,
    +447        KIOSKS,
    +448        METRICS,
    +449        PLATFORM_SILVER,
    +450        INVENTORIES,
    +451        STRING_VARIABLES,
    +452        TRANSITORY,
    +453        CRAFTABLES,
    +454    )
    +455    """ALl components included."""
     
    -

    Deserialize a JSON payload of an array of activity history information.

    +

    An Enum for Destiny 2 profile Components.

    +
    + + +
    +
    + ALL_PROFILES = <ComponentType.ALL_PROFILES: (100, 102, 103, 104)> -
    Parameters
    + +
    + + +

    All profile components.

    +
    - -
    Returns
    +
    +
    +
    + ALL_VENDORS = <ComponentType.ALL_VENDORS: (400, 101, 402)> -
      -
    • aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]: Am iterator over activity objects of the deserialized payload.
    • -
    + +
    + + +

    All vendor components.

    -
    - -
    - - def - deserialize_extended_weapon_values( self, payload: dict[str, typing.Any]) -> aiobungie.crates.activity.ExtendedWeaponValues: - - +
    +
    + ALL_ITEMS = <ComponentType.ALL_ITEMS: (309, 308, 305, 300, 301, 302, 303, 304, 306, 310)> +
    - -
    1829    def deserialize_extended_weapon_values(
    -1830        self, payload: typedefs.JSONObject
    -1831    ) -> activity.ExtendedWeaponValues:
    -1832
    -1833        assists: typing.Optional[int] = None
    -1834        if raw_assists := payload["values"].get("uniqueWeaponAssists"):
    -1835            assists = raw_assists["basic"]["value"]
    -1836        assists_damage: typing.Optional[int] = None
    -1837
    -1838        if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"):
    -1839            assists_damage = raw_assists_damage["basic"]["value"]
    -1840
    -1841        return activity.ExtendedWeaponValues(
    -1842            reference_id=int(payload["referenceId"]),
    -1843            kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"],
    -1844            precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][
    -1845                "value"
    -1846            ],
    -1847            assists=assists,
    -1848            assists_damage=assists_damage,
    -1849            precision_kills_percentage=(
    -1850                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"],
    -1851                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][
    -1852                    "displayValue"
    -1853                ],
    -1854            ),
    -1855        )
    -
    + + +

    All item components.

    +
    -

    Deserialize values of extended weapons JSON object.

    +
    +
    +
    + ALL_CHARACTERS = <ComponentType.ALL_CHARACTERS: (200, 201, 202, 203, 204, 205, 900)> -
    Parameters
    + +
    + + +

    All character components.

    +
    - -
    Returns
    +
    +
    +
    + ALL = <ComponentType.ALL: (100, 102, 103, 104, 200, 201, 202, 203, 204, 205, 900, 400, 101, 402, 309, 308, 305, 300, 301, 302, 303, 304, 306, 310, 900, 600, 700, 800, 500, 1100, 105, 102, 1200, 1000, 1300)> - + +
    + + +

    ALl components included.

    -
    - -
    - - def - deserialize_post_activity_player( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.activity.PostActivityPlayer: +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    - +
    +
    +
    +
    +
    + +
    +
    @typing.final
    -
    - -
    1878    def deserialize_post_activity_player(
    -1879        self, payload: typedefs.JSONObject, /
    -1880    ) -> activity.PostActivityPlayer:
    -1881        player = payload["player"]
    -1882
    -1883        class_hash: typedefs.NoneOr[int] = None
    -1884        if (class_hash := player.get("classHash")) is not None:
    -1885            class_hash = class_hash
    -1886
    -1887        race_hash: typedefs.NoneOr[int] = None
    -1888        if (race_hash := player.get("raceHash")) is not None:
    -1889            race_hash = race_hash
    -1890
    -1891        gender_hash: typedefs.NoneOr[int] = None
    -1892        if (gender_hash := player.get("genderHash")) is not None:
    -1893            gender_hash = gender_hash
    -1894
    -1895        character_class: undefined.UndefinedOr[str] = undefined.Undefined
    -1896        if (
    -1897            character_class := player.get("characterClass")
    -1898        ) and not typedefs.is_unknown(character_class):
    -1899            character_class = character_class
    -1900
    -1901        character_level: typedefs.NoneOr[int] = None
    -1902        if (character_level := player.get("characterLevel")) is not None:
    -1903            character_level = character_level
    -1904
    -1905        return activity.PostActivityPlayer(
    -1906            standing=int(payload["standing"]),
    -1907            score=int(payload["score"]["basic"]["value"]),
    -1908            character_id=payload["characterId"],
    -1909            destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]),
    -1910            character_class=character_class,
    -1911            character_level=character_level,
    -1912            race_hash=race_hash,
    -1913            gender_hash=gender_hash,
    -1914            class_hash=class_hash,
    -1915            light_level=int(player["lightLevel"]),
    -1916            emblem_hash=int(player["emblemHash"]),
    -1917            values=self._deserialize_activity_values(payload["values"]),
    -1918            extended_values=self._deserialize_extended_values(payload["extended"]),
    -1919        )
    -
    + class + CredentialType(builtins.int, aiobungie.Enum): + -

    Deserialize a JSON payload of a post activity player information.

    +
    + +
    661@typing.final
    +662class CredentialType(int, Enum):
    +663    """The types of the accounts system supports at bungie."""
    +664
    +665    NONE = 0
    +666    XUID = 1
    +667    PSNID = 2
    +668    WILD = 3
    +669    FAKE = 4
    +670    FACEBOOK = 5
    +671    GOOGLE = 8
    +672    WINDOWS = 9
    +673    DEMONID = 10
    +674    STEAMID = 12
    +675    BATTLENETID = 14
    +676    STADIAID = 16
    +677    TWITCHID = 18
    +
    -
    Parameters
    - +

    The types of the accounts system supports at bungie.

    +
    -
    Returns
    - - +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    +
    -
    - -
    - - def - deserialize_post_activity( self, payload: dict[str, typing.Any]) -> aiobungie.crates.activity.PostActivity: +
    +
    + +
    +
    @typing.final
    - + class + DamageType(builtins.int, aiobungie.Enum): + +
    - -
    1931    def deserialize_post_activity(
    -1932        self, payload: typedefs.JSONObject
    -1933    ) -> activity.PostActivity:
    -1934        period = time.clean_date(payload["period"])
    -1935        details = payload["activityDetails"]
    -1936        ref_id = int(details["referenceId"])
    -1937        instance_id = int(details["instanceId"])
    -1938        mode = enums.GameMode(details["mode"])
    -1939        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
    -1940        is_private = details["isPrivate"]
    -1941        membership_type = enums.MembershipType(int(details["membershipType"]))
    -1942        return activity.PostActivity(
    -1943            net=self._net,
    -1944            hash=ref_id,
    -1945            membership_type=membership_type,
    -1946            instance_id=instance_id,
    -1947            mode=mode,
    -1948            modes=modes,
    -1949            is_private=is_private,
    -1950            occurred_at=period,
    -1951            starting_phase=int(payload["startingPhaseIndex"]),
    -1952            players=[
    -1953                self.deserialize_post_activity_player(player)
    -1954                for player in payload["entries"]
    -1955            ],
    -1956            teams=[
    -1957                self._deserialize_post_activity_team(team) for team in payload["teams"]
    -1958            ],
    -1959        )
    +    
    +            
    539@typing.final
    +540class DamageType(int, Enum):
    +541    """Enums for Destiny Damage types"""
    +542
    +543    NONE = 0
    +544    KINETIC = 1
    +545    ARC = 2
    +546    SOLAR = 3
    +547    VOID = 4
    +548    RAID = 5
    +549    """This is a special damage type reserved for some raid activity encounters."""
    +550    STASIS = 6
     
    -

    Deserialize a JSON payload of a post activity information.

    - -
    Parameters
    +

    Enums for Destiny Damage types

    +
    - -
    Returns
    +
    +
    + RAID = <DamageType.RAID: 5> - + +
    + + +

    This is a special damage type reserved for some raid activity encounters.

    -
    - -
    - - def - deserialize_aggregated_activity( self, payload: dict[str, typing.Any]) -> aiobungie.crates.activity.AggregatedActivity: +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    - +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    + +
    +
    +
    +
    +
    + +
    +
    @typing.final
    + + class + Difficulty(builtins.int, aiobungie.Enum): + +
    - -
    1997    def deserialize_aggregated_activity(
    -1998        self, payload: typedefs.JSONObject
    -1999    ) -> activity.AggregatedActivity:
    -2000        return activity.AggregatedActivity(
    -2001            hash=int(payload["activityHash"]),
    -2002            values=self._deserialize_aggregated_activity_values(payload["values"]),
    -2003        )
    +    
    +            
    64@typing.final
    +65class Difficulty(int, enums.Enum):
    +66    """An enum for activities difficulties."""
    +67
    +68    TRIVIAL = 0
    +69    EASY = 1
    +70    NORMAL = 2
    +71    CHALLENGING = 3
    +72    HARD = 4
    +73    BRAVE = 5
    +74    ALMOST_IMPOSSIBLE = 6
    +75    IMPOSSIBLE = 7
     
    -

    Deserialize a JSON payload of an aggregated activity.

    - -
    Parameters
    +

    An enum for activities difficulties.

    +
    - -
    Returns
    +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    - -
    +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    + +
    +
    +
    + +
    +
    @typing.final
    -
    -
    - -
    - - def - deserialize_aggregated_activities( self, payload: dict[str, typing.Any]) -> aiobungie.FlatIterator[aiobungie.crates.activity.AggregatedActivity]: + class + Dungeon(builtins.int, aiobungie.Enum): - +
    - -
    2005    def deserialize_aggregated_activities(
    -2006        self, payload: typedefs.JSONObject
    -2007    ) -> iterators.FlatIterator[activity.AggregatedActivity]:
    -2008        return iterators.FlatIterator(
    -2009            [
    -2010                self.deserialize_aggregated_activity(activity)
    -2011                for activity in payload["activities"]
    -2012            ]
    -2013        )
    +    
    +            
    160@typing.final
    +161class Dungeon(int, Enum):
    +162    """An Enum for all available Dungeon/Like missions in Destiny 2."""
    +163
    +164    NORMAL_PRESAGE = 2124066889
    +165    """Normal Presage"""
    +166
    +167    MASTER_PRESAGE = 4212753278
    +168    """Master Presage"""
    +169
    +170    HARBINGER = 1738383283
    +171    """Harbinger"""
    +172
    +173    PROPHECY = 4148187374
    +174    """Prophecy"""
    +175
    +176    MASTER_POH = 785700673
    +177    """Master Pit of Heresy?"""
    +178
    +179    LEGEND_POH = 785700678
    +180    """Legend Pit of Heresy?"""
    +181
    +182    POH = 1375089621
    +183    """Normal Pit of Heresy."""
    +184
    +185    SHATTERED = 2032534090
    +186    """Shattered Throne"""
    +187
    +188    GOA_LEGEND = 4078656646
    +189    """Grasp of Avarice legend."""
    +190
    +191    GOA_MASTER = 3774021532
    +192    """Grasp of Avarice master."""
     
    -

    Deserialize a JSON payload of an array of aggregated activities.

    - -
    Parameters
    +

    An Enum for all available Dungeon/Like missions in Destiny 2.

    +
    - -
    Returns
    +
    +
    + NORMAL_PRESAGE = <Dungeon.NORMAL_PRESAGE: 2124066889> - + +
    + + +

    Normal Presage

    -
    - -
    - - def - deserialize_linked_profiles( self, payload: dict[str, typing.Any]) -> aiobungie.crates.profile.LinkedProfile: - - +
    +
    + MASTER_PRESAGE = <Dungeon.MASTER_PRESAGE: 4212753278> +
    - -
    2015    def deserialize_linked_profiles(
    -2016        self, payload: typedefs.JSONObject
    -2017    ) -> profile.LinkedProfile:
    -2018        bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"])
    -2019        error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
    -2020        profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
    -2021
    -2022        if raw_profile := payload.get("profiles"):
    -2023            for pfile in raw_profile:
    -2024                profiles_vec.append(self.deserialize_destiny_membership(pfile))
    -2025
    -2026        if raw_profiles_with_errors := payload.get("profilesWithErrors"):
    -2027            for raw_error_pfile in raw_profiles_with_errors:
    -2028                if error_pfile := raw_error_pfile.get("infoCard"):
    -2029                    error_profiles_vec.append(
    -2030                        self.deserialize_destiny_membership(error_pfile)
    -2031                    )
    -2032
    -2033        return profile.LinkedProfile(
    -2034            net=self._net,
    -2035            bungie=bungie_user,
    -2036            profiles=profiles_vec,
    -2037            profiles_with_errors=error_profiles_vec,
    -2038        )
    -
    - - -

    Deserialize a JSON payload of Bungie.net hard linked profile information.

    - -
    Parameters
    - - - -
    Returns
    - - + + +

    Master Presage

    -
    - -
    - - def - deserialize_clan_banners( self, payload: dict[str, typing.Any]) -> collections.abc.Sequence[aiobungie.crates.clans.ClanBanner]: - - +
    +
    + HARBINGER = <Dungeon.HARBINGER: 1738383283> +
    - -
    2040    def deserialize_clan_banners(
    -2041        self, payload: typedefs.JSONObject
    -2042    ) -> collections.Sequence[clans.ClanBanner]:
    -2043        banners_seq: typing.MutableSequence[clans.ClanBanner] = []
    -2044        if banners := payload.get("clanBannerDecals"):
    -2045            for k, v in banners.items():
    -2046                banner_obj = clans.ClanBanner(
    -2047                    id=int(k),
    -2048                    foreground=assets.Image(v["foregroundPath"]),
    -2049                    background=assets.Image(v["backgroundPath"]),
    -2050                )
    -2051                banners_seq.append(banner_obj)
    -2052        return banners_seq
    -
    + + +

    Harbinger

    +
    -

    Deserialize a JSON array of a clan banners information.

    +
    +
    +
    + PROPHECY = <Dungeon.PROPHECY: 4148187374> -
    Parameters
    + +
    + + +

    Prophecy

    +
    - -
    Returns
    +
    +
    +
    + MASTER_POH = <Dungeon.MASTER_POH: 785700673> - + +
    + + +

    Master Pit of Heresy?

    -
    - -
    - - def - deserialize_public_milestone_content( self, payload: dict[str, typing.Any]) -> aiobungie.crates.milestones.MilestoneContent: - - +
    +
    + LEGEND_POH = <Dungeon.LEGEND_POH: 785700678> +
    - -
    2054    def deserialize_public_milestone_content(
    -2055        self, payload: typedefs.JSONObject
    -2056    ) -> milestones.MilestoneContent:
    -2057        items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None
    -2058        if raw_categories := payload.get("itemCategories"):
    -2059            for item in raw_categories:
    -2060                title = undefined.Undefined
    -2061                if raw_title := item.get("title"):
    -2062                    if raw_title != typedefs.Unknown:
    -2063                        title = raw_title
    -2064                if raw_hashes := item.get("itemHashes"):
    -2065                    hashes: collections.Sequence[int] = raw_hashes
    -2066
    -2067                items_categoris = milestones.MilestoneItems(title=title, hashes=hashes)
    -2068
    -2069        about = undefined.Undefined
    -2070        if (raw_about := payload["about"]) != typedefs.Unknown:
    -2071            about = raw_about
    -2072
    -2073        status = undefined.Undefined
    -2074        if (raw_status := payload["status"]) != typedefs.Unknown:
    -2075            status = raw_status
    -2076
    -2077        tips: typing.MutableSequence[undefined.UndefinedOr[str]] = []
    -2078        if raw_tips := payload.get("tips"):
    -2079            for raw_tip in raw_tips:
    -2080                if raw_tip == typedefs.Unknown:
    -2081                    raw_tip = undefined.Undefined
    -2082                tips.append(raw_tip)
    -2083
    -2084        return milestones.MilestoneContent(
    -2085            about=about, status=status, tips=tips, items=items_categoris
    -2086        )
    -
    + + +

    Legend Pit of Heresy?

    +
    -

    Deserialize a JSON payload of milestone content information.

    +
    +
    +
    + POH = <Dungeon.POH: 1375089621> -
    Parameters
    + +
    + + +

    Normal Pit of Heresy.

    +
    - -
    Returns
    +
    +
    +
    + SHATTERED = <Dungeon.SHATTERED: 2032534090> - + +
    + + +

    Shattered Throne

    -
    - -
    - - def - deserialize_friend( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.friends.Friend: - - +
    +
    + GOA_LEGEND = <Dungeon.GOA_LEGEND: 4078656646> +
    - -
    2088    def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend:
    -2089        name = undefined.Undefined
    -2090        if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown:
    -2091            name = raw_name
    -2092
    -2093        bungie_user: typedefs.NoneOr[user.BungieUser] = None
    -2094
    -2095        if raw_bungie_user := payload.get("bungieNetUser"):
    -2096            bungie_user = self.deserialize_bungie_user(raw_bungie_user)
    -2097
    -2098        return friends.Friend(
    -2099            net=self._net,
    -2100            id=int(payload["lastSeenAsMembershipId"]),
    -2101            name=name,
    -2102            code=payload.get("bungieGlobalDisplayNameCode"),
    -2103            relationship=enums.Relationship(payload["relationship"]),
    -2104            user=bungie_user,
    -2105            online_status=enums.Presence(payload["onlineStatus"]),
    -2106            online_title=payload["onlineTitle"],
    -2107            type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]),
    -2108        )
    -
    - + + +

    Grasp of Avarice legend.

    +
    -

    Deserialize a JSON payload of a Bungie friend information.

    -
    Parameters
    +
    +
    +
    + GOA_MASTER = <Dungeon.GOA_MASTER: 3774021532> - + +
    + + +

    Grasp of Avarice master.

    +
    -
    Returns
    - -
    +
    +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    +
    -
    - -
    +
    +
    + +
    - def - deserialize_friends( self, payload: dict[str, typing.Any]) -> collections.abc.Sequence[aiobungie.crates.friends.Friend]: + class + Enum(enum.Enum): - +
    - -
    2110    def deserialize_friends(
    -2111        self, payload: typedefs.JSONObject
    -2112    ) -> collections.Sequence[friends.Friend]:
    -2113        mut_seq: typing.MutableSequence[friends.Friend] = []
    -2114        if raw_friends := payload.get("friends"):
    -2115            for friend in raw_friends:
    -2116                mut_seq.append(self.deserialize_friend(friend))
    -2117        return mut_seq
    +    
    +            
    72class Enum(__enum.Enum):
    +73    """Builtin Python enum with extra handlings."""
    +74
    +75    @property
    +76    def name(self) -> str:  # type: ignore[override]
    +77        return self._name_
    +78
    +79    @property
    +80    def value(self) -> typing.Any:  # type: ignore[override]
    +81        return self._value_
    +82
    +83    def __str__(self) -> str:
    +84        return self._name_
    +85
    +86    def __repr__(self) -> str:
    +87        return f"<{type(self).__name__}.{self._name_}: {self._value_!s}>"
    +88
    +89    def __int__(self) -> int:
    +90        if isinstance(self.value, _ITERABLE):
    +91            raise TypeError(
    +92                f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.",
    +93            )
    +94        return int(self.value)
     
    -

    Deserialize a JSON sequence of Bungie friends information.

    +

    Builtin Python enum with extra handlings.

    +
    -

    This is usually used to deserialize the incoming/outgoing friend requests.

    -
    Parameters
    +
    +
    + name: str + + +
    + + +

    The name of the Enum member.

    +
    - -
    Returns
    +
    +
    +
    + value: Any - + +
    + + +

    The value of the Enum member.

    -
    - -
    +
    +
    + +
    - def - deserialize_friend_requests( self, payload: dict[str, typing.Any]) -> aiobungie.crates.friends.FriendRequestView: + class + Factory(aiobungie.interfaces.factory.FactoryInterface): - +
    - -
    2119    def deserialize_friend_requests(
    -2120        self, payload: typedefs.JSONObject
    -2121    ) -> friends.FriendRequestView:
    -2122        incoming: typing.MutableSequence[friends.Friend] = []
    -2123        outgoing: typing.MutableSequence[friends.Friend] = []
    -2124
    -2125        if raw_incoming_requests := payload.get("incomingRequests"):
    -2126            for incoming_request in raw_incoming_requests:
    -2127                incoming.append(self.deserialize_friend(incoming_request))
    -2128
    -2129        if raw_outgoing_requests := payload.get("outgoingRequests"):
    -2130            for outgoing_request in raw_outgoing_requests:
    -2131                outgoing.append(self.deserialize_friend(outgoing_request))
    -2132
    -2133        return friends.FriendRequestView(incoming=incoming, outgoing=outgoing)
    +    
    +            
      61class Factory(interfaces.FactoryInterface):
    +  62    """The base deserialization factory class for all aiobungie objects.
    +  63
    +  64    Highly inspired hikari entity factory used to deserialize JSON responses from the REST client and turning them
    +  65    into a `aiobungie.crates` Python classes.
    +  66    """
    +  67
    +  68    __slots__ = ("_net",)
    +  69
    +  70    def __init__(self, net: traits.Netrunner) -> None:
    +  71        self._net = net
    +  72
    +  73    def deserialize_bungie_user(self, data: typedefs.JSONObject) -> user.BungieUser:
    +  74        return user.BungieUser(
    +  75            id=int(data["membershipId"]),
    +  76            created_at=time.clean_date(data["firstAccess"]),
    +  77            name=data.get("cachedBungieGlobalDisplayName", undefined.Undefined),
    +  78            is_deleted=data["isDeleted"],
    +  79            about=data["about"],
    +  80            updated_at=time.clean_date(data["lastUpdate"]),
    +  81            psn_name=data.get("psnDisplayName", None),
    +  82            stadia_name=data.get("stadiaDisplayName", None),
    +  83            steam_name=data.get("steamDisplayName", None),
    +  84            twitch_name=data.get("twitchDisplayName", None),
    +  85            blizzard_name=data.get("blizzardDisplayName", None),
    +  86            status=data["statusText"],
    +  87            locale=data["locale"],
    +  88            picture=assets.Image(path=str(data["profilePicturePath"])),
    +  89            code=data.get("cachedBungieGlobalDisplayNameCode", None),
    +  90            unique_name=data.get("uniqueName", None),
    +  91            theme_id=int(data["profileTheme"]),
    +  92            show_activity=bool(data["showActivity"]),
    +  93            theme_name=data["profileThemeName"],
    +  94            display_title=data["userTitleDisplay"],
    +  95        )
    +  96
    +  97    def deserialize_partial_bungie_user(
    +  98        self, payload: typedefs.JSONObject
    +  99    ) -> user.PartialBungieUser:
    + 100        return user.PartialBungieUser(
    + 101            net=self._net,
    + 102            types=[
    + 103                enums.MembershipType(type_)
    + 104                for type_ in payload.get("applicableMembershipTypes", [])
    + 105            ],
    + 106            name=payload.get("displayName", undefined.Undefined),
    + 107            id=int(payload["membershipId"]),
    + 108            crossave_override=enums.MembershipType(payload["crossSaveOverride"]),
    + 109            is_public=payload["isPublic"],
    + 110            icon=assets.Image(payload.get("iconPath", "")),
    + 111            type=enums.MembershipType(payload["membershipType"]),
    + 112        )
    + 113
    + 114    def deserialize_destiny_membership(
    + 115        self, payload: typedefs.JSONObject
    + 116    ) -> user.DestinyMembership:
    + 117        name: undefined.UndefinedOr[str] = undefined.Undefined
    + 118        if (
    + 119            raw_name := payload.get("bungieGlobalDisplayName", "")
    + 120        ) and not typedefs.is_unknown(raw_name):
    + 121            name = raw_name
    + 122
    + 123        return user.DestinyMembership(
    + 124            net=self._net,
    + 125            id=int(payload["membershipId"]),
    + 126            name=name,
    + 127            code=payload.get("bungieGlobalDisplayNameCode", None),
    + 128            last_seen_name=payload.get("LastSeenDisplayName")
    + 129            or payload.get("displayName")  # noqa: W503
    + 130            or "",  # noqa: W503
    + 131            type=enums.MembershipType(payload["membershipType"]),
    + 132            is_public=payload["isPublic"],
    + 133            crossave_override=enums.MembershipType(payload["crossSaveOverride"]),
    + 134            icon=assets.Image(payload.get("iconPath", "")),
    + 135            types=[
    + 136                enums.MembershipType(type_)
    + 137                for type_ in payload.get("applicableMembershipTypes", [])
    + 138            ],
    + 139        )
    + 140
    + 141    def deserialize_destiny_memberships(
    + 142        self, data: typedefs.JSONArray
    + 143    ) -> collections.Sequence[user.DestinyMembership]:
    + 144        return [self.deserialize_destiny_membership(membership) for membership in data]
    + 145
    + 146    def deserialize_user(self, data: typedefs.JSONObject) -> user.User:
    + 147
    + 148        primary_membership_id: typing.Optional[int] = None
    + 149        if raw_primary_id := data.get("primaryMembershipId"):
    + 150            primary_membership_id = int(raw_primary_id)
    + 151
    + 152        return user.User(
    + 153            bungie=self.deserialize_bungie_user(data["bungieNetUser"]),
    + 154            destiny=self.deserialize_destiny_memberships(data["destinyMemberships"]),
    + 155            primary_membership_id=primary_membership_id,
    + 156        )
    + 157
    + 158    def deserialize_searched_user(
    + 159        self, payload: typedefs.JSONObject
    + 160    ) -> user.SearchableDestinyUser:
    + 161        name: undefined.UndefinedOr[str] = undefined.Undefined
    + 162        if (raw_name := payload["bungieGlobalDisplayName"]) and not typedefs.is_unknown(
    + 163            raw_name
    + 164        ):
    + 165            name = raw_name
    + 166
    + 167        code: typing.Optional[int] = None
    + 168        if raw_code := payload.get("bungieGlobalDisplayNameCode"):
    + 169            code = int(raw_code)
    + 170
    + 171        bungie_id: typing.Optional[int] = None
    + 172        if raw_bungie_id := payload.get("bungieNetMembershipId"):
    + 173            bungie_id = int(raw_bungie_id)
    + 174
    + 175        return user.SearchableDestinyUser(
    + 176            name=name,
    + 177            code=code,
    + 178            bungie_id=bungie_id,
    + 179            memberships=self.deserialize_destiny_memberships(
    + 180                payload["destinyMemberships"]
    + 181            ),
    + 182        )
    + 183
    + 184    def deserialize_user_credentials(
    + 185        self, payload: typedefs.JSONArray
    + 186    ) -> collections.Sequence[user.UserCredentials]:
    + 187        return [
    + 188            user.UserCredentials(
    + 189                type=enums.CredentialType(int(creds["credentialType"])),
    + 190                display_name=creds["credentialDisplayName"],
    + 191                is_public=creds["isPublic"],
    + 192                self_as_string=creds.get("credentialAsString", undefined.Undefined),
    + 193            )
    + 194            for creds in payload
    + 195        ]
    + 196
    + 197    def deserialize_user_themes(
    + 198        self, payload: typedefs.JSONArray
    + 199    ) -> collections.Sequence[user.UserThemes]:
    + 200        return [
    + 201            user.UserThemes(
    + 202                id=int(entry["userThemeId"]),
    + 203                name=entry["userThemeName"]
    + 204                if "userThemeName" in entry
    + 205                else undefined.Undefined,
    + 206                description=entry["userThemeDescription"]
    + 207                if "userThemeDescription" in entry
    + 208                else undefined.Undefined,
    + 209            )
    + 210            for entry in payload
    + 211        ]
    + 212
    + 213    def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan:
    + 214
    + 215        # This is kinda redundant
    + 216        data = payload
    + 217
    + 218        # This is always outside the details.
    + 219        current_user_map: typing.Optional[
    + 220            collections.Mapping[str, clans.ClanMember]
    + 221        ] = None
    + 222        if raw_current_user_map := payload.get("currentUserMemberMap"):
    + 223            current_user_map = {
    + 224                membership_type: self.deserialize_clan_member(membership)
    + 225                for membership_type, membership in raw_current_user_map.items()
    + 226            }
    + 227
    + 228        try:
    + 229            data = payload["detail"]
    + 230        except KeyError:
    + 231            pass
    + 232
    + 233        id = data["groupId"]
    + 234        name = data["name"]
    + 235        created_at = data["creationDate"]
    + 236        member_count = data["memberCount"]
    + 237        about = data["about"]
    + 238        motto = data["motto"]
    + 239        is_public = data["isPublic"]
    + 240        banner = assets.Image(str(data["bannerPath"]))
    + 241        avatar = assets.Image(str(data["avatarPath"]))
    + 242        tags = data["tags"]
    + 243        type = data["groupType"]
    + 244
    + 245        features = data["features"]
    + 246        features_obj = clans.ClanFeatures(
    + 247            max_members=features["maximumMembers"],
    + 248            max_membership_types=features["maximumMembershipsOfGroupType"],
    + 249            capabilities=features["capabilities"],
    + 250            membership_types=features["membershipTypes"],
    + 251            invite_permissions=features["invitePermissionOverride"],
    + 252            update_banner_permissions=features["updateBannerPermissionOverride"],
    + 253            update_culture_permissions=features["updateCulturePermissionOverride"],
    + 254            join_level=features["joinLevel"],
    + 255        )
    + 256
    + 257        information: typedefs.JSONObject = data["clanInfo"]
    + 258        progression: collections.Mapping[int, progressions.Progression] = {
    + 259            int(prog_hash): self.deserialize_progressions(prog)
    + 260            for prog_hash, prog in information["d2ClanProgressions"].items()
    + 261        }
    + 262
    + 263        founder: typedefs.NoneOr[clans.ClanMember] = None
    + 264        if raw_founder := payload.get("founder"):
    + 265            founder = self.deserialize_clan_member(raw_founder)
    + 266
    + 267        return clans.Clan(
    + 268            net=self._net,
    + 269            id=int(id),
    + 270            name=name,
    + 271            type=enums.GroupType(type),
    + 272            created_at=time.clean_date(created_at),
    + 273            member_count=member_count,
    + 274            motto=motto,
    + 275            about=about,
    + 276            is_public=is_public,
    + 277            banner=banner,
    + 278            avatar=avatar,
    + 279            tags=tags,
    + 280            features=features_obj,
    + 281            owner=founder,
    + 282            progressions=progression,
    + 283            call_sign=information["clanCallsign"],
    + 284            banner_data=information["clanBannerData"],
    + 285            chat_security=data["chatSecurity"],
    + 286            conversation_id=int(data["conversationId"]),
    + 287            allow_chat=data["allowChat"],
    + 288            theme=data["theme"],
    + 289            current_user_membership=current_user_map,
    + 290        )
    + 291
    + 292    def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember:
    + 293        destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"])
    + 294        return clans.ClanMember(
    + 295            net=self._net,
    + 296            last_seen_name=destiny_user.last_seen_name,
    + 297            id=destiny_user.id,
    + 298            name=destiny_user.name,
    + 299            icon=destiny_user.icon,
    + 300            last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])),
    + 301            group_id=int(data["groupId"]),
    + 302            joined_at=time.clean_date(data["joinDate"]),
    + 303            types=destiny_user.types,
    + 304            is_public=destiny_user.is_public,
    + 305            type=destiny_user.type,
    + 306            code=destiny_user.code,
    + 307            is_online=data["isOnline"],
    + 308            crossave_override=destiny_user.crossave_override,
    + 309            bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"])
    + 310            if "bungieNetUserInfo" in data
    + 311            else None,
    + 312            member_type=enums.ClanMemberType(int(data["memberType"])),
    + 313        )
    + 314
    + 315    def deserialize_clan_members(
    + 316        self, data: typedefs.JSONObject, /
    + 317    ) -> iterators.Iterator[clans.ClanMember]:
    + 318        return iterators.Iterator(
    + 319            [self.deserialize_clan_member(member) for member in data["results"]]
    + 320        )
    + 321
    + 322    def deserialize_group_member(
    + 323        self, payload: typedefs.JSONObject
    + 324    ) -> clans.GroupMember:
    + 325        member = payload["member"]
    + 326        return clans.GroupMember(
    + 327            net=self._net,
    + 328            join_date=time.clean_date(member["joinDate"]),
    + 329            group_id=int(member["groupId"]),
    + 330            member_type=enums.ClanMemberType(member["memberType"]),
    + 331            is_online=member["isOnline"],
    + 332            last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])),
    + 333            inactive_memberships=payload.get("areAllMembershipsInactive", None),
    + 334            member=self.deserialize_destiny_membership(member["destinyUserInfo"]),
    + 335            group=self.deserialize_clan(payload["group"]),
    + 336        )
    + 337
    + 338    def _deserialize_clan_conversation(
    + 339        self, payload: typedefs.JSONObject
    + 340    ) -> clans.ClanConversation:
    + 341        return clans.ClanConversation(
    + 342            net=self._net,
    + 343            id=int(payload["conversationId"]),
    + 344            group_id=int(payload["groupId"]),
    + 345            name=(
    + 346                payload["chatName"]
    + 347                if not typedefs.is_unknown(payload["chatName"])
    + 348                else undefined.Undefined
    + 349            ),
    + 350            chat_enabled=payload["chatEnabled"],
    + 351            security=payload["chatSecurity"],
    + 352        )
    + 353
    + 354    def deserialize_clan_conversations(
    + 355        self, payload: typedefs.JSONArray
    + 356    ) -> collections.Sequence[clans.ClanConversation]:
    + 357        return [self._deserialize_clan_conversation(conv) for conv in payload]
    + 358
    + 359    def deserialize_app_owner(
    + 360        self, payload: typedefs.JSONObject
    + 361    ) -> application.ApplicationOwner:
    + 362        return application.ApplicationOwner(
    + 363            net=self._net,
    + 364            name=payload.get("bungieGlobalDisplayName", undefined.Undefined),
    + 365            id=int(payload["membershipId"]),
    + 366            type=enums.MembershipType(payload["membershipType"]),
    + 367            icon=assets.Image(str(payload["iconPath"])),
    + 368            is_public=payload["isPublic"],
    + 369            code=payload.get("bungieGlobalDisplayNameCode", None),
    + 370        )
    + 371
    + 372    def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application:
    + 373        return application.Application(
    + 374            id=int(payload["applicationId"]),
    + 375            name=payload["name"],
    + 376            link=payload["link"],
    + 377            status=payload["status"],
    + 378            redirect_url=payload.get("redirectUrl", None),
    + 379            created_at=time.clean_date(str(payload["creationDate"])),
    + 380            published_at=time.clean_date(str(payload["firstPublished"])),
    + 381            owner=self.deserialize_app_owner(payload["team"][0]["user"]),  # type: ignore
    + 382            scope=payload.get("scope", undefined.Undefined),
    + 383        )
    + 384
    + 385    def _set_character_attrs(self, payload: typedefs.JSONObject) -> character.Character:
    + 386        total_time = time.format_played(int(payload["minutesPlayedTotal"]), suffix=True)
    + 387        return character.Character(
    + 388            net=self._net,
    + 389            id=int(payload["characterId"]),
    + 390            gender=enums.Gender(payload["genderType"]),
    + 391            race=enums.Race(payload["raceType"]),
    + 392            class_type=enums.Class(payload["classType"]),
    + 393            emblem=assets.Image(str(payload["emblemBackgroundPath"])),
    + 394            emblem_icon=assets.Image(str(payload["emblemPath"])),
    + 395            emblem_hash=int(payload["emblemHash"]),
    + 396            last_played=time.clean_date(payload["dateLastPlayed"]),
    + 397            total_played_time=total_time,
    + 398            member_id=int(payload["membershipId"]),
    + 399            member_type=enums.MembershipType(payload["membershipType"]),
    + 400            level=payload["baseCharacterLevel"],
    + 401            title_hash=payload.get("titleRecordHash", None),
    + 402            light=payload["light"],
    + 403            stats={enums.Stat(int(k)): v for k, v in payload["stats"].items()},
    + 404        )
    + 405
    + 406    def deserialize_profile(
    + 407        self, payload: typedefs.JSONObject, /
    + 408    ) -> typing.Optional[profile.Profile]:
    + 409        if (raw_profile := payload.get("data")) is None:
    + 410            return None
    + 411
    + 412        payload = raw_profile
    + 413        id = int(payload["userInfo"]["membershipId"])
    + 414        name = payload["userInfo"]["displayName"]
    + 415        is_public = payload["userInfo"]["isPublic"]
    + 416        type = enums.MembershipType(payload["userInfo"]["membershipType"])
    + 417        last_played = time.clean_date(str(payload["dateLastPlayed"]))
    + 418        character_ids = [int(cid) for cid in payload["characterIds"]]
    + 419        power_cap = payload["currentSeasonRewardPowerCap"]
    + 420
    + 421        return profile.Profile(
    + 422            id=int(id),
    + 423            name=name,
    + 424            is_public=is_public,
    + 425            type=type,
    + 426            last_played=last_played,
    + 427            character_ids=character_ids,
    + 428            power_cap=power_cap,
    + 429            net=self._net,
    + 430        )
    + 431
    + 432    def deserialize_profile_item(
    + 433        self, payload: typedefs.JSONObject
    + 434    ) -> profile.ProfileItemImpl:
    + 435
    + 436        instance_id: typing.Optional[int] = None
    + 437        if raw_instance_id := payload.get("itemInstanceId"):
    + 438            instance_id = int(raw_instance_id)
    + 439
    + 440        version_number: typing.Optional[int] = None
    + 441        if raw_version := payload.get("versionNumber"):
    + 442            version_number = int(raw_version)
    + 443
    + 444        transfer_status = enums.TransferStatus(payload["transferStatus"])
    + 445
    + 446        return profile.ProfileItemImpl(
    + 447            net=self._net,
    + 448            hash=payload["itemHash"],
    + 449            quantity=payload["quantity"],
    + 450            bind_status=enums.ItemBindStatus(payload["bindStatus"]),
    + 451            location=enums.ItemLocation(payload["location"]),
    + 452            bucket=payload["bucketHash"],
    + 453            transfer_status=transfer_status,
    + 454            lockable=payload["lockable"],
    + 455            state=enums.ItemState(payload["state"]),
    + 456            dismantel_permissions=payload["dismantlePermission"],
    + 457            is_wrapper=payload["isWrapper"],
    + 458            instance_id=instance_id,
    + 459            version_number=version_number,
    + 460            ornament_id=payload.get("overrideStyleItemHash"),
    + 461        )
    + 462
    + 463    def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective:
    + 464        return records.Objective(
    + 465            net=self._net,
    + 466            hash=payload["objectiveHash"],
    + 467            visible=payload["visible"],
    + 468            complete=payload["complete"],
    + 469            completion_value=payload["completionValue"],
    + 470            progress=payload.get("progress"),
    + 471            destination_hash=payload.get("destinationHash"),
    + 472            activity_hash=payload.get("activityHash"),
    + 473        )
    + 474
    + 475    def deserialize_records(
    + 476        self,
    + 477        payload: typedefs.JSONObject,
    + 478        scores: typing.Optional[records.RecordScores] = None,
    + 479        **nodes: int,
    + 480    ) -> records.Record:
    + 481        objectives: typing.Optional[list[records.Objective]] = None
    + 482        interval_objectives: typing.Optional[list[records.Objective]] = None
    + 483        record_state: typedefs.IntAnd[records.RecordState]
    + 484
    + 485        record_state = records.RecordState(payload["state"])
    + 486
    + 487        if raw_objs := payload.get("objectives"):
    + 488            objectives = [self.deserialize_objectives(obj) for obj in raw_objs]
    + 489
    + 490        if raw_interval_objs := payload.get("intervalObjectives"):
    + 491            interval_objectives = [
    + 492                self.deserialize_objectives(obj) for obj in raw_interval_objs
    + 493            ]
    + 494
    + 495        return records.Record(
    + 496            scores=scores,
    + 497            categories_node_hash=nodes.get("categories_hash", undefined.Undefined),
    + 498            seals_node_hash=nodes.get("seals_hash", undefined.Undefined),
    + 499            state=record_state,
    + 500            objectives=objectives,
    + 501            interval_objectives=interval_objectives,
    + 502            redeemed_count=payload.get("intervalsRedeemedCount", 0),
    + 503            completion_times=payload.get("completedCount", None),
    + 504            reward_visibility=payload.get("rewardVisibilty", None),
    + 505        )
    + 506
    + 507    def deserialize_character_records(
    + 508        self,
    + 509        payload: typedefs.JSONObject,
    + 510        scores: typing.Optional[records.RecordScores] = None,
    + 511        record_hashes: typing.Optional[list[int]] = None,
    + 512    ) -> records.CharacterRecord:
    + 513
    + 514        record = self.deserialize_records(payload, scores)
    + 515        return records.CharacterRecord(
    + 516            scores=scores,
    + 517            categories_node_hash=record.categories_node_hash,
    + 518            seals_node_hash=record.seals_node_hash,
    + 519            state=record.state,
    + 520            objectives=record.objectives,
    + 521            interval_objectives=record.interval_objectives,
    + 522            redeemed_count=payload.get("intervalsRedeemedCount", 0),
    + 523            completion_times=payload.get("completedCount"),
    + 524            reward_visibility=payload.get("rewardVisibilty"),
    + 525            record_hashes=record_hashes or [],
    + 526        )
    + 527
    + 528    def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye:
    + 529        return character.Dye(
    + 530            channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"]
    + 531        )
    + 532
    + 533    def deserialize_character_customization(
    + 534        self, payload: typedefs.JSONObject
    + 535    ) -> character.CustomizationOptions:
    + 536        return character.CustomizationOptions(
    + 537            personality=payload["personality"],
    + 538            face=payload["face"],
    + 539            skin_color=payload["skinColor"],
    + 540            lip_color=payload["lipColor"],
    + 541            eye_color=payload["eyeColor"],
    + 542            hair_colors=payload.get("hairColors", []),
    + 543            feature_colors=payload.get("featureColors", []),
    + 544            decal_color=payload["decalColor"],
    + 545            wear_helmet=payload["wearHelmet"],
    + 546            hair_index=payload["hairIndex"],
    + 547            feature_index=payload["featureIndex"],
    + 548            decal_index=payload["decalIndex"],
    + 549        )
    + 550
    + 551    def deserialize_character_minimal_equipments(
    + 552        self, payload: typedefs.JSONObject
    + 553    ) -> character.MinimalEquipments:
    + 554        dyes = None
    + 555        if raw_dyes := payload.get("dyes"):
    + 556            if raw_dyes:
    + 557                dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes]
    + 558        return character.MinimalEquipments(
    + 559            net=self._net, item_hash=payload["itemHash"], dyes=dyes
    + 560        )
    + 561
    + 562    def deserialize_character_render_data(
    + 563        self, payload: typedefs.JSONObject, /
    + 564    ) -> character.RenderedData:
    + 565        return character.RenderedData(
    + 566            net=self._net,
    + 567            customization=self.deserialize_character_customization(
    + 568                payload["customization"]
    + 569            ),
    + 570            custom_dyes=[
    + 571                self.deserialize_character_dye(dye)
    + 572                for dye in payload["customDyes"]
    + 573                if dye
    + 574            ],
    + 575            equipment=[
    + 576                self.deserialize_character_minimal_equipments(equipment)
    + 577                for equipment in payload["peerView"]["equipment"]
    + 578            ],
    + 579        )
    + 580
    + 581    def deserialize_available_activity(
    + 582        self, payload: typedefs.JSONObject
    + 583    ) -> activity.AvailableActivity:
    + 584        return activity.AvailableActivity(
    + 585            hash=payload["activityHash"],
    + 586            is_new=payload["isNew"],
    + 587            is_completed=payload["isCompleted"],
    + 588            is_visible=payload["isVisible"],
    + 589            display_level=payload.get("displayLevel"),
    + 590            recommended_light=payload.get("recommendedLight"),
    + 591            difficulty=activity.Difficulty(payload["difficultyTier"]),
    + 592            can_join=payload["canJoin"],
    + 593            can_lead=payload["canLead"],
    + 594        )
    + 595
    + 596    def deserialize_character_activity(
    + 597        self, payload: typedefs.JSONObject
    + 598    ) -> activity.CharacterActivity:
    + 599        current_mode: typing.Optional[enums.GameMode] = None
    + 600        if raw_current_mode := payload.get("currentActivityModeType"):
    + 601            current_mode = enums.GameMode(raw_current_mode)
    + 602
    + 603        current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None
    + 604        if raw_current_modes := payload.get("currentActivityModeTypes"):
    + 605            current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes]
    + 606
    + 607        return activity.CharacterActivity(
    + 608            date_started=time.clean_date(payload["dateActivityStarted"]),
    + 609            current_hash=payload["currentActivityHash"],
    + 610            current_mode_hash=payload["currentActivityModeHash"],
    + 611            current_mode=current_mode,
    + 612            current_mode_hashes=payload.get("currentActivityModeHashes"),
    + 613            current_mode_types=current_mode_types,
    + 614            current_playlist_hash=payload.get("currentPlaylistActivityHash"),
    + 615            last_story_hash=payload["lastCompletedStoryHash"],
    + 616            available_activities=[
    + 617                self.deserialize_available_activity(activity_)
    + 618                for activity_ in payload["availableActivities"]
    + 619            ],
    + 620        )
    + 621
    + 622    def deserialize_profile_items(
    + 623        self, payload: typedefs.JSONObject, /
    + 624    ) -> list[profile.ProfileItemImpl]:
    + 625        return [self.deserialize_profile_item(item) for item in payload["items"]]
    + 626
    + 627    def _deserialize_node(self, payload: typedefs.JSONObject) -> records.Node:
    + 628        return records.Node(
    + 629            state=int(payload["state"]),
    + 630            objective=self.deserialize_objectives(payload["objective"])
    + 631            if "objective" in payload
    + 632            else None,
    + 633            progress_value=int(payload["progressValue"]),
    + 634            completion_value=int(payload["completionValue"]),
    + 635            record_category_score=int(payload["recordCategoryScore"])
    + 636            if "recordCategoryScore" in payload
    + 637            else None,
    + 638        )
    + 639
    + 640    @staticmethod
    + 641    def _deserialize_collectible(payload: typedefs.JSONObject) -> items.Collectible:
    + 642        recent_collectibles: typing.Optional[collections.Collection[int]] = None
    + 643        if raw_recent_collectibles := payload.get("recentCollectibleHashes"):
    + 644            recent_collectibles = [
    + 645                int(item_hash) for item_hash in raw_recent_collectibles
    + 646            ]
    + 647
    + 648        collectibles: dict[int, int] = {}
    + 649        for item_hash, mapping in payload["collectibles"].items():
    + 650            collectibles[int(item_hash)] = int(mapping["state"])
    + 651
    + 652        return items.Collectible(
    + 653            recent_collectibles=recent_collectibles,
    + 654            collectibles=collectibles,
    + 655            collection_categorie_hash=int(payload["collectionCategoriesRootNodeHash"]),
    + 656            collection_badges_hash=int(payload["collectionBadgesRootNodeHash"]),
    + 657        )
    + 658
    + 659    @staticmethod
    + 660    def _deserialize_currencies(
    + 661        payload: typedefs.JSONObject,
    + 662    ) -> collections.Sequence[items.Currency]:
    + 663        return [
    + 664            items.Currency(hash=int(item_hash), amount=int(amount))
    + 665            for item_hash, amount in payload["itemQuantities"].items()
    + 666        ]
    + 667
    + 668    def deserialize_progressions(
    + 669        self, payload: typedefs.JSONObject
    + 670    ) -> progressions.Progression:
    + 671        return progressions.Progression(
    + 672            hash=int(payload["progressionHash"]),
    + 673            level=int(payload["level"]),
    + 674            cap=int(payload["levelCap"]),
    + 675            daily_limit=int(payload["dailyLimit"]),
    + 676            weekly_limit=int(payload["weeklyLimit"]),
    + 677            current_progress=int(payload["currentProgress"]),
    + 678            daily_progress=int(payload["dailyProgress"]),
    + 679            needed=int(payload["progressToNextLevel"]),
    + 680            next_level=int(payload["nextLevelAt"]),
    + 681        )
    + 682
    + 683    def _deserialize_factions(
    + 684        self, payload: typedefs.JSONObject
    + 685    ) -> progressions.Factions:
    + 686        progs = self.deserialize_progressions(payload)
    + 687        return progressions.Factions(
    + 688            hash=progs.hash,
    + 689            level=progs.level,
    + 690            cap=progs.cap,
    + 691            daily_limit=progs.daily_limit,
    + 692            weekly_limit=progs.weekly_limit,
    + 693            current_progress=progs.current_progress,
    + 694            daily_progress=progs.daily_progress,
    + 695            needed=progs.needed,
    + 696            next_level=progs.next_level,
    + 697            faction_hash=payload["factionHash"],
    + 698            faction_vendor_hash=payload["factionVendorIndex"],
    + 699        )
    + 700
    + 701    def _deserialize_milestone_available_quest(
    + 702        self, payload: typedefs.JSONObject
    + 703    ) -> milestones.MilestoneQuest:
    + 704        return milestones.MilestoneQuest(
    + 705            item_hash=payload["questItemHash"],
    + 706            status=self._deserialize_milestone_quest_status(payload["status"]),
    + 707        )
    + 708
    + 709    def _deserialize_milestone_activity(
    + 710        self, payload: typedefs.JSONObject
    + 711    ) -> milestones.MilestoneActivity:
    + 712
    + 713        phases: typing.Optional[
    + 714            collections.Sequence[milestones.MilestoneActivityPhase]
    + 715        ] = None
    + 716        if raw_phases := payload.get("phases"):
    + 717            phases = [
    + 718                milestones.MilestoneActivityPhase(
    + 719                    is_completed=obj["complete"], hash=obj["phaseHash"]
    + 720                )
    + 721                for obj in raw_phases
    + 722            ]
    + 723
    + 724        return milestones.MilestoneActivity(
    + 725            hash=payload["activityHash"],
    + 726            challenges=[
    + 727                self.deserialize_objectives(obj["objective"])
    + 728                for obj in payload["challenges"]
    + 729            ],
    + 730            modifier_hashes=payload.get("modifierHashes"),
    + 731            boolean_options=payload.get("booleanActivityOptions"),
    + 732            phases=phases,
    + 733        )
    + 734
    + 735    def _deserialize_milestone_quest_status(
    + 736        self, payload: typedefs.JSONObject
    + 737    ) -> milestones.QuestStatus:
    + 738        return milestones.QuestStatus(
    + 739            net=self._net,
    + 740            quest_hash=payload["questHash"],
    + 741            step_hash=payload["stepHash"],
    + 742            step_objectives=[
    + 743                self.deserialize_objectives(objective)
    + 744                for objective in payload["stepObjectives"]
    + 745            ],
    + 746            is_tracked=payload["tracked"],
    + 747            is_completed=payload["completed"],
    + 748            started=payload["started"],
    + 749            item_instance_id=payload["itemInstanceId"],
    + 750            vendor_hash=payload.get("vendorHash"),
    + 751            is_redeemed=payload["redeemed"],
    + 752        )
    + 753
    + 754    def _deserialize_milestone_rewards(
    + 755        self, payload: typedefs.JSONObject
    + 756    ) -> milestones.MilestoneReward:
    + 757        return milestones.MilestoneReward(
    + 758            category_hash=payload["rewardCategoryHash"],
    + 759            entries=[
    + 760                milestones.MilestoneRewardEntry(
    + 761                    entry_hash=entry["rewardEntryHash"],
    + 762                    is_earned=entry["earned"],
    + 763                    is_redeemed=entry["redeemed"],
    + 764                )
    + 765                for entry in payload["entries"]
    + 766            ],
    + 767        )
    + 768
    + 769    def deserialize_milestone(
    + 770        self, payload: typedefs.JSONObject
    + 771    ) -> milestones.Milestone:
    + 772        start_date: typing.Optional[datetime.datetime] = None
    + 773        if raw_start_date := payload.get("startDate"):
    + 774            start_date = time.clean_date(raw_start_date)
    + 775
    + 776        end_date: typing.Optional[datetime.datetime] = None
    + 777        if raw_end_date := payload.get("endDate"):
    + 778            end_date = time.clean_date(raw_end_date)
    + 779
    + 780        rewards: typing.Optional[
    + 781            collections.Collection[milestones.MilestoneReward]
    + 782        ] = None
    + 783        if raw_rewards := payload.get("rewards"):
    + 784            rewards = [
    + 785                self._deserialize_milestone_rewards(reward) for reward in raw_rewards
    + 786            ]
    + 787
    + 788        activities: typing.Optional[
    + 789            collections.Sequence[milestones.MilestoneActivity]
    + 790        ] = None
    + 791        if raw_activities := payload.get("activities"):
    + 792            activities = [
    + 793                self._deserialize_milestone_activity(active)
    + 794                for active in raw_activities
    + 795            ]
    + 796
    + 797        quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None
    + 798        if raw_quests := payload.get("availableQuests"):
    + 799            quests = [
    + 800                self._deserialize_milestone_available_quest(quest)
    + 801                for quest in raw_quests
    + 802            ]
    + 803
    + 804        vendors: typing.Optional[
    + 805            collections.Sequence[milestones.MilestoneVendor]
    + 806        ] = None
    + 807        if raw_vendors := payload.get("vendors"):
    + 808            vendors = [
    + 809                milestones.MilestoneVendor(
    + 810                    vendor_hash=vendor["vendorHash"],
    + 811                    preview_itemhash=vendor.get("previewItemHash"),
    + 812                )
    + 813                for vendor in raw_vendors
    + 814            ]
    + 815
    + 816        return milestones.Milestone(
    + 817            hash=payload["milestoneHash"],
    + 818            start_date=start_date,
    + 819            end_date=end_date,
    + 820            order=payload["order"],
    + 821            rewards=rewards,
    + 822            available_quests=quests,
    + 823            activities=activities,
    + 824            vendors=vendors,
    + 825        )
    + 826
    + 827    def _deserialize_artifact_tiers(
    + 828        self, payload: typedefs.JSONObject
    + 829    ) -> season.ArtifactTier:
    + 830        return season.ArtifactTier(
    + 831            hash=payload["tierHash"],
    + 832            is_unlocked=payload["isUnlocked"],
    + 833            points_to_unlock=payload["pointsToUnlock"],
    + 834            items=[
    + 835                season.ArtifactTierItem(
    + 836                    hash=item["itemHash"], is_active=item["isActive"]
    + 837                )
    + 838                for item in payload["items"]
    + 839            ],
    + 840        )
    + 841
    + 842    def deserialize_characters(
    + 843        self, payload: typedefs.JSONObject
    + 844    ) -> collections.Mapping[int, character.Character]:
    + 845        return {
    + 846            int(char_id): self._set_character_attrs(char)
    + 847            for char_id, char in payload["data"].items()
    + 848        }
    + 849
    + 850    def deserialize_character(
    + 851        self, payload: typedefs.JSONObject
    + 852    ) -> character.Character:
    + 853        return self._set_character_attrs(payload)
    + 854
    + 855    def deserialize_character_equipments(
    + 856        self, payload: typedefs.JSONObject
    + 857    ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]:
    + 858        return {
    + 859            int(char_id): self.deserialize_profile_items(item)
    + 860            for char_id, item in payload["data"].items()
    + 861        }
    + 862
    + 863    def deserialize_character_activities(
    + 864        self, payload: typedefs.JSONObject
    + 865    ) -> collections.Mapping[int, activity.CharacterActivity]:
    + 866        return {
    + 867            int(char_id): self.deserialize_character_activity(data)
    + 868            for char_id, data in payload["data"].items()
    + 869        }
    + 870
    + 871    def deserialize_characters_render_data(
    + 872        self, payload: typedefs.JSONObject
    + 873    ) -> collections.Mapping[int, character.RenderedData]:
    + 874        return {
    + 875            int(char_id): self.deserialize_character_render_data(data)
    + 876            for char_id, data in payload["data"].items()
    + 877        }
    + 878
    + 879    def deserialize_character_progressions(
    + 880        self, payload: typedefs.JSONObject
    + 881    ) -> character.CharacterProgression:
    + 882        progressions_ = {
    + 883            int(prog_id): self.deserialize_progressions(prog)
    + 884            for prog_id, prog in payload["progressions"].items()
    + 885        }
    + 886
    + 887        factions = {
    + 888            int(faction_id): self._deserialize_factions(faction)
    + 889            for faction_id, faction in payload["factions"].items()
    + 890        }
    + 891
    + 892        milestones_ = {
    + 893            int(milestone_hash): self.deserialize_milestone(milestone)
    + 894            for milestone_hash, milestone in payload["milestones"].items()
    + 895        }
    + 896
    + 897        uninstanced_item_objectives = {
    + 898            int(item_hash): [self.deserialize_objectives(ins) for ins in obj]
    + 899            for item_hash, obj in payload["uninstancedItemObjectives"].items()
    + 900        }
    + 901
    + 902        artifact = payload["seasonalArtifact"]
    + 903        seasonal_artifact = season.CharacterScopedArtifact(
    + 904            hash=artifact["artifactHash"],
    + 905            points_used=artifact["pointsUsed"],
    + 906            reset_count=artifact["resetCount"],
    + 907            tiers=[
    + 908                self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"]
    + 909            ],
    + 910        )
    + 911        checklists = payload["checklists"]
    + 912
    + 913        return character.CharacterProgression(
    + 914            progressions=progressions_,
    + 915            factions=factions,
    + 916            checklists=checklists,
    + 917            milestones=milestones_,
    + 918            seasonal_artifact=seasonal_artifact,
    + 919            uninstanced_item_objectives=uninstanced_item_objectives,
    + 920        )
    + 921
    + 922    def deserialize_character_progressions_mapping(
    + 923        self, payload: typedefs.JSONObject
    + 924    ) -> collections.Mapping[int, character.CharacterProgression]:
    + 925        character_progressions: collections.Mapping[
    + 926            int, character.CharacterProgression
    + 927        ] = {}
    + 928        for char_id, data in payload["data"].items():
    + 929            # A little hack to stop mypy complaining about Mapping <-> dict
    + 930            character_progressions[int(char_id)] = self.deserialize_character_progressions(data)  # type: ignore[index]
    + 931        return character_progressions
    + 932
    + 933    def deserialize_characters_records(
    + 934        self,
    + 935        payload: typedefs.JSONObject,
    + 936    ) -> collections.Mapping[int, records.CharacterRecord]:
    + 937
    + 938        return {
    + 939            int(rec_id): self.deserialize_character_records(
    + 940                rec, record_hashes=payload.get("featuredRecordHashes")
    + 941            )
    + 942            for rec_id, rec in payload["records"].items()
    + 943        }
    + 944
    + 945    def deserialize_profile_records(
    + 946        self, payload: typedefs.JSONObject
    + 947    ) -> collections.Mapping[int, records.Record]:
    + 948        raw_profile_records = payload["data"]
    + 949        scores = records.RecordScores(
    + 950            current_score=raw_profile_records["score"],
    + 951            legacy_score=raw_profile_records["legacyScore"],
    + 952            lifetime_score=raw_profile_records["lifetimeScore"],
    + 953        )
    + 954        return {
    + 955            int(record_id): self.deserialize_records(
    + 956                record,
    + 957                scores,
    + 958                categories_hash=raw_profile_records["recordCategoriesRootNodeHash"],
    + 959                seals_hash=raw_profile_records["recordSealsRootNodeHash"],
    + 960            )
    + 961            for record_id, record in raw_profile_records["records"].items()
    + 962        }
    + 963
    + 964    def _deserialize_craftable_socket_plug(
    + 965        self, payload: typedefs.JSONObject
    + 966    ) -> items.CraftableSocketPlug:
    + 967        return items.CraftableSocketPlug(
    + 968            item_hash=int(payload["plugItemHash"]),
    + 969            failed_requirement_indexes=payload.get("failedRequirementIndexes", []),
    + 970        )
    + 971
    + 972    def _deserialize_craftable_socket(
    + 973        self, payload: typedefs.JSONObject
    + 974    ) -> items.CraftableSocket:
    + 975
    + 976        plugs: list[items.CraftableSocketPlug] = []
    + 977        if raw_plug := payload.get("plug"):
    + 978            plugs.extend(
    + 979                self._deserialize_craftable_socket_plug(plug) for plug in raw_plug
    + 980            )
    + 981
    + 982        return items.CraftableSocket(
    + 983            plug_set_hash=int(payload["plugSetHash"]), plugs=plugs
    + 984        )
    + 985
    + 986    def _deserialize_craftable_item(
    + 987        self, payload: typedefs.JSONObject
    + 988    ) -> items.CraftableItem:
    + 989
    + 990        return items.CraftableItem(
    + 991            is_visible=payload["visible"],
    + 992            failed_requirement_indexes=payload.get("failedRequirementIndexes", []),
    + 993            sockets=[
    + 994                self._deserialize_craftable_socket(socket)
    + 995                for socket in payload["sockets"]
    + 996            ],
    + 997        )
    + 998
    + 999    def deserialize_craftables_component(
    +1000        self, payload: typedefs.JSONObject
    +1001    ) -> components.CraftablesComponent:
    +1002        return components.CraftablesComponent(
    +1003            net=self._net,
    +1004            craftables={
    +1005                int(item_id): self._deserialize_craftable_item(item)
    +1006                for item_id, item in payload["craftables"].items()
    +1007                if item is not None
    +1008            },
    +1009            crafting_root_node_hash=payload["craftingRootNodeHash"],
    +1010        )
    +1011
    +1012    def deserialize_components(  # noqa: C901 Too complex.
    +1013        self, payload: typedefs.JSONObject
    +1014    ) -> components.Component:
    +1015
    +1016        profile_: typing.Optional[profile.Profile] = None
    +1017        if raw_profile := payload.get("profile"):
    +1018            profile_ = self.deserialize_profile(raw_profile)
    +1019
    +1020        profile_progression: typing.Optional[profile.ProfileProgression] = None
    +1021        if raw_profile_progression := payload.get("profileProgression"):
    +1022            profile_progression = self.deserialize_profile_progression(
    +1023                raw_profile_progression
    +1024            )
    +1025
    +1026        profile_currencies: typing.Optional[
    +1027            collections.Sequence[profile.ProfileItemImpl]
    +1028        ] = None
    +1029        if raw_profile_currencies := payload.get("profileCurrencies"):
    +1030            if "data" in raw_profile_currencies:
    +1031                profile_currencies = self.deserialize_profile_items(
    +1032                    raw_profile_currencies["data"]
    +1033                )
    +1034
    +1035        profile_inventories: typing.Optional[
    +1036            collections.Sequence[profile.ProfileItemImpl]
    +1037        ] = None
    +1038        if raw_profile_inventories := payload.get("profileInventory"):
    +1039            if "data" in raw_profile_inventories:
    +1040                profile_inventories = self.deserialize_profile_items(
    +1041                    raw_profile_inventories["data"]
    +1042                )
    +1043
    +1044        profile_records: typing.Optional[
    +1045            collections.Mapping[int, records.Record]
    +1046        ] = None
    +1047
    +1048        if raw_profile_records_ := payload.get("profileRecords"):
    +1049            profile_records = self.deserialize_profile_records(raw_profile_records_)
    +1050
    +1051        characters: typing.Optional[typing.Mapping[int, character.Character]] = None
    +1052        if raw_characters := payload.get("characters"):
    +1053            characters = self.deserialize_characters(raw_characters)
    +1054
    +1055        character_records: typing.Optional[
    +1056            collections.Mapping[int, records.CharacterRecord]
    +1057        ] = None
    +1058
    +1059        if raw_character_records := payload.get("characterRecords"):
    +1060            # Had to do it in two steps..
    +1061            to_update: typedefs.JSONObject = {}
    +1062            for _, data in raw_character_records["data"].items():
    +1063                for record_id, record in data.items():
    +1064                    to_update[record_id] = record
    +1065
    +1066            character_records = {
    +1067                int(rec_id): self.deserialize_character_records(
    +1068                    rec, record_hashes=to_update.get("featuredRecordHashes")
    +1069                )
    +1070                for rec_id, rec in to_update["records"].items()
    +1071            }
    +1072
    +1073        character_equipments: typing.Optional[
    +1074            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
    +1075        ] = None
    +1076        if raw_character_equips := payload.get("characterEquipment"):
    +1077            character_equipments = self.deserialize_character_equipments(
    +1078                raw_character_equips
    +1079            )
    +1080
    +1081        character_inventories: typing.Optional[
    +1082            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
    +1083        ] = None
    +1084        if raw_character_inventories := payload.get("characterInventories"):
    +1085            if "data" in raw_character_inventories:
    +1086                character_inventories = self.deserialize_character_equipments(
    +1087                    raw_character_inventories
    +1088                )
    +1089
    +1090        character_activities: typing.Optional[
    +1091            collections.Mapping[int, activity.CharacterActivity]
    +1092        ] = None
    +1093        if raw_char_acts := payload.get("characterActivities"):
    +1094            character_activities = self.deserialize_character_activities(raw_char_acts)
    +1095
    +1096        character_render_data: typing.Optional[
    +1097            collections.Mapping[int, character.RenderedData]
    +1098        ] = None
    +1099        if raw_character_render_data := payload.get("characterRenderData"):
    +1100            character_render_data = self.deserialize_characters_render_data(
    +1101                raw_character_render_data
    +1102            )
    +1103
    +1104        character_progressions: typing.Optional[
    +1105            collections.Mapping[int, character.CharacterProgression]
    +1106        ] = None
    +1107
    +1108        if raw_character_progressions := payload.get("characterProgressions"):
    +1109            character_progressions = self.deserialize_character_progressions_mapping(
    +1110                raw_character_progressions
    +1111            )
    +1112
    +1113        profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None
    +1114        if raw_profile_string_vars := payload.get("profileStringVariables"):
    +1115            profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"]
    +1116
    +1117        character_string_vars: typing.Optional[
    +1118            collections.Mapping[int, collections.Mapping[int, int]]
    +1119        ] = None
    +1120        if raw_character_string_vars := payload.get("characterStringVariables"):
    +1121            character_string_vars = {
    +1122                int(char_id): data["integerValuesByHash"]
    +1123                for char_id, data in raw_character_string_vars["data"].items()
    +1124            }
    +1125
    +1126        metrics: typing.Optional[
    +1127            collections.Sequence[
    +1128                collections.Mapping[
    +1129                    int, tuple[bool, typing.Optional[records.Objective]]
    +1130                ]
    +1131            ]
    +1132        ] = None
    +1133        root_node_hash: typing.Optional[int] = None
    +1134
    +1135        if raw_metrics := payload.get("metrics"):
    +1136            root_node_hash = raw_metrics["data"]["metricsRootNodeHash"]
    +1137            metrics = [
    +1138                {
    +1139                    int(metrics_hash): (
    +1140                        data["invisible"],
    +1141                        self.deserialize_objectives(data["objectiveProgress"])
    +1142                        if "objectiveProgress" in data
    +1143                        else None,
    +1144                    )
    +1145                    for metrics_hash, data in raw_metrics["data"]["metrics"].items()
    +1146                }
    +1147            ]
    +1148        transitory: typing.Optional[fireteams.FireteamParty] = None
    +1149        if raw_transitory := payload.get("profileTransitoryData"):
    +1150            if "data" in raw_transitory:
    +1151                transitory = self.deserialize_fireteam_party(raw_transitory["data"])
    +1152
    +1153        item_components: typing.Optional[components.ItemsComponent] = None
    +1154        if raw_item_components := payload.get("itemComponents"):
    +1155            item_components = self.deserialize_items_component(raw_item_components)
    +1156
    +1157        profile_plugsets: typing.Optional[
    +1158            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    +1159        ] = None
    +1160
    +1161        if raw_profile_plugs := payload.get("profilePlugSets"):
    +1162            profile_plugsets = {
    +1163                int(index): [self.deserialize_plug_item_state(state) for state in data]
    +1164                for index, data in raw_profile_plugs["data"]["plugs"].items()
    +1165            }
    +1166
    +1167        character_plugsets: typing.Optional[
    +1168            collections.Mapping[
    +1169                int, collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    +1170            ]
    +1171        ] = None
    +1172        if raw_char_plugsets := payload.get("characterPlugSets"):
    +1173            character_plugsets = {
    +1174                int(char_id): {
    +1175                    int(index): [
    +1176                        self.deserialize_plug_item_state(state) for state in data
    +1177                    ]
    +1178                    for index, data in inner["plugs"].items()
    +1179                }
    +1180                for char_id, inner in raw_char_plugsets["data"].items()
    +1181            }
    +1182
    +1183        character_collectibles: typing.Optional[
    +1184            collections.Mapping[int, items.Collectible]
    +1185        ] = None
    +1186        if raw_character_collectibles := payload.get("characterCollectibles"):
    +1187            character_collectibles = {
    +1188                int(char_id): self._deserialize_collectible(data)
    +1189                for char_id, data in raw_character_collectibles["data"].items()
    +1190            }
    +1191
    +1192        profile_collectibles: typing.Optional[items.Collectible] = None
    +1193        if raw_profile_collectibles := payload.get("profileCollectibles"):
    +1194            profile_collectibles = self._deserialize_collectible(
    +1195                raw_profile_collectibles["data"]
    +1196            )
    +1197
    +1198        profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
    +1199        if raw_profile_nodes := payload.get("profilePresentationNodes"):
    +1200            profile_nodes = {
    +1201                int(node_hash): self._deserialize_node(node)
    +1202                for node_hash, node in raw_profile_nodes["data"]["nodes"].items()
    +1203            }
    +1204
    +1205        character_nodes: typing.Optional[
    +1206            collections.Mapping[int, collections.Mapping[int, records.Node]]
    +1207        ] = None
    +1208        if raw_character_nodes := payload.get("characterPresentationNodes"):
    +1209            character_nodes = {
    +1210                int(char_id): {
    +1211                    int(node_hash): self._deserialize_node(node)
    +1212                    for node_hash, node in each_character["nodes"].items()
    +1213                }
    +1214                for char_id, each_character in raw_character_nodes["data"].items()
    +1215            }
    +1216
    +1217        platform_silver: typing.Optional[
    +1218            collections.Mapping[str, profile.ProfileItemImpl]
    +1219        ] = None
    +1220        if raw_platform_silver := payload.get("platformSilver"):
    +1221            if "data" in raw_platform_silver:
    +1222                platform_silver = {
    +1223                    platform_name: self.deserialize_profile_item(item)
    +1224                    for platform_name, item in raw_platform_silver["data"][
    +1225                        "platformSilver"
    +1226                    ].items()
    +1227                }
    +1228
    +1229        character_currency_lookups: typing.Optional[
    +1230            collections.Mapping[int, collections.Sequence[items.Currency]]
    +1231        ] = None
    +1232        if raw_char_lookups := payload.get("characterCurrencyLookups"):
    +1233            if "data" in raw_char_lookups:
    +1234                character_currency_lookups = {
    +1235                    int(char_id): self._deserialize_currencies(currencie)
    +1236                    for char_id, currencie in raw_char_lookups["data"].items()
    +1237                }
    +1238
    +1239        character_craftables: typing.Optional[
    +1240            collections.Mapping[int, components.CraftablesComponent]
    +1241        ] = None
    +1242        if raw_character_craftables := payload.get("characterCraftables"):
    +1243
    +1244            if "data" in raw_character_craftables:
    +1245                character_craftables = {
    +1246                    int(char_id): self.deserialize_craftables_component(craftable)
    +1247                    for char_id, craftable in raw_character_craftables["data"].items()
    +1248                }
    +1249
    +1250        return components.Component(
    +1251            profiles=profile_,
    +1252            profile_progression=profile_progression,
    +1253            profile_currencies=profile_currencies,
    +1254            profile_inventories=profile_inventories,
    +1255            profile_records=profile_records,
    +1256            characters=characters,
    +1257            character_records=character_records,
    +1258            character_equipments=character_equipments,
    +1259            character_inventories=character_inventories,
    +1260            character_activities=character_activities,
    +1261            character_render_data=character_render_data,
    +1262            character_progressions=character_progressions,
    +1263            profile_string_variables=profile_string_vars,
    +1264            character_string_variables=character_string_vars,
    +1265            metrics=metrics,
    +1266            root_node_hash=root_node_hash,
    +1267            transitory=transitory,
    +1268            item_components=item_components,
    +1269            profile_plugsets=profile_plugsets,
    +1270            character_plugsets=character_plugsets,
    +1271            character_collectibles=character_collectibles,
    +1272            profile_collectibles=profile_collectibles,
    +1273            profile_nodes=profile_nodes,
    +1274            character_nodes=character_nodes,
    +1275            platform_silver=platform_silver,
    +1276            character_currency_lookups=character_currency_lookups,
    +1277            character_craftables=character_craftables,
    +1278        )
    +1279
    +1280    def deserialize_items_component(
    +1281        self, payload: typedefs.JSONObject
    +1282    ) -> components.ItemsComponent:
    +1283        instances: typing.Optional[
    +1284            collections.Sequence[collections.Mapping[int, items.ItemInstance]]
    +1285        ] = None
    +1286        if raw_instances := payload.get("instances"):
    +1287            instances = [
    +1288                {
    +1289                    int(ins_id): self.deserialize_instanced_item(item)
    +1290                    for ins_id, item in raw_instances["data"].items()
    +1291                }
    +1292            ]
    +1293
    +1294        render_data: typing.Optional[
    +1295            collections.Mapping[int, tuple[bool, dict[int, int]]]
    +1296        ] = None
    +1297        if raw_render_data := payload.get("renderData"):
    +1298            render_data = {
    +1299                int(ins_id): (data["useCustomDyes"], data["artRegions"])
    +1300                for ins_id, data in raw_render_data["data"].items()
    +1301            }
    +1302
    +1303        stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None
    +1304        if raw_stats := payload.get("stats"):
    +1305            builder: collections.Mapping[int, items.ItemStatsView] = {}
    +1306            for ins_id, stat in raw_stats["data"].items():
    +1307                for _, items_ in stat.items():
    +1308                    builder[int(ins_id)] = self.deserialize_item_stats_view(items_)  # type: ignore[index]
    +1309            stats = builder
    +1310
    +1311        sockets: typing.Optional[
    +1312            collections.Mapping[int, collections.Sequence[items.ItemSocket]]
    +1313        ] = None
    +1314        if raw_sockets := payload.get("sockets"):
    +1315            sockets = {
    +1316                int(ins_id): [
    +1317                    self.deserialize_item_socket(socket) for socket in item["sockets"]
    +1318                ]
    +1319                for ins_id, item in raw_sockets["data"].items()
    +1320            }
    +1321
    +1322        objeectives: typing.Optional[
    +1323            collections.Mapping[int, collections.Sequence[records.Objective]]
    +1324        ] = None
    +1325        if raw_objectives := payload.get("objectives"):
    +1326            objeectives = {
    +1327                int(ins_id): [self.deserialize_objectives(objective)]
    +1328                for ins_id, data in raw_objectives["data"].items()
    +1329                for objective in data["objectives"]
    +1330            }
    +1331
    +1332        perks: typing.Optional[
    +1333            collections.Mapping[int, collections.Collection[items.ItemPerk]]
    +1334        ] = None
    +1335        if raw_perks := payload.get("perks"):
    +1336            perks = {
    +1337                int(ins_id): [
    +1338                    self.deserialize_item_perk(perk) for perk in item["perks"]
    +1339                ]
    +1340                for ins_id, item in raw_perks["data"].items()
    +1341            }
    +1342
    +1343        plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None
    +1344        if raw_plug_states := payload.get("plugStates"):
    +1345            pending_states: list[items.PlugItemState] = []
    +1346            for _, plug in raw_plug_states["data"].items():
    +1347                pending_states.append(self.deserialize_plug_item_state(plug))
    +1348            plug_states = pending_states
    +1349
    +1350        reusable_plugs: typing.Optional[
    +1351            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    +1352        ] = None
    +1353        if raw_re_plugs := payload.get("reusablePlugs"):
    +1354            reusable_plugs = {
    +1355                int(ins_id): [
    +1356                    self.deserialize_plug_item_state(state) for state in inner
    +1357                ]
    +1358                for ins_id, plug in raw_re_plugs["data"].items()
    +1359                for inner in list(plug["plugs"].values())
    +1360            }
    +1361
    +1362        plug_objectives: typing.Optional[
    +1363            collections.Mapping[
    +1364                int, collections.Mapping[int, collections.Collection[records.Objective]]
    +1365            ]
    +1366        ] = None
    +1367        if raw_plug_objectives := payload.get("plugObjectives"):
    +1368            plug_objectives = {
    +1369                int(ins_id): {
    +1370                    int(obj_hash): [self.deserialize_objectives(obj) for obj in objs]
    +1371                    for obj_hash, objs in inner["objectivesPerPlug"].items()
    +1372                }
    +1373                for ins_id, inner in raw_plug_objectives["data"].items()
    +1374            }
    +1375
    +1376        return components.ItemsComponent(
    +1377            sockets=sockets,
    +1378            stats=stats,
    +1379            render_data=render_data,
    +1380            instances=instances,
    +1381            objectives=objeectives,
    +1382            perks=perks,
    +1383            plug_states=plug_states,
    +1384            reusable_plugs=reusable_plugs,
    +1385            plug_objectives=plug_objectives,
    +1386        )
    +1387
    +1388    def deserialize_character_component(  # type: ignore[call-arg]
    +1389        self, payload: typedefs.JSONObject
    +1390    ) -> components.CharacterComponent:
    +1391
    +1392        character_: typing.Optional[character.Character] = None
    +1393        if raw_singuler_character := payload.get("character"):
    +1394            character_ = self.deserialize_character(raw_singuler_character["data"])
    +1395
    +1396        inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
    +1397        if raw_inventory := payload.get("inventory"):
    +1398            if "data" in raw_inventory:
    +1399                inventory = self.deserialize_profile_items(raw_inventory["data"])
    +1400
    +1401        activities: typing.Optional[activity.CharacterActivity] = None
    +1402        if raw_activities := payload.get("activities"):
    +1403            activities = self.deserialize_character_activity(raw_activities["data"])
    +1404
    +1405        equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
    +1406        if raw_equipments := payload.get("equipment"):
    +1407            equipment = self.deserialize_profile_items(raw_equipments["data"])
    +1408
    +1409        progressions_: typing.Optional[character.CharacterProgression] = None
    +1410        if raw_progressions := payload.get("progressions"):
    +1411            progressions_ = self.deserialize_character_progressions(
    +1412                raw_progressions["data"]
    +1413            )
    +1414
    +1415        render_data: typing.Optional[character.RenderedData] = None
    +1416        if raw_render_data := payload.get("renderData"):
    +1417            render_data = self.deserialize_character_render_data(
    +1418                raw_render_data["data"]
    +1419            )
    +1420
    +1421        character_records: typing.Optional[
    +1422            collections.Mapping[int, records.CharacterRecord]
    +1423        ] = None
    +1424        if raw_char_records := payload.get("records"):
    +1425            character_records = self.deserialize_characters_records(
    +1426                raw_char_records["data"]
    +1427            )
    +1428
    +1429        item_components: typing.Optional[components.ItemsComponent] = None
    +1430        if raw_item_components := payload.get("itemComponents"):
    +1431            item_components = self.deserialize_items_component(raw_item_components)
    +1432
    +1433        nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
    +1434        if raw_nodes := payload.get("presentationNodes"):
    +1435            nodes = {
    +1436                int(node_hash): self._deserialize_node(node)
    +1437                for node_hash, node in raw_nodes["data"]["nodes"].items()
    +1438            }
    +1439
    +1440        collectibles: typing.Optional[items.Collectible] = None
    +1441        if raw_collectibles := payload.get("collectibles"):
    +1442            collectibles = self._deserialize_collectible(raw_collectibles["data"])
    +1443
    +1444        currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None
    +1445        if raw_currencies := payload.get("currencyLookups"):
    +1446            if "data" in raw_currencies:
    +1447                currency_lookups = self._deserialize_currencies(raw_currencies)
    +1448
    +1449        return components.CharacterComponent(
    +1450            activities=activities,
    +1451            equipment=equipment,
    +1452            inventory=inventory,
    +1453            progressions=progressions_,
    +1454            render_data=render_data,
    +1455            character=character_,
    +1456            character_records=character_records,
    +1457            profile_records=None,
    +1458            item_components=item_components,
    +1459            currency_lookups=currency_lookups,
    +1460            collectibles=collectibles,
    +1461            nodes=nodes,
    +1462        )
    +1463
    +1464    def _set_entity_attrs(
    +1465        self, payload: typedefs.JSONObject, *, key: str = "displayProperties"
    +1466    ) -> entity.Entity:
    +1467
    +1468        name: undefined.UndefinedOr[str] = undefined.Undefined
    +1469        description: undefined.UndefinedOr[str] = undefined.Undefined
    +1470
    +1471        if properties := payload[key]:
    +1472            if (raw_name := properties["name"]) is not typedefs.Unknown:
    +1473                name = raw_name
    +1474
    +1475            if (
    +1476                raw_description := properties["description"]
    +1477            ) and not typedefs.is_unknown(raw_description):
    +1478                description = raw_description
    +1479
    +1480        return entity.Entity(
    +1481            net=self._net,
    +1482            hash=payload["hash"],
    +1483            index=payload["index"],
    +1484            name=name,
    +1485            description=description,
    +1486            has_icon=properties["hasIcon"],
    +1487            icon=assets.Image(properties["icon"] if "icon" in properties else None),
    +1488        )
    +1489
    +1490    def deserialize_inventory_results(
    +1491        self, payload: typedefs.JSONObject
    +1492    ) -> iterators.Iterator[entity.SearchableEntity]:
    +1493        suggested_words: list[str] = payload["suggestedWords"]
    +1494
    +1495        def _check_unknown(s: str) -> undefined.UndefinedOr[str]:
    +1496            return s if not typedefs.is_unknown(s) else undefined.Undefined
    +1497
    +1498        return iterators.Iterator(
    +1499            [
    +1500                entity.SearchableEntity(
    +1501                    net=self._net,
    +1502                    hash=data["hash"],
    +1503                    entity_type=data["entityType"],
    +1504                    weight=data["weight"],
    +1505                    suggested_words=suggested_words,
    +1506                    name=data["displayProperties"]["name"],
    +1507                    has_icon=data["displayProperties"]["hasIcon"],
    +1508                    description=_check_unknown(
    +1509                        data["displayProperties"]["description"]
    +1510                    ),
    +1511                    icon=assets.Image(data["displayProperties"]["icon"]),
    +1512                )
    +1513                for data in payload["results"]["results"]
    +1514            ]
    +1515        )
    +1516
    +1517    def _deserialize_inventory_item_objects(
    +1518        self, payload: typedefs.JSONObject
    +1519    ) -> entity.InventoryEntityObjects:
    +1520        return entity.InventoryEntityObjects(
    +1521            action=payload.get("action"),
    +1522            set_data=payload.get("setData"),
    +1523            stats=payload.get("stats"),
    +1524            equipping_block=payload.get("equippingBlock"),
    +1525            translation_block=payload.get("translationBlock"),
    +1526            preview=payload.get("preview"),
    +1527            quality=payload.get("quality"),
    +1528            value=payload.get("value"),
    +1529            source_data=payload.get("sourceData"),
    +1530            objectives=payload.get("objectives"),
    +1531            plug=payload.get("plug"),
    +1532            metrics=payload.get("metrics"),
    +1533            gearset=payload.get("gearset"),
    +1534            sack=payload.get("sack"),
    +1535            sockets=payload.get("sockets"),
    +1536            summary=payload.get("summary"),
    +1537            talent_gird=payload.get("talentGrid"),
    +1538            investments_stats=payload.get("investmentStats"),
    +1539            perks=payload.get("perks"),
    +1540            animations=payload.get("animations", []),
    +1541            links=payload.get("links", []),
    +1542        )
    +1543
    +1544    def deserialize_inventory_entity(  # noqa: C901 Too complex.
    +1545        self, payload: typedefs.JSONObject, /
    +1546    ) -> entity.InventoryEntity:
    +1547
    +1548        props = self._set_entity_attrs(payload)
    +1549        objects = self._deserialize_inventory_item_objects(payload)
    +1550
    +1551        collectible_hash: typing.Optional[int] = None
    +1552        if raw_collectible_hash := payload.get("collectibleHash"):
    +1553            collectible_hash = int(raw_collectible_hash)
    +1554
    +1555        secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    +1556        if raw_second_icon := payload.get("secondaryIcon"):
    +1557            secondary_icon = assets.Image(raw_second_icon)
    +1558
    +1559        secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    +1560        if raw_second_overlay := payload.get("secondaryOverlay"):
    +1561            secondary_overlay = assets.Image(raw_second_overlay)
    +1562
    +1563        secondary_special: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    +1564        if raw_second_special := payload.get("secondarySpecial"):
    +1565            secondary_special = assets.Image(raw_second_special)
    +1566
    +1567        screenshot: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    +1568        if raw_screenshot := payload.get("screenshot"):
    +1569            screenshot = assets.Image(raw_screenshot)
    +1570
    +1571        watermark_icon: typing.Optional[assets.Image] = None
    +1572        if raw_watermark_icon := payload.get("iconWatermark"):
    +1573            watermark_icon = assets.Image(raw_watermark_icon)
    +1574
    +1575        watermark_shelved: typing.Optional[assets.Image] = None
    +1576        if raw_watermark_shelved := payload.get("iconWatermarkShelved"):
    +1577            watermark_shelved = assets.Image(raw_watermark_shelved)
    +1578
    +1579        about: undefined.UndefinedOr[str] = undefined.Undefined
    +1580        if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown(
    +1581            raw_about
    +1582        ):
    +1583            about = raw_about
    +1584
    +1585        ui_item_style: undefined.UndefinedOr[str] = undefined.Undefined
    +1586        if (
    +1587            raw_ui_style := payload.get("uiItemDisplayStyle")
    +1588        ) and not typedefs.is_unknown(raw_ui_style):
    +1589            ui_item_style = raw_ui_style
    +1590
    +1591        tier_and_name: undefined.UndefinedOr[str] = undefined.Undefined
    +1592        if (
    +1593            raw_tier_and_name := payload.get("itemTypeAndTierDisplayName")
    +1594        ) and not typedefs.is_unknown(raw_tier_and_name):
    +1595            tier_and_name = raw_tier_and_name
    +1596
    +1597        type_name: undefined.UndefinedOr[str] = undefined.Undefined
    +1598        if (
    +1599            raw_type_name := payload.get("itemTypeDisplayName")
    +1600        ) and not typedefs.is_unknown(raw_type_name):
    +1601            type_name = raw_type_name
    +1602
    +1603        display_source: undefined.UndefinedOr[str] = undefined.Undefined
    +1604        if (
    +1605            raw_display_source := payload.get("displaySource")
    +1606        ) and not typedefs.is_unknown(raw_display_source):
    +1607            display_source = raw_display_source
    +1608
    +1609        lorehash: typing.Optional[int] = None
    +1610        if raw_lore_hash := payload.get("loreHash"):
    +1611            lorehash = int(raw_lore_hash)
    +1612
    +1613        summary_hash: typing.Optional[int] = None
    +1614        if raw_summary_hash := payload.get("summaryItemHash"):
    +1615            summary_hash = raw_summary_hash
    +1616
    +1617        breaker_type_hash: typing.Optional[int] = None
    +1618        if raw_breaker_type_hash := payload.get("breakerTypeHash"):
    +1619            breaker_type_hash = int(raw_breaker_type_hash)
    +1620
    +1621        damage_types: typing.Optional[collections.Sequence[int]] = None
    +1622        if raw_damage_types := payload.get("damageTypes"):
    +1623            damage_types = [int(type_) for type_ in raw_damage_types]
    +1624
    +1625        damagetype_hashes: typing.Optional[collections.Sequence[int]] = None
    +1626        if raw_damagetype_hashes := payload.get("damageTypeHashes"):
    +1627            damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes]
    +1628
    +1629        default_damagetype_hash: typing.Optional[int] = None
    +1630        if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"):
    +1631            default_damagetype_hash = int(raw_defaultdmg_hash)
    +1632
    +1633        emblem_objective_hash: typing.Optional[int] = None
    +1634        if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"):
    +1635            emblem_objective_hash = int(raw_emblem_obj_hash)
    +1636
    +1637        tier_type: typing.Optional[enums.TierType] = None
    +1638        tier: typing.Optional[enums.ItemTier] = None
    +1639        bucket_hash: typing.Optional[int] = None
    +1640        recovery_hash: typing.Optional[int] = None
    +1641        tier_name: undefined.UndefinedOr[str] = undefined.Undefined
    +1642        isinstance_item: bool = False
    +1643        expire_tool_tip: undefined.UndefinedOr[str] = undefined.Undefined
    +1644        expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.Undefined
    +1645        suppress_expiration: bool = False
    +1646        max_stack_size: typing.Optional[int] = None
    +1647        stack_label: undefined.UndefinedOr[str] = undefined.Undefined
    +1648
    +1649        if inventory := payload.get("inventory"):
    +1650            tier_type = enums.TierType(int(inventory["tierType"]))
    +1651            tier = enums.ItemTier(int(inventory["tierTypeHash"]))
    +1652            bucket_hash = int(inventory["bucketTypeHash"])
    +1653            recovery_hash = int(inventory["recoveryBucketTypeHash"])
    +1654            tier_name = inventory["tierTypeName"]
    +1655            isinstance_item = inventory["isInstanceItem"]
    +1656            suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"]
    +1657            max_stack_size = int(inventory["maxStackSize"])
    +1658
    +1659            try:
    +1660                stack_label = inventory["stackUniqueLabel"]
    +1661            except KeyError:
    +1662                pass
    +1663
    +1664        return entity.InventoryEntity(
    +1665            net=self._net,
    +1666            collectible_hash=collectible_hash,
    +1667            name=props.name,
    +1668            about=about,
    +1669            emblem_objective_hash=emblem_objective_hash,
    +1670            suppress_expiration=suppress_expiration,
    +1671            max_stack_size=max_stack_size,
    +1672            stack_label=stack_label,
    +1673            tier=tier,
    +1674            tier_type=tier_type,
    +1675            tier_name=tier_name,
    +1676            bucket_hash=bucket_hash,
    +1677            recovery_bucket_hash=recovery_hash,
    +1678            isinstance_item=isinstance_item,
    +1679            expire_in_orbit_message=expire_in_orbit_message,
    +1680            expiration_tooltip=expire_tool_tip,
    +1681            lore_hash=lorehash,
    +1682            type_and_tier_name=tier_and_name,
    +1683            summary_hash=summary_hash,
    +1684            ui_display_style=ui_item_style,
    +1685            type_name=type_name,
    +1686            breaker_type_hash=breaker_type_hash,
    +1687            description=props.description,
    +1688            display_source=display_source,
    +1689            hash=props.hash,
    +1690            damage_types=damage_types,
    +1691            index=props.index,
    +1692            icon=props.icon,
    +1693            has_icon=props.has_icon,
    +1694            screenshot=screenshot,
    +1695            watermark_icon=watermark_icon,
    +1696            watermark_shelved=watermark_shelved,
    +1697            secondary_icon=secondary_icon,
    +1698            secondary_overlay=secondary_overlay,
    +1699            secondary_special=secondary_special,
    +1700            type=enums.ItemType(int(payload["itemType"])),
    +1701            trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])],
    +1702            trait_ids=[trait for trait in payload.get("traitIds", [])],
    +1703            category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]],
    +1704            item_class=enums.Class(int(payload["classType"])),
    +1705            sub_type=enums.ItemSubType(int(payload["itemSubType"])),
    +1706            breaker_type=int(payload["breakerType"]),
    +1707            default_damagetype=int(payload["defaultDamageType"]),
    +1708            default_damagetype_hash=default_damagetype_hash,
    +1709            damagetype_hashes=damagetype_hashes,
    +1710            tooltip_notifications=payload["tooltipNotifications"],
    +1711            not_transferable=payload["nonTransferrable"],
    +1712            allow_actions=payload["allowActions"],
    +1713            is_equippable=payload["equippable"],
    +1714            objects=objects,
    +1715            background_colors=payload.get("backgroundColor", {}),
    +1716            season_hash=payload.get("seasonHash"),
    +1717            has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"],
    +1718        )
    +1719
    +1720    def deserialize_objective_entity(
    +1721        self, payload: typedefs.JSONObject, /
    +1722    ) -> entity.ObjectiveEntity:
    +1723        props = self._set_entity_attrs(payload)
    +1724        return entity.ObjectiveEntity(
    +1725            net=self._net,
    +1726            hash=props.hash,
    +1727            index=props.index,
    +1728            description=props.description,
    +1729            name=props.name,
    +1730            has_icon=props.has_icon,
    +1731            icon=props.icon,
    +1732            unlock_value_hash=payload["unlockValueHash"],
    +1733            completion_value=payload["completionValue"],
    +1734            scope=entity.GatingScope(int(payload["scope"])),
    +1735            location_hash=payload["locationHash"],
    +1736            allowed_negative_value=payload["allowNegativeValue"],
    +1737            allowed_value_change=payload["allowValueChangeWhenCompleted"],
    +1738            counting_downward=payload["isCountingDownward"],
    +1739            value_style=entity.ValueUIStyle(int(payload["valueStyle"])),
    +1740            progress_description=payload["progressDescription"],
    +1741            perks=payload["perks"],
    +1742            stats=payload["stats"],
    +1743            minimum_visibility=payload["minimumVisibilityThreshold"],
    +1744            allow_over_completion=payload["allowOvercompletion"],
    +1745            show_value_style=payload["showValueOnComplete"],
    +1746            display_only_objective=payload["isDisplayOnlyObjective"],
    +1747            complete_value_style=entity.ValueUIStyle(
    +1748                int(payload["completedValueStyle"])
    +1749            ),
    +1750            progress_value_style=entity.ValueUIStyle(
    +1751                int(payload["inProgressValueStyle"])
    +1752            ),
    +1753            ui_label=payload["uiLabel"],
    +1754            ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])),
    +1755        )
    +1756
    +1757    def _deserialize_activity_values(
    +1758        self, payload: typedefs.JSONObject, /
    +1759    ) -> activity.ActivityValues:
    +1760        team: typing.Optional[int] = None
    +1761        if raw_team := payload.get("team"):
    +1762            team = raw_team["basic"]["value"]
    +1763        return activity.ActivityValues(
    +1764            assists=payload["assists"]["basic"]["value"],
    +1765            deaths=payload["deaths"]["basic"]["value"],
    +1766            kills=payload["kills"]["basic"]["value"],
    +1767            is_completed=bool(payload["completed"]["basic"]["value"]),
    +1768            opponents_defeated=payload["opponentsDefeated"]["basic"]["value"],
    +1769            efficiency=payload["efficiency"]["basic"]["value"],
    +1770            kd_ratio=payload["killsDeathsRatio"]["basic"]["value"],
    +1771            kd_assists=payload["killsDeathsAssists"]["basic"]["value"],
    +1772            score=payload["score"]["basic"]["value"],
    +1773            duration=payload["activityDurationSeconds"]["basic"]["displayValue"],
    +1774            team=team,
    +1775            completion_reason=payload["completionReason"]["basic"]["displayValue"],
    +1776            fireteam_id=payload["fireteamId"]["basic"]["value"],
    +1777            start_seconds=payload["startSeconds"]["basic"]["value"],
    +1778            played_time=payload["timePlayedSeconds"]["basic"]["displayValue"],
    +1779            player_count=payload["playerCount"]["basic"]["value"],
    +1780            team_score=payload["teamScore"]["basic"]["value"],
    +1781        )
    +1782
    +1783    def deserialize_activity(
    +1784        self,
    +1785        payload: typedefs.JSONObject,
    +1786        /,
    +1787    ) -> activity.Activity:
    +1788        period = time.clean_date(payload["period"])
    +1789        details = payload["activityDetails"]
    +1790        ref_id = int(details["referenceId"])
    +1791        instance_id = int(details["instanceId"])
    +1792        mode = enums.GameMode(details["mode"])
    +1793        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
    +1794        is_private = details["isPrivate"]
    +1795        membership_type = enums.MembershipType(int(details["membershipType"]))
    +1796
    +1797        # Since we're using the same fields for post activity method
    +1798        # this check is required since post activity doesn't values values
    +1799        values = self._deserialize_activity_values(payload["values"])
    +1800
    +1801        return activity.Activity(
    +1802            net=self._net,
    +1803            hash=ref_id,
    +1804            instance_id=instance_id,
    +1805            mode=mode,
    +1806            modes=modes,
    +1807            is_private=is_private,
    +1808            membership_type=membership_type,
    +1809            occurred_at=period,
    +1810            values=values,
    +1811        )
    +1812
    +1813    def deserialize_activities(
    +1814        self, payload: typedefs.JSONObject
    +1815    ) -> iterators.Iterator[activity.Activity]:
    +1816        return iterators.Iterator(
    +1817            [
    +1818                self.deserialize_activity(activity_)
    +1819                for activity_ in payload["activities"]
    +1820            ]
    +1821        )
    +1822
    +1823    def deserialize_extended_weapon_values(
    +1824        self, payload: typedefs.JSONObject
    +1825    ) -> activity.ExtendedWeaponValues:
    +1826
    +1827        assists: typing.Optional[int] = None
    +1828        if raw_assists := payload["values"].get("uniqueWeaponAssists"):
    +1829            assists = raw_assists["basic"]["value"]
    +1830        assists_damage: typing.Optional[int] = None
    +1831
    +1832        if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"):
    +1833            assists_damage = raw_assists_damage["basic"]["value"]
    +1834
    +1835        return activity.ExtendedWeaponValues(
    +1836            reference_id=int(payload["referenceId"]),
    +1837            kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"],
    +1838            precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][
    +1839                "value"
    +1840            ],
    +1841            assists=assists,
    +1842            assists_damage=assists_damage,
    +1843            precision_kills_percentage=(
    +1844                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"],
    +1845                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][
    +1846                    "displayValue"
    +1847                ],
    +1848            ),
    +1849        )
    +1850
    +1851    def _deserialize_extended_values(
    +1852        self, payload: typedefs.JSONObject
    +1853    ) -> activity.ExtendedValues:
    +1854        weapons: typing.Optional[
    +1855            collections.Collection[activity.ExtendedWeaponValues]
    +1856        ] = None
    +1857
    +1858        if raw_weapons := payload.get("weapons"):
    +1859            weapons = [
    +1860                self.deserialize_extended_weapon_values(value) for value in raw_weapons
    +1861            ]
    +1862
    +1863        return activity.ExtendedValues(
    +1864            precision_kills=payload["values"]["precisionKills"]["basic"]["value"],
    +1865            grenade_kills=payload["values"]["weaponKillsGrenade"]["basic"]["value"],
    +1866            melee_kills=payload["values"]["weaponKillsMelee"]["basic"]["value"],
    +1867            super_kills=payload["values"]["weaponKillsSuper"]["basic"]["value"],
    +1868            ability_kills=payload["values"]["weaponKillsAbility"]["basic"]["value"],
    +1869            weapons=weapons,
    +1870        )
    +1871
    +1872    def deserialize_post_activity_player(
    +1873        self, payload: typedefs.JSONObject, /
    +1874    ) -> activity.PostActivityPlayer:
    +1875        player = payload["player"]
    +1876
    +1877        class_hash: typedefs.NoneOr[int] = None
    +1878        if (class_hash := player.get("classHash")) is not None:
    +1879            class_hash = class_hash
    +1880
    +1881        race_hash: typedefs.NoneOr[int] = None
    +1882        if (race_hash := player.get("raceHash")) is not None:
    +1883            race_hash = race_hash
    +1884
    +1885        gender_hash: typedefs.NoneOr[int] = None
    +1886        if (gender_hash := player.get("genderHash")) is not None:
    +1887            gender_hash = gender_hash
    +1888
    +1889        character_class: undefined.UndefinedOr[str] = undefined.Undefined
    +1890        if (
    +1891            character_class := player.get("characterClass")
    +1892        ) and not typedefs.is_unknown(character_class):
    +1893            character_class = character_class
    +1894
    +1895        character_level: typedefs.NoneOr[int] = None
    +1896        if (character_level := player.get("characterLevel")) is not None:
    +1897            character_level = character_level
    +1898
    +1899        return activity.PostActivityPlayer(
    +1900            standing=int(payload["standing"]),
    +1901            score=int(payload["score"]["basic"]["value"]),
    +1902            character_id=payload["characterId"],
    +1903            destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]),
    +1904            character_class=character_class,
    +1905            character_level=character_level,
    +1906            race_hash=race_hash,
    +1907            gender_hash=gender_hash,
    +1908            class_hash=class_hash,
    +1909            light_level=int(player["lightLevel"]),
    +1910            emblem_hash=int(player["emblemHash"]),
    +1911            values=self._deserialize_activity_values(payload["values"]),
    +1912            extended_values=self._deserialize_extended_values(payload["extended"]),
    +1913        )
    +1914
    +1915    def _deserialize_post_activity_team(
    +1916        self, payload: typedefs.JSONObject
    +1917    ) -> activity.PostActivityTeam:
    +1918        return activity.PostActivityTeam(
    +1919            id=payload["teamId"],
    +1920            is_defeated=bool(payload["standing"]["basic"]["value"]),
    +1921            score=int(payload["score"]["basic"]["value"]),
    +1922            name=payload["teamName"],
    +1923        )
    +1924
    +1925    def deserialize_post_activity(
    +1926        self, payload: typedefs.JSONObject
    +1927    ) -> activity.PostActivity:
    +1928        period = time.clean_date(payload["period"])
    +1929        details = payload["activityDetails"]
    +1930        ref_id = int(details["referenceId"])
    +1931        instance_id = int(details["instanceId"])
    +1932        mode = enums.GameMode(details["mode"])
    +1933        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
    +1934        is_private = details["isPrivate"]
    +1935        membership_type = enums.MembershipType(int(details["membershipType"]))
    +1936        return activity.PostActivity(
    +1937            net=self._net,
    +1938            hash=ref_id,
    +1939            membership_type=membership_type,
    +1940            instance_id=instance_id,
    +1941            mode=mode,
    +1942            modes=modes,
    +1943            is_private=is_private,
    +1944            occurred_at=period,
    +1945            starting_phase=int(payload["startingPhaseIndex"]),
    +1946            players=[
    +1947                self.deserialize_post_activity_player(player)
    +1948                for player in payload["entries"]
    +1949            ],
    +1950            teams=[
    +1951                self._deserialize_post_activity_team(team) for team in payload["teams"]
    +1952            ],
    +1953        )
    +1954
    +1955    def _deserialize_aggregated_activity_values(
    +1956        self, payload: typedefs.JSONObject
    +1957    ) -> activity.AggregatedActivityValues:
    +1958        # This ID is always the same for all aggregated values.
    +1959        activity_id = int(payload["fastestCompletionMsForActivity"]["activityId"])
    +1960
    +1961        return activity.AggregatedActivityValues(
    +1962            id=activity_id,
    +1963            fastest_completion_time=(
    +1964                int(payload["fastestCompletionMsForActivity"]["basic"]["value"]),
    +1965                payload["fastestCompletionMsForActivity"]["basic"]["displayValue"],
    +1966            ),
    +1967            completions=int(payload["activityCompletions"]["basic"]["value"]),
    +1968            kills=int(payload["activityKills"]["basic"]["value"]),
    +1969            deaths=int(payload["activityDeaths"]["basic"]["value"]),
    +1970            assists=int(payload["activityAssists"]["basic"]["value"]),
    +1971            seconds_played=(
    +1972                int(payload["activitySecondsPlayed"]["basic"]["value"]),
    +1973                payload["activitySecondsPlayed"]["basic"]["displayValue"],
    +1974            ),
    +1975            wins=int(payload["activityWins"]["basic"]["value"]),
    +1976            goals_missed=int(payload["activityGoalsMissed"]["basic"]["value"]),
    +1977            special_actions=int(payload["activitySpecialActions"]["basic"]["value"]),
    +1978            best_goals_hit=int(payload["activityBestGoalsHit"]["basic"]["value"]),
    +1979            best_single_score=int(
    +1980                payload["activityBestSingleGameScore"]["basic"]["value"]
    +1981            ),
    +1982            goals_hit=int(payload["activityGoalsHit"]["basic"]["value"]),
    +1983            special_score=int(payload["activitySpecialScore"]["basic"]["value"]),
    +1984            kd_assists=int(payload["activityKillsDeathsAssists"]["basic"]["value"]),
    +1985            kd_ratio=float(
    +1986                payload["activityKillsDeathsAssists"]["basic"]["displayValue"]
    +1987            ),
    +1988            precision_kills=int(payload["activityPrecisionKills"]["basic"]["value"]),
    +1989        )
    +1990
    +1991    def deserialize_aggregated_activity(
    +1992        self, payload: typedefs.JSONObject
    +1993    ) -> activity.AggregatedActivity:
    +1994        return activity.AggregatedActivity(
    +1995            hash=int(payload["activityHash"]),
    +1996            values=self._deserialize_aggregated_activity_values(payload["values"]),
    +1997        )
    +1998
    +1999    def deserialize_aggregated_activities(
    +2000        self, payload: typedefs.JSONObject
    +2001    ) -> iterators.Iterator[activity.AggregatedActivity]:
    +2002        return iterators.Iterator(
    +2003            [
    +2004                self.deserialize_aggregated_activity(activity)
    +2005                for activity in payload["activities"]
    +2006            ]
    +2007        )
    +2008
    +2009    def deserialize_linked_profiles(
    +2010        self, payload: typedefs.JSONObject
    +2011    ) -> profile.LinkedProfile:
    +2012        bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"])
    +2013        error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
    +2014        profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
    +2015
    +2016        if raw_profile := payload.get("profiles"):
    +2017            for pfile in raw_profile:
    +2018                profiles_vec.append(self.deserialize_destiny_membership(pfile))
    +2019
    +2020        if raw_profiles_with_errors := payload.get("profilesWithErrors"):
    +2021            for raw_error_pfile in raw_profiles_with_errors:
    +2022                if error_pfile := raw_error_pfile.get("infoCard"):
    +2023                    error_profiles_vec.append(
    +2024                        self.deserialize_destiny_membership(error_pfile)
    +2025                    )
    +2026
    +2027        return profile.LinkedProfile(
    +2028            net=self._net,
    +2029            bungie=bungie_user,
    +2030            profiles=profiles_vec,
    +2031            profiles_with_errors=error_profiles_vec,
    +2032        )
    +2033
    +2034    def deserialize_clan_banners(
    +2035        self, payload: typedefs.JSONObject
    +2036    ) -> collections.Sequence[clans.ClanBanner]:
    +2037        banners_seq: typing.MutableSequence[clans.ClanBanner] = []
    +2038        if banners := payload.get("clanBannerDecals"):
    +2039            for k, v in banners.items():
    +2040                banner_obj = clans.ClanBanner(
    +2041                    id=int(k),
    +2042                    foreground=assets.Image(v["foregroundPath"]),
    +2043                    background=assets.Image(v["backgroundPath"]),
    +2044                )
    +2045                banners_seq.append(banner_obj)
    +2046        return banners_seq
    +2047
    +2048    def deserialize_public_milestone_content(
    +2049        self, payload: typedefs.JSONObject
    +2050    ) -> milestones.MilestoneContent:
    +2051        items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None
    +2052        if raw_categories := payload.get("itemCategories"):
    +2053            for item in raw_categories:
    +2054                title = undefined.Undefined
    +2055                if raw_title := item.get("title"):
    +2056                    if raw_title != typedefs.Unknown:
    +2057                        title = raw_title
    +2058                if raw_hashes := item.get("itemHashes"):
    +2059                    hashes: collections.Sequence[int] = raw_hashes
    +2060
    +2061                items_categoris = milestones.MilestoneItems(title=title, hashes=hashes)
    +2062
    +2063        about = undefined.Undefined
    +2064        if (raw_about := payload["about"]) != typedefs.Unknown:
    +2065            about = raw_about
    +2066
    +2067        status = undefined.Undefined
    +2068        if (raw_status := payload["status"]) != typedefs.Unknown:
    +2069            status = raw_status
    +2070
    +2071        tips: typing.MutableSequence[undefined.UndefinedOr[str]] = []
    +2072        if raw_tips := payload.get("tips"):
    +2073            for raw_tip in raw_tips:
    +2074                if raw_tip == typedefs.Unknown:
    +2075                    raw_tip = undefined.Undefined
    +2076                tips.append(raw_tip)
    +2077
    +2078        return milestones.MilestoneContent(
    +2079            about=about, status=status, tips=tips, items=items_categoris
    +2080        )
    +2081
    +2082    def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend:
    +2083        name = undefined.Undefined
    +2084        if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown:
    +2085            name = raw_name
    +2086
    +2087        bungie_user: typedefs.NoneOr[user.BungieUser] = None
    +2088
    +2089        if raw_bungie_user := payload.get("bungieNetUser"):
    +2090            bungie_user = self.deserialize_bungie_user(raw_bungie_user)
    +2091
    +2092        return friends.Friend(
    +2093            net=self._net,
    +2094            id=int(payload["lastSeenAsMembershipId"]),
    +2095            name=name,
    +2096            code=payload.get("bungieGlobalDisplayNameCode"),
    +2097            relationship=enums.Relationship(payload["relationship"]),
    +2098            user=bungie_user,
    +2099            online_status=enums.Presence(payload["onlineStatus"]),
    +2100            online_title=payload["onlineTitle"],
    +2101            type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]),
    +2102        )
    +2103
    +2104    def deserialize_friends(
    +2105        self, payload: typedefs.JSONObject
    +2106    ) -> collections.Sequence[friends.Friend]:
    +2107        mut_seq: typing.MutableSequence[friends.Friend] = []
    +2108        if raw_friends := payload.get("friends"):
    +2109            for friend in raw_friends:
    +2110                mut_seq.append(self.deserialize_friend(friend))
    +2111        return mut_seq
    +2112
    +2113    def deserialize_friend_requests(
    +2114        self, payload: typedefs.JSONObject
    +2115    ) -> friends.FriendRequestView:
    +2116        incoming: typing.MutableSequence[friends.Friend] = []
    +2117        outgoing: typing.MutableSequence[friends.Friend] = []
    +2118
    +2119        if raw_incoming_requests := payload.get("incomingRequests"):
    +2120            for incoming_request in raw_incoming_requests:
    +2121                incoming.append(self.deserialize_friend(incoming_request))
    +2122
    +2123        if raw_outgoing_requests := payload.get("outgoingRequests"):
    +2124            for outgoing_request in raw_outgoing_requests:
    +2125                outgoing.append(self.deserialize_friend(outgoing_request))
    +2126
    +2127        return friends.FriendRequestView(incoming=incoming, outgoing=outgoing)
    +2128
    +2129    def _set_fireteam_fields(
    +2130        self, payload: typedefs.JSONObject, total_results: typing.Optional[int] = None
    +2131    ) -> fireteams.Fireteam:
    +2132        activity_type = fireteams.FireteamActivity(payload["activityType"])
    +2133        return fireteams.Fireteam(
    +2134            id=int(payload["fireteamId"]),
    +2135            group_id=int(payload["groupId"]),
    +2136            platform=fireteams.FireteamPlatform(payload["platform"]),
    +2137            is_immediate=payload["isImmediate"],
    +2138            activity_type=activity_type,
    +2139            owner_id=int(payload["ownerMembershipId"]),
    +2140            player_slot_count=payload["playerSlotCount"],
    +2141            available_player_slots=payload["availablePlayerSlotCount"],
    +2142            available_alternate_slots=payload["availableAlternateSlotCount"],
    +2143            title=payload["title"],
    +2144            date_created=time.clean_date(payload["dateCreated"]),
    +2145            is_public=payload["isPublic"],
    +2146            locale=fireteams.FireteamLanguage(payload["locale"]),
    +2147            is_valid=payload["isValid"],
    +2148            last_modified=time.clean_date(payload["datePlayerModified"]),
    +2149            total_results=total_results or 0,
    +2150        )
    +2151
    +2152    def deserialize_fireteams(
    +2153        self, payload: typedefs.JSONObject
    +2154    ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]:
    +2155        fireteams_: typing.MutableSequence[fireteams.Fireteam] = []
    +2156
    +2157        result: list[typedefs.JSONObject]
    +2158        if not (result := payload["results"]):
    +2159            return None
    +2160        for elem in result:
    +2161            fireteams_.append(
    +2162                self._set_fireteam_fields(
    +2163                    elem, total_results=int(payload["totalResults"])
    +2164                )
    +2165            )
    +2166        return fireteams_
    +2167
    +2168    def deserialize_fireteam_destiny_users(
    +2169        self, payload: typedefs.JSONObject
    +2170    ) -> fireteams.FireteamUser:
    +2171        destiny_obj = self.deserialize_destiny_membership(payload)
    +2172        # We could helpers.just return a DestinyMembership object but this is
    +2173        # missing the fireteam display name and id fields.
    +2174        return fireteams.FireteamUser(
    +2175            net=self._net,
    +2176            id=destiny_obj.id,
    +2177            code=destiny_obj.code,
    +2178            icon=destiny_obj.icon,
    +2179            types=destiny_obj.types,
    +2180            type=destiny_obj.type,
    +2181            is_public=destiny_obj.is_public,
    +2182            crossave_override=destiny_obj.crossave_override,
    +2183            name=destiny_obj.name,
    +2184            last_seen_name=destiny_obj.last_seen_name,
    +2185            fireteam_display_name=payload["FireteamDisplayName"],
    +2186            fireteam_membership_id=enums.MembershipType(
    +2187                payload["FireteamMembershipType"]
    +2188            ),
    +2189        )
    +2190
    +2191    def deserialize_fireteam_members(
    +2192        self, payload: typedefs.JSONObject, *, alternatives: bool = False
    +2193    ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]:
    +2194        members_: list[fireteams.FireteamMember] = []
    +2195        if members := payload.get("Members" if not alternatives else "Alternates"):
    +2196            for member in members:
    +2197                bungie_fields = self.deserialize_partial_bungie_user(member)
    +2198                members_fields = fireteams.FireteamMember(
    +2199                    destiny_user=self.deserialize_fireteam_destiny_users(member),
    +2200                    has_microphone=member["hasMicrophone"],
    +2201                    character_id=int(member["characterId"]),
    +2202                    date_joined=time.clean_date(member["dateJoined"]),
    +2203                    last_platform_invite_date=time.clean_date(
    +2204                        member["lastPlatformInviteAttemptDate"]
    +2205                    ),
    +2206                    last_platform_invite_result=int(
    +2207                        member["lastPlatformInviteAttemptResult"]
    +2208                    ),
    +2209                    net=self._net,
    +2210                    name=bungie_fields.name,
    +2211                    id=bungie_fields.id,
    +2212                    icon=bungie_fields.icon,
    +2213                    is_public=bungie_fields.is_public,
    +2214                    crossave_override=bungie_fields.crossave_override,
    +2215                    types=bungie_fields.types,
    +2216                    type=bungie_fields.type,
    +2217                )
    +2218                members_.append(members_fields)
    +2219        else:
    +2220            return None
    +2221        return members_
    +2222
    +2223    def deserialize_available_fireteams(
    +2224        self,
    +2225        data: typedefs.JSONObject,
    +2226        *,
    +2227        no_results: bool = False,
    +2228    ) -> typing.Union[
    +2229        fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam]
    +2230    ]:
    +2231        fireteams_: list[fireteams.AvailableFireteam] = []
    +2232
    +2233        # This needs to be used outside the results
    +2234        # JSON key.
    +2235        if no_results is True:
    +2236            payload = data
    +2237
    +2238        if result := payload.get("results"):
    +2239
    +2240            for fireteam in result:
    +2241                found_fireteams = self._set_fireteam_fields(fireteam["Summary"])
    +2242                fireteams_fields = fireteams.AvailableFireteam(
    +2243                    id=found_fireteams.id,
    +2244                    group_id=found_fireteams.group_id,
    +2245                    platform=found_fireteams.platform,
    +2246                    activity_type=found_fireteams.activity_type,
    +2247                    is_immediate=found_fireteams.is_immediate,
    +2248                    is_public=found_fireteams.is_public,
    +2249                    is_valid=found_fireteams.is_valid,
    +2250                    owner_id=found_fireteams.owner_id,
    +2251                    player_slot_count=found_fireteams.player_slot_count,
    +2252                    available_player_slots=found_fireteams.available_player_slots,
    +2253                    available_alternate_slots=found_fireteams.available_alternate_slots,
    +2254                    title=found_fireteams.title,
    +2255                    date_created=found_fireteams.date_created,
    +2256                    locale=found_fireteams.locale,
    +2257                    last_modified=found_fireteams.last_modified,
    +2258                    total_results=found_fireteams.total_results,
    +2259                    members=self.deserialize_fireteam_members(payload),
    +2260                    alternatives=self.deserialize_fireteam_members(
    +2261                        payload, alternatives=True
    +2262                    ),
    +2263                )
    +2264            fireteams_.append(fireteams_fields)
    +2265            if no_results:
    +2266                return fireteams_fields
    +2267        return fireteams_
    +2268
    +2269    def deserialize_fireteam_party(
    +2270        self, payload: typedefs.JSONObject
    +2271    ) -> fireteams.FireteamParty:
    +2272        last_destination_hash: typing.Optional[int] = None
    +2273        if raw_dest_hash := payload.get("lastOrbitedDestinationHash"):
    +2274            last_destination_hash = int(raw_dest_hash)
    +2275
    +2276        return fireteams.FireteamParty(
    +2277            members=[
    +2278                self._deserialize_fireteam_party_member(member)
    +2279                for member in payload["partyMembers"]
    +2280            ],
    +2281            activity=self._deserialize_fireteam_party_current_activity(
    +2282                payload["currentActivity"]
    +2283            ),
    +2284            settings=self._deserialize_fireteam_party_settings(payload["joinability"]),
    +2285            last_destination_hash=last_destination_hash,
    +2286            tracking=payload["tracking"],
    +2287        )
    +2288
    +2289    def _deserialize_fireteam_party_member(
    +2290        self, payload: typedefs.JSONObject
    +2291    ) -> fireteams.FireteamPartyMember:
    +2292
    +2293        status = fireteams.FireteamPartyMemberState(payload["status"])
    +2294        displayname: undefined.UndefinedOr[str] = undefined.Undefined
    +2295        if raw_name := payload.get("displayName"):
    +2296            displayname = raw_name
    +2297
    +2298        return fireteams.FireteamPartyMember(
    +2299            membership_id=int(payload["membershipId"]),
    +2300            emblem_hash=int(payload["emblemHash"]),
    +2301            status=status,
    +2302            display_name=displayname,
    +2303        )
    +2304
    +2305    def _deserialize_fireteam_party_current_activity(
    +2306        self, payload: typedefs.JSONObject
    +2307    ) -> fireteams.FireteamPartyCurrentActivity:
    +2308        start_date: typing.Optional[datetime.datetime] = None
    +2309        if raw_start_date := payload.get("startTime"):
    +2310            start_date = time.clean_date(raw_start_date)
    +2311
    +2312        end_date: typing.Optional[datetime.datetime] = None
    +2313        if raw_end_date := payload.get("endTime"):
    +2314            end_date = time.clean_date(raw_end_date)
    +2315        return fireteams.FireteamPartyCurrentActivity(
    +2316            start_time=start_date,
    +2317            end_time=end_date,
    +2318            score=float(payload["score"]),
    +2319            highest_opposing_score=float(payload["highestOpposingFactionScore"]),
    +2320            opponenst_count=int(payload["numberOfOpponents"]),
    +2321            player_count=int(payload["numberOfPlayers"]),
    +2322        )
    +2323
    +2324    def _deserialize_fireteam_party_settings(
    +2325        self, payload: typedefs.JSONObject
    +2326    ) -> fireteams.FireteamPartySettings:
    +2327        closed_reasons = enums.ClosedReasons(payload["closedReasons"])
    +2328        return fireteams.FireteamPartySettings(
    +2329            open_slots=int(payload["openSlots"]),
    +2330            privacy_setting=enums.PrivacySetting(int(payload["privacySetting"])),
    +2331            closed_reasons=closed_reasons,
    +2332        )
    +2333
    +2334    def deserialize_seasonal_artifact(
    +2335        self, payload: typedefs.JSONObject
    +2336    ) -> season.Artifact:
    +2337        if raw_artifact := payload.get("seasonalArtifact"):
    +2338            if points := raw_artifact.get("pointProgression"):
    +2339                points_prog = progressions.Progression(
    +2340                    hash=points["progressionHash"],
    +2341                    level=points["level"],
    +2342                    cap=points["levelCap"],
    +2343                    daily_limit=points["dailyLimit"],
    +2344                    weekly_limit=points["weeklyLimit"],
    +2345                    current_progress=points["currentProgress"],
    +2346                    daily_progress=points["dailyProgress"],
    +2347                    needed=points["progressToNextLevel"],
    +2348                    next_level=points["nextLevelAt"],
    +2349                )
    +2350
    +2351            if bonus := raw_artifact.get("powerBonusProgression"):
    +2352                power_bonus_prog = progressions.Progression(
    +2353                    hash=bonus["progressionHash"],
    +2354                    level=bonus["level"],
    +2355                    cap=bonus["levelCap"],
    +2356                    daily_limit=bonus["dailyLimit"],
    +2357                    weekly_limit=bonus["weeklyLimit"],
    +2358                    current_progress=bonus["currentProgress"],
    +2359                    daily_progress=bonus["dailyProgress"],
    +2360                    needed=bonus["progressToNextLevel"],
    +2361                    next_level=bonus["nextLevelAt"],
    +2362                )
    +2363            artifact = season.Artifact(
    +2364                net=self._net,
    +2365                hash=raw_artifact["artifactHash"],
    +2366                power_bonus=raw_artifact["powerBonus"],
    +2367                acquired_points=raw_artifact["pointsAcquired"],
    +2368                bonus=power_bonus_prog,
    +2369                points=points_prog,
    +2370            )
    +2371        return artifact
    +2372
    +2373    def deserialize_profile_progression(
    +2374        self, payload: typedefs.JSONObject
    +2375    ) -> profile.ProfileProgression:
    +2376        return profile.ProfileProgression(
    +2377            artifact=self.deserialize_seasonal_artifact(payload["data"]),
    +2378            checklist={
    +2379                int(check_id): checklists
    +2380                for check_id, checklists in payload["data"]["checklists"].items()
    +2381            },
    +2382        )
    +2383
    +2384    def deserialize_instanced_item(
    +2385        self, payload: typedefs.JSONObject
    +2386    ) -> items.ItemInstance:
    +2387        damage_type_hash: typing.Optional[int] = None
    +2388        if raw_damagetype_hash := payload.get("damageTypeHash"):
    +2389            damage_type_hash = int(raw_damagetype_hash)
    +2390
    +2391        required_hashes: typing.Optional[collections.Collection[int]] = None
    +2392        if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"):
    +2393            required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes]
    +2394
    +2395        breaker_type: typing.Optional[items.ItemBreakerType] = None
    +2396        if raw_break_type := payload.get("breakerType"):
    +2397            breaker_type = items.ItemBreakerType(int(raw_break_type))
    +2398
    +2399        breaker_type_hash: typing.Optional[int] = None
    +2400        if raw_break_type_hash := payload.get("breakerTypeHash"):
    +2401            breaker_type_hash = int(raw_break_type_hash)
    +2402
    +2403        energy: typing.Optional[items.ItemEnergy] = None
    +2404        if raw_energy := payload.get("energy"):
    +2405            energy = self.deserialize_item_energy(raw_energy)
    +2406
    +2407        primary_stats = None
    +2408        if raw_primary_stats := payload.get("primaryStat"):
    +2409            primary_stats = self.deserialize_item_stats_view(raw_primary_stats)
    +2410
    +2411        return items.ItemInstance(
    +2412            damage_type=enums.DamageType(int(payload["damageType"])),
    +2413            damage_type_hash=damage_type_hash,
    +2414            primary_stat=primary_stats,
    +2415            item_level=int(payload["itemLevel"]),
    +2416            quality=int(payload["quality"]),
    +2417            is_equipped=payload["isEquipped"],
    +2418            can_equip=payload["canEquip"],
    +2419            equip_required_level=int(payload["equipRequiredLevel"]),
    +2420            required_equip_unlock_hashes=required_hashes,
    +2421            cant_equip_reason=int(payload["cannotEquipReason"]),
    +2422            breaker_type=breaker_type,
    +2423            breaker_type_hash=breaker_type_hash,
    +2424            energy=energy,
    +2425        )
    +2426
    +2427    def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy:
    +2428        energy_hash: typing.Optional[int] = None
    +2429        if raw_energy_hash := payload.get("energyTypeHash"):
    +2430            energy_hash = int(raw_energy_hash)
    +2431
    +2432        return items.ItemEnergy(
    +2433            hash=energy_hash,
    +2434            type=items.ItemEnergyType(int(payload["energyType"])),
    +2435            capacity=int(payload["energyCapacity"]),
    +2436            used_energy=int(payload["energyUsed"]),
    +2437            unused_energy=int(payload["energyUnused"]),
    +2438        )
    +2439
    +2440    def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk:
    +2441        perk_hash: typing.Optional[int] = None
    +2442        if raw_perk_hash := payload.get("perkHash"):
    +2443            perk_hash = int(raw_perk_hash)
    +2444
    +2445        return items.ItemPerk(
    +2446            hash=perk_hash,
    +2447            icon=assets.Image(payload["iconPath"]),
    +2448            is_active=payload["isActive"],
    +2449            is_visible=payload["visible"],
    +2450        )
    +2451
    +2452    def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket:
    +2453        plug_hash: typing.Optional[int] = None
    +2454        if raw_plug_hash := payload.get("plugHash"):
    +2455            plug_hash = int(raw_plug_hash)
    +2456
    +2457        enable_fail_indexes: typing.Optional[list[int]] = None
    +2458        if raw_indexes := payload.get("enableFailIndexes"):
    +2459            enable_fail_indexes = [int(index) for index in raw_indexes]
    +2460
    +2461        return items.ItemSocket(
    +2462            plug_hash=plug_hash,
    +2463            is_enabled=payload["isEnabled"],
    +2464            enable_fail_indexes=enable_fail_indexes,
    +2465            is_visible=payload.get("visible"),
    +2466        )
    +2467
    +2468    def deserialize_item_stats_view(
    +2469        self, payload: typedefs.JSONObject
    +2470    ) -> items.ItemStatsView:
    +2471        return items.ItemStatsView(
    +2472            stat_hash=payload.get("statHash"), value=payload.get("value")
    +2473        )
    +2474
    +2475    def deserialize_plug_item_state(
    +2476        self, payload: typedefs.JSONObject
    +2477    ) -> items.PlugItemState:
    +2478        item_hash: typing.Optional[int] = None
    +2479        if raw_item_hash := payload.get("plugItemHash"):
    +2480            item_hash = int(raw_item_hash)
    +2481
    +2482        insert_fail_indexes: typedefs.NoneOr[list[int]] = None
    +2483        if raw_fail_indexes := payload.get("insertFailIndexes"):
    +2484            insert_fail_indexes = [int(k) for k in raw_fail_indexes]
    +2485
    +2486        enable_fail_indexes: typedefs.NoneOr[list[int]] = None
    +2487        if raw_enabled_indexes := payload.get("enableFailIndexes"):
    +2488            enable_fail_indexes = [int(k) for k in raw_enabled_indexes]
    +2489
    +2490        return items.PlugItemState(
    +2491            item_hash=item_hash,
    +2492            insert_fail_indexes=insert_fail_indexes,
    +2493            enable_fail_indexes=enable_fail_indexes,
    +2494            is_enabled=payload["enabled"],
    +2495            can_insert=payload["canInsert"],
    +2496        )
     
    -

    Deserialize a JSON sequence of Bungie friend requests information.

    +

    The base deserialization factory class for all aiobungie objects.

    -

    This is used for incoming/outgoing friend requests.

    +

    Highly inspired hikari entity factory used to deserialize JSON responses from the REST client and turning them +into a aiobungie.crates Python classes.

    +
    -
    Parameters
    - +
    + +
    + + Factory(net: aiobungie.traits.Netrunner) -
    Returns
    + + +
    + +
    70    def __init__(self, net: traits.Netrunner) -> None:
    +71        self._net = net
    +
    - -
    +
    -
    - +
    +
    def - deserialize_fireteams( self, payload: dict[str, typing.Any]) -> Optional[collections.abc.Sequence[aiobungie.crates.fireteams.Fireteam]]: + deserialize_bungie_user(self, data: dict[str, typing.Any]) -> aiobungie.crates.user.BungieUser: - +
    - -
    2158    def deserialize_fireteams(
    -2159        self, payload: typedefs.JSONObject
    -2160    ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]:
    -2161        fireteams_: typing.MutableSequence[fireteams.Fireteam] = []
    -2162
    -2163        result: list[typedefs.JSONObject]
    -2164        if not (result := payload["results"]):
    -2165            return None
    -2166        for elem in result:
    -2167            fireteams_.append(
    -2168                self._set_fireteam_fields(
    -2169                    elem, total_results=int(payload["totalResults"])
    -2170                )
    -2171            )
    -2172        return fireteams_
    +    
    +            
    73    def deserialize_bungie_user(self, data: typedefs.JSONObject) -> user.BungieUser:
    +74        return user.BungieUser(
    +75            id=int(data["membershipId"]),
    +76            created_at=time.clean_date(data["firstAccess"]),
    +77            name=data.get("cachedBungieGlobalDisplayName", undefined.Undefined),
    +78            is_deleted=data["isDeleted"],
    +79            about=data["about"],
    +80            updated_at=time.clean_date(data["lastUpdate"]),
    +81            psn_name=data.get("psnDisplayName", None),
    +82            stadia_name=data.get("stadiaDisplayName", None),
    +83            steam_name=data.get("steamDisplayName", None),
    +84            twitch_name=data.get("twitchDisplayName", None),
    +85            blizzard_name=data.get("blizzardDisplayName", None),
    +86            status=data["statusText"],
    +87            locale=data["locale"],
    +88            picture=assets.Image(path=str(data["profilePicturePath"])),
    +89            code=data.get("cachedBungieGlobalDisplayNameCode", None),
    +90            unique_name=data.get("uniqueName", None),
    +91            theme_id=int(data["profileTheme"]),
    +92            show_activity=bool(data["showActivity"]),
    +93            theme_name=data["profileThemeName"],
    +94            display_title=data["userTitleDisplay"],
    +95        )
     
    -

    Deserialize a JSON sequence of Bungie fireteams information.

    +

    Deserialize a raw JSON Bungie.net user only payload into a user object.

    + +
    + +

    This only returns the Bungie.net user and not the Destiny memberships.

    + +
    Parameters
    Returns
    -
    - +
    +
    def - deserialize_fireteam_destiny_users( self, payload: dict[str, typing.Any]) -> aiobungie.crates.fireteams.FireteamUser: + deserialize_partial_bungie_user( self, payload: dict[str, typing.Any]) -> aiobungie.crates.user.PartialBungieUser: - +
    - -
    2174    def deserialize_fireteam_destiny_users(
    -2175        self, payload: typedefs.JSONObject
    -2176    ) -> fireteams.FireteamUser:
    -2177        destiny_obj = self.deserialize_destiny_membership(payload)
    -2178        # We could helpers.just return a DestinyMembership object but this is
    -2179        # missing the fireteam display name and id fields.
    -2180        return fireteams.FireteamUser(
    -2181            net=self._net,
    -2182            id=destiny_obj.id,
    -2183            code=destiny_obj.code,
    -2184            icon=destiny_obj.icon,
    -2185            types=destiny_obj.types,
    -2186            type=destiny_obj.type,
    -2187            is_public=destiny_obj.is_public,
    -2188            crossave_override=destiny_obj.crossave_override,
    -2189            name=destiny_obj.name,
    -2190            last_seen_name=destiny_obj.last_seen_name,
    -2191            fireteam_display_name=payload["FireteamDisplayName"],
    -2192            fireteam_membership_id=enums.MembershipType(
    -2193                payload["FireteamMembershipType"]
    -2194            ),
    -2195        )
    +    
    +            
     97    def deserialize_partial_bungie_user(
    + 98        self, payload: typedefs.JSONObject
    + 99    ) -> user.PartialBungieUser:
    +100        return user.PartialBungieUser(
    +101            net=self._net,
    +102            types=[
    +103                enums.MembershipType(type_)
    +104                for type_ in payload.get("applicableMembershipTypes", [])
    +105            ],
    +106            name=payload.get("displayName", undefined.Undefined),
    +107            id=int(payload["membershipId"]),
    +108            crossave_override=enums.MembershipType(payload["crossSaveOverride"]),
    +109            is_public=payload["isPublic"],
    +110            icon=assets.Image(payload.get("iconPath", "")),
    +111            type=enums.MembershipType(payload["membershipType"]),
    +112        )
     
    -

    Deserialize a JSON payload of Bungie fireteam destiny users information.

    +

    Deserialize a raw JSON of a partial bungieNetUserInfo.

    + +

    A partial user is a bungie.net user payload with missing information from +the main BungieUser object.

    Parameters
    @@ -15020,4428 +9537,4468 @@
    Parameters
    Returns
    -
    - +
    +
    def - deserialize_fireteam_members( self, payload: dict[str, typing.Any], *, alternatives: bool = False) -> Optional[collections.abc.Sequence[aiobungie.crates.fireteams.FireteamMember]]: + deserialize_destiny_membership( self, payload: dict[str, typing.Any]) -> aiobungie.crates.user.DestinyMembership: - +
    - -
    2197    def deserialize_fireteam_members(
    -2198        self, payload: typedefs.JSONObject, *, alternatives: bool = False
    -2199    ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]:
    -2200        members_: list[fireteams.FireteamMember] = []
    -2201        if members := payload.get("Members" if not alternatives else "Alternates"):
    -2202            for member in members:
    -2203                bungie_fields = self.deserialize_partial_bungie_user(member)
    -2204                members_fields = fireteams.FireteamMember(
    -2205                    destiny_user=self.deserialize_fireteam_destiny_users(member),
    -2206                    has_microphone=member["hasMicrophone"],
    -2207                    character_id=int(member["characterId"]),
    -2208                    date_joined=time.clean_date(member["dateJoined"]),
    -2209                    last_platform_invite_date=time.clean_date(
    -2210                        member["lastPlatformInviteAttemptDate"]
    -2211                    ),
    -2212                    last_platform_invite_result=int(
    -2213                        member["lastPlatformInviteAttemptResult"]
    -2214                    ),
    -2215                    net=self._net,
    -2216                    name=bungie_fields.name,
    -2217                    id=bungie_fields.id,
    -2218                    icon=bungie_fields.icon,
    -2219                    is_public=bungie_fields.is_public,
    -2220                    crossave_override=bungie_fields.crossave_override,
    -2221                    types=bungie_fields.types,
    -2222                    type=bungie_fields.type,
    -2223                )
    -2224                members_.append(members_fields)
    -2225        else:
    -2226            return None
    -2227        return members_
    +    
    +            
    114    def deserialize_destiny_membership(
    +115        self, payload: typedefs.JSONObject
    +116    ) -> user.DestinyMembership:
    +117        name: undefined.UndefinedOr[str] = undefined.Undefined
    +118        if (
    +119            raw_name := payload.get("bungieGlobalDisplayName", "")
    +120        ) and not typedefs.is_unknown(raw_name):
    +121            name = raw_name
    +122
    +123        return user.DestinyMembership(
    +124            net=self._net,
    +125            id=int(payload["membershipId"]),
    +126            name=name,
    +127            code=payload.get("bungieGlobalDisplayNameCode", None),
    +128            last_seen_name=payload.get("LastSeenDisplayName")
    +129            or payload.get("displayName")  # noqa: W503
    +130            or "",  # noqa: W503
    +131            type=enums.MembershipType(payload["membershipType"]),
    +132            is_public=payload["isPublic"],
    +133            crossave_override=enums.MembershipType(payload["crossSaveOverride"]),
    +134            icon=assets.Image(payload.get("iconPath", "")),
    +135            types=[
    +136                enums.MembershipType(type_)
    +137                for type_ in payload.get("applicableMembershipTypes", [])
    +138            ],
    +139        )
     
    -

    Deserialize a JSON sequence of Bungie fireteam members information.

    +

    Deserialize a raw JSON of destinyUserInfo destiny membership information.

    Parameters
    • payload (aiobungie.typedefs.JSONObject): The JSON payload.
    • -
    • alternatives (bool): -If set to True, Then it will deserialize the alternatives data in the payload. -If not the it will just deserialize the members data.
    Returns
      -
    • typing.Optional[collections.Sequence[aiobungie.crates.FireteamUser]]: An optional sequence of the fireteam members.
    • +
    • aiobungie.crates.user.DestinyMembership: A Destiny 2 membership.
    -
    - +
    +
    def - deserialize_available_fireteams( self, data: dict[str, typing.Any], *, no_results: bool = False) -> Union[aiobungie.crates.fireteams.AvailableFireteam, collections.abc.Sequence[aiobungie.crates.fireteams.AvailableFireteam]]: + deserialize_destiny_memberships( self, data: list[typing.Any]) -> collections.abc.Sequence[aiobungie.crates.user.DestinyMembership]: - +
    - -
    2229    def deserialize_available_fireteams(
    -2230        self,
    -2231        data: typedefs.JSONObject,
    -2232        *,
    -2233        no_results: bool = False,
    -2234    ) -> typing.Union[
    -2235        fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam]
    -2236    ]:
    -2237        fireteams_: list[fireteams.AvailableFireteam] = []
    -2238
    -2239        # This needs to be used outside the results
    -2240        # JSON key.
    -2241        if no_results is True:
    -2242            payload = data
    -2243
    -2244        if result := payload.get("results"):
    -2245
    -2246            for fireteam in result:
    -2247                found_fireteams = self._set_fireteam_fields(fireteam["Summary"])
    -2248                fireteams_fields = fireteams.AvailableFireteam(
    -2249                    id=found_fireteams.id,
    -2250                    group_id=found_fireteams.group_id,
    -2251                    platform=found_fireteams.platform,
    -2252                    activity_type=found_fireteams.activity_type,
    -2253                    is_immediate=found_fireteams.is_immediate,
    -2254                    is_public=found_fireteams.is_public,
    -2255                    is_valid=found_fireteams.is_valid,
    -2256                    owner_id=found_fireteams.owner_id,
    -2257                    player_slot_count=found_fireteams.player_slot_count,
    -2258                    available_player_slots=found_fireteams.available_player_slots,
    -2259                    available_alternate_slots=found_fireteams.available_alternate_slots,
    -2260                    title=found_fireteams.title,
    -2261                    date_created=found_fireteams.date_created,
    -2262                    locale=found_fireteams.locale,
    -2263                    last_modified=found_fireteams.last_modified,
    -2264                    total_results=found_fireteams.total_results,
    -2265                    members=self.deserialize_fireteam_members(payload),
    -2266                    alternatives=self.deserialize_fireteam_members(
    -2267                        payload, alternatives=True
    -2268                    ),
    -2269                )
    -2270            fireteams_.append(fireteams_fields)
    -2271            if no_results:
    -2272                return fireteams_fields
    -2273        return fireteams_
    +    
    +            
    141    def deserialize_destiny_memberships(
    +142        self, data: typedefs.JSONArray
    +143    ) -> collections.Sequence[user.DestinyMembership]:
    +144        return [self.deserialize_destiny_membership(membership) for membership in data]
     
    -

    Deserialize a JSON payload of a sequence of/fireteam information.

    +

    Deserialize a raw JSON payload/array of destinyUserInfo.

    Parameters
    Returns
      -
    • typing.Union[aiobungie.crates.fireteams.AvailableFireteam, collections.Sequence[aiobungie.crates.fireteams.AvailableFireteam]] # noqa (E501): -An available fireteam or a sequence of available fireteam.
    • +
    • collections.Sequence[aiobungie.crates.user.DestinyMembership]: A sequence of Destiny 2 memberships.
    -
    - +
    +
    def - deserialize_fireteam_party( self, payload: dict[str, typing.Any]) -> aiobungie.crates.fireteams.FireteamParty: + deserialize_user(self, data: dict[str, typing.Any]) -> aiobungie.crates.user.User: - +
    - -
    2275    def deserialize_fireteam_party(
    -2276        self, payload: typedefs.JSONObject
    -2277    ) -> fireteams.FireteamParty:
    -2278        last_destination_hash: typing.Optional[int] = None
    -2279        if raw_dest_hash := payload.get("lastOrbitedDestinationHash"):
    -2280            last_destination_hash = int(raw_dest_hash)
    -2281
    -2282        return fireteams.FireteamParty(
    -2283            members=[
    -2284                self._deserialize_fireteam_party_member(member)
    -2285                for member in payload["partyMembers"]
    -2286            ],
    -2287            activity=self._deserialize_fireteam_party_current_activity(
    -2288                payload["currentActivity"]
    -2289            ),
    -2290            settings=self._deserialize_fireteam_party_settings(payload["joinability"]),
    -2291            last_destination_hash=last_destination_hash,
    -2292            tracking=payload["tracking"],
    -2293        )
    +    
    +            
    146    def deserialize_user(self, data: typedefs.JSONObject) -> user.User:
    +147
    +148        primary_membership_id: typing.Optional[int] = None
    +149        if raw_primary_id := data.get("primaryMembershipId"):
    +150            primary_membership_id = int(raw_primary_id)
    +151
    +152        return user.User(
    +153            bungie=self.deserialize_bungie_user(data["bungieNetUser"]),
    +154            destiny=self.deserialize_destiny_memberships(data["destinyMemberships"]),
    +155            primary_membership_id=primary_membership_id,
    +156        )
     
    -

    Deserialize a JSON payload of profileTransitory component response.

    +

    Deserialize a raw JSON results of fetched user memberships and Bungie.net user its their id.

    Parameters
    Returns
    -
    - +
    +
    def - deserialize_seasonal_artifact(self, payload: dict[str, typing.Any]) -> aiobungie.crates.season.Artifact: + deserialize_searched_user( self, payload: dict[str, typing.Any]) -> aiobungie.crates.user.SearchableDestinyUser: - +
    - -
    2340    def deserialize_seasonal_artifact(
    -2341        self, payload: typedefs.JSONObject
    -2342    ) -> season.Artifact:
    -2343        if raw_artifact := payload.get("seasonalArtifact"):
    -2344            if points := raw_artifact.get("pointProgression"):
    -2345                points_prog = progressions.Progression(
    -2346                    hash=points["progressionHash"],
    -2347                    level=points["level"],
    -2348                    cap=points["levelCap"],
    -2349                    daily_limit=points["dailyLimit"],
    -2350                    weekly_limit=points["weeklyLimit"],
    -2351                    current_progress=points["currentProgress"],
    -2352                    daily_progress=points["dailyProgress"],
    -2353                    needed=points["progressToNextLevel"],
    -2354                    next_level=points["nextLevelAt"],
    -2355                )
    -2356
    -2357            if bonus := raw_artifact.get("powerBonusProgression"):
    -2358                power_bonus_prog = progressions.Progression(
    -2359                    hash=bonus["progressionHash"],
    -2360                    level=bonus["level"],
    -2361                    cap=bonus["levelCap"],
    -2362                    daily_limit=bonus["dailyLimit"],
    -2363                    weekly_limit=bonus["weeklyLimit"],
    -2364                    current_progress=bonus["currentProgress"],
    -2365                    daily_progress=bonus["dailyProgress"],
    -2366                    needed=bonus["progressToNextLevel"],
    -2367                    next_level=bonus["nextLevelAt"],
    -2368                )
    -2369            artifact = season.Artifact(
    -2370                net=self._net,
    -2371                hash=raw_artifact["artifactHash"],
    -2372                power_bonus=raw_artifact["powerBonus"],
    -2373                acquired_points=raw_artifact["pointsAcquired"],
    -2374                bonus=power_bonus_prog,
    -2375                points=points_prog,
    -2376            )
    -2377        return artifact
    +    
    +            
    158    def deserialize_searched_user(
    +159        self, payload: typedefs.JSONObject
    +160    ) -> user.SearchableDestinyUser:
    +161        name: undefined.UndefinedOr[str] = undefined.Undefined
    +162        if (raw_name := payload["bungieGlobalDisplayName"]) and not typedefs.is_unknown(
    +163            raw_name
    +164        ):
    +165            name = raw_name
    +166
    +167        code: typing.Optional[int] = None
    +168        if raw_code := payload.get("bungieGlobalDisplayNameCode"):
    +169            code = int(raw_code)
    +170
    +171        bungie_id: typing.Optional[int] = None
    +172        if raw_bungie_id := payload.get("bungieNetMembershipId"):
    +173            bungie_id = int(raw_bungie_id)
    +174
    +175        return user.SearchableDestinyUser(
    +176            name=name,
    +177            code=code,
    +178            bungie_id=bungie_id,
    +179            memberships=self.deserialize_destiny_memberships(
    +180                payload["destinyMemberships"]
    +181            ),
    +182        )
     
    -

    Deserialize a JSON payload of a Destiny 2 seasonal artifact information.

    +

    Deserialize the results of user search details.

    Parameters
    Returns
    -
    - +
    +
    def - deserialize_profile_progression( self, payload: dict[str, typing.Any]) -> aiobungie.crates.profile.ProfileProgression: + deserialize_user_credentials( self, payload: list[typing.Any]) -> collections.abc.Sequence[aiobungie.crates.user.UserCredentials]: - +
    - -
    2379    def deserialize_profile_progression(
    -2380        self, payload: typedefs.JSONObject
    -2381    ) -> profile.ProfileProgression:
    -2382        return profile.ProfileProgression(
    -2383            artifact=self.deserialize_seasonal_artifact(payload["data"]),
    -2384            checklist={
    -2385                int(check_id): checklists
    -2386                for check_id, checklists in payload["data"]["checklists"].items()
    -2387            },
    -2388        )
    +    
    +            
    184    def deserialize_user_credentials(
    +185        self, payload: typedefs.JSONArray
    +186    ) -> collections.Sequence[user.UserCredentials]:
    +187        return [
    +188            user.UserCredentials(
    +189                type=enums.CredentialType(int(creds["credentialType"])),
    +190                display_name=creds["credentialDisplayName"],
    +191                is_public=creds["isPublic"],
    +192                self_as_string=creds.get("credentialAsString", undefined.Undefined),
    +193            )
    +194            for creds in payload
    +195        ]
     
    -

    Deserialize a JSON payload of a profile progression component.

    +

    Deserialize a JSON array of Bungie user credentials.

    Parameters
    Returns
    -
    - +
    +
    def - deserialize_instanced_item( self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.ItemInstance: + deserialize_user_themes( self, payload: list[typing.Any]) -> collections.abc.Sequence[aiobungie.crates.user.UserThemes]: - +
    - -
    2390    def deserialize_instanced_item(
    -2391        self, payload: typedefs.JSONObject
    -2392    ) -> items.ItemInstance:
    -2393        damage_type_hash: typing.Optional[int] = None
    -2394        if raw_damagetype_hash := payload.get("damageTypeHash"):
    -2395            damage_type_hash = int(raw_damagetype_hash)
    -2396
    -2397        required_hashes: typing.Optional[collections.Collection[int]] = None
    -2398        if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"):
    -2399            required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes]
    -2400
    -2401        breaker_type: typing.Optional[items.ItemBreakerType] = None
    -2402        if raw_break_type := payload.get("breakerType"):
    -2403            breaker_type = items.ItemBreakerType(int(raw_break_type))
    -2404
    -2405        breaker_type_hash: typing.Optional[int] = None
    -2406        if raw_break_type_hash := payload.get("breakerTypeHash"):
    -2407            breaker_type_hash = int(raw_break_type_hash)
    -2408
    -2409        energy: typing.Optional[items.ItemEnergy] = None
    -2410        if raw_energy := payload.get("energy"):
    -2411            energy = self.deserialize_item_energy(raw_energy)
    -2412
    -2413        primary_stats = None
    -2414        if raw_primary_stats := payload.get("primaryStat"):
    -2415            primary_stats = self.deserialize_item_stats_view(raw_primary_stats)
    -2416
    -2417        return items.ItemInstance(
    -2418            damage_type=enums.DamageType(int(payload["damageType"])),
    -2419            damage_type_hash=damage_type_hash,
    -2420            primary_stat=primary_stats,
    -2421            item_level=int(payload["itemLevel"]),
    -2422            quality=int(payload["quality"]),
    -2423            is_equipped=payload["isEquipped"],
    -2424            can_equip=payload["canEquip"],
    -2425            equip_required_level=int(payload["equipRequiredLevel"]),
    -2426            required_equip_unlock_hashes=required_hashes,
    -2427            cant_equip_reason=int(payload["cannotEquipReason"]),
    -2428            breaker_type=breaker_type,
    -2429            breaker_type_hash=breaker_type_hash,
    -2430            energy=energy,
    -2431        )
    +    
    +            
    197    def deserialize_user_themes(
    +198        self, payload: typedefs.JSONArray
    +199    ) -> collections.Sequence[user.UserThemes]:
    +200        return [
    +201            user.UserThemes(
    +202                id=int(entry["userThemeId"]),
    +203                name=entry["userThemeName"]
    +204                if "userThemeName" in entry
    +205                else undefined.Undefined,
    +206                description=entry["userThemeDescription"]
    +207                if "userThemeDescription" in entry
    +208                else undefined.Undefined,
    +209            )
    +210            for entry in payload
    +211        ]
     
    -

    Deserialize a JSON object into an instanced item.

    +

    Deserialize a raw JSON array of Bungie user themes.

    Parameters
    Returns
      -
    • aiobungie.crates.ItemInstance: An instanced item object.
    • +
    • collections.Sequence[aiobungie.crates.user.UserThemes]: A sequence of bungie user themes.
    -
    - -
    - - def - deserialize_item_energy( self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.ItemEnergy: - - - -
    - -
    2433    def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy:
    -2434        energy_hash: typing.Optional[int] = None
    -2435        if raw_energy_hash := payload.get("energyTypeHash"):
    -2436            energy_hash = int(raw_energy_hash)
    -2437
    -2438        return items.ItemEnergy(
    -2439            hash=energy_hash,
    -2440            type=items.ItemEnergyType(int(payload["energyType"])),
    -2441            capacity=int(payload["energyCapacity"]),
    -2442            used_energy=int(payload["energyUsed"]),
    -2443            unused_energy=int(payload["energyUnused"]),
    -2444        )
    -
    - - - - -
    -
    - -
    - - def - deserialize_item_perk(self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.ItemPerk: - - - -
    - -
    2446    def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk:
    -2447        perk_hash: typing.Optional[int] = None
    -2448        if raw_perk_hash := payload.get("perkHash"):
    -2449            perk_hash = int(raw_perk_hash)
    -2450
    -2451        return items.ItemPerk(
    -2452            hash=perk_hash,
    -2453            icon=assets.Image(payload["iconPath"]),
    -2454            is_active=payload["isActive"],
    -2455            is_visible=payload["visible"],
    -2456        )
    -
    - - - - -
    -
    - +
    +
    def - deserialize_item_socket( self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.ItemSocket: + deserialize_clan(self, payload: dict[str, typing.Any]) -> aiobungie.crates.clans.Clan: - +
    - -
    2458    def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket:
    -2459        plug_hash: typing.Optional[int] = None
    -2460        if raw_plug_hash := payload.get("plugHash"):
    -2461            plug_hash = int(raw_plug_hash)
    -2462
    -2463        enable_fail_indexes: typing.Optional[list[int]] = None
    -2464        if raw_indexes := payload.get("enableFailIndexes"):
    -2465            enable_fail_indexes = [int(index) for index in raw_indexes]
    -2466
    -2467        return items.ItemSocket(
    -2468            plug_hash=plug_hash,
    -2469            is_enabled=payload["isEnabled"],
    -2470            enable_fail_indexes=enable_fail_indexes,
    -2471            is_visible=payload.get("visible"),
    -2472        )
    +    
    +            
    213    def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan:
    +214
    +215        # This is kinda redundant
    +216        data = payload
    +217
    +218        # This is always outside the details.
    +219        current_user_map: typing.Optional[
    +220            collections.Mapping[str, clans.ClanMember]
    +221        ] = None
    +222        if raw_current_user_map := payload.get("currentUserMemberMap"):
    +223            current_user_map = {
    +224                membership_type: self.deserialize_clan_member(membership)
    +225                for membership_type, membership in raw_current_user_map.items()
    +226            }
    +227
    +228        try:
    +229            data = payload["detail"]
    +230        except KeyError:
    +231            pass
    +232
    +233        id = data["groupId"]
    +234        name = data["name"]
    +235        created_at = data["creationDate"]
    +236        member_count = data["memberCount"]
    +237        about = data["about"]
    +238        motto = data["motto"]
    +239        is_public = data["isPublic"]
    +240        banner = assets.Image(str(data["bannerPath"]))
    +241        avatar = assets.Image(str(data["avatarPath"]))
    +242        tags = data["tags"]
    +243        type = data["groupType"]
    +244
    +245        features = data["features"]
    +246        features_obj = clans.ClanFeatures(
    +247            max_members=features["maximumMembers"],
    +248            max_membership_types=features["maximumMembershipsOfGroupType"],
    +249            capabilities=features["capabilities"],
    +250            membership_types=features["membershipTypes"],
    +251            invite_permissions=features["invitePermissionOverride"],
    +252            update_banner_permissions=features["updateBannerPermissionOverride"],
    +253            update_culture_permissions=features["updateCulturePermissionOverride"],
    +254            join_level=features["joinLevel"],
    +255        )
    +256
    +257        information: typedefs.JSONObject = data["clanInfo"]
    +258        progression: collections.Mapping[int, progressions.Progression] = {
    +259            int(prog_hash): self.deserialize_progressions(prog)
    +260            for prog_hash, prog in information["d2ClanProgressions"].items()
    +261        }
    +262
    +263        founder: typedefs.NoneOr[clans.ClanMember] = None
    +264        if raw_founder := payload.get("founder"):
    +265            founder = self.deserialize_clan_member(raw_founder)
    +266
    +267        return clans.Clan(
    +268            net=self._net,
    +269            id=int(id),
    +270            name=name,
    +271            type=enums.GroupType(type),
    +272            created_at=time.clean_date(created_at),
    +273            member_count=member_count,
    +274            motto=motto,
    +275            about=about,
    +276            is_public=is_public,
    +277            banner=banner,
    +278            avatar=avatar,
    +279            tags=tags,
    +280            features=features_obj,
    +281            owner=founder,
    +282            progressions=progression,
    +283            call_sign=information["clanCallsign"],
    +284            banner_data=information["clanBannerData"],
    +285            chat_security=data["chatSecurity"],
    +286            conversation_id=int(data["conversationId"]),
    +287            allow_chat=data["allowChat"],
    +288            theme=data["theme"],
    +289            current_user_membership=current_user_map,
    +290        )
     
    - +

    Deserialize a raw JSON payload of Bungie clan information.

    -
    -
    - -
    - - def - deserialize_item_stats_view( self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.ItemStatsView: +
    Parameters
    - + -
    - -
    2474    def deserialize_item_stats_view(
    -2475        self, payload: typedefs.JSONObject
    -2476    ) -> items.ItemStatsView:
    -2477        return items.ItemStatsView(
    -2478            stat_hash=payload.get("statHash"), value=payload.get("value")
    -2479        )
    -
    +
    Returns
    + +
    -
    -
    - +
    +
    def - deserialize_plug_item_state( self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.PlugItemState: + deserialize_clan_member( self, data: dict[str, typing.Any], /) -> aiobungie.crates.clans.ClanMember: - +
    - -
    2481    def deserialize_plug_item_state(
    -2482        self, payload: typedefs.JSONObject
    -2483    ) -> items.PlugItemState:
    -2484        item_hash: typing.Optional[int] = None
    -2485        if raw_item_hash := payload.get("plugItemHash"):
    -2486            item_hash = int(raw_item_hash)
    -2487
    -2488        insert_fail_indexes: typedefs.NoneOr[list[int]] = None
    -2489        if raw_fail_indexes := payload.get("insertFailIndexes"):
    -2490            insert_fail_indexes = [int(k) for k in raw_fail_indexes]
    -2491
    -2492        enable_fail_indexes: typedefs.NoneOr[list[int]] = None
    -2493        if raw_enabled_indexes := payload.get("enableFailIndexes"):
    -2494            enable_fail_indexes = [int(k) for k in raw_enabled_indexes]
    -2495
    -2496        return items.PlugItemState(
    -2497            item_hash=item_hash,
    -2498            insert_fail_indexes=insert_fail_indexes,
    -2499            enable_fail_indexes=enable_fail_indexes,
    -2500            is_enabled=payload["enabled"],
    -2501            can_insert=payload["canInsert"],
    -2502        )
    +    
    +            
    292    def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember:
    +293        destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"])
    +294        return clans.ClanMember(
    +295            net=self._net,
    +296            last_seen_name=destiny_user.last_seen_name,
    +297            id=destiny_user.id,
    +298            name=destiny_user.name,
    +299            icon=destiny_user.icon,
    +300            last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])),
    +301            group_id=int(data["groupId"]),
    +302            joined_at=time.clean_date(data["joinDate"]),
    +303            types=destiny_user.types,
    +304            is_public=destiny_user.is_public,
    +305            type=destiny_user.type,
    +306            code=destiny_user.code,
    +307            is_online=data["isOnline"],
    +308            crossave_override=destiny_user.crossave_override,
    +309            bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"])
    +310            if "bungieNetUserInfo" in data
    +311            else None,
    +312            member_type=enums.ClanMemberType(int(data["memberType"])),
    +313        )
     
    - - -
    -
    -
    - -
    -
    @typing.final
    - - class - FireteamActivity(builtins.int, aiobungie.Enum): +

    Deserialize a JSON payload of a clan member information.

    - +
    Parameters
    -
    - -
     68@typing.final
    - 69class FireteamActivity(int, enums.Enum):
    - 70    """An enum for the fireteam activities."""
    - 71
    - 72    ALL = 0
    - 73    CRUCIBLE = 2
    - 74    TRIALS_OF_OSIRIS = 3
    - 75    NIGHTFALL = 4
    - 76    ANY = 5
    - 77    GAMBIT = 6
    - 78    BLIND_WELL = 7
    - 79    NIGHTMARE_HUNTS = 12
    - 80    ALTARS_OF_SORROWS = 14
    - 81    DUNGEON = 15
    - 82    RAID_LW = 20
    - 83    RAID_GOS = 21
    - 84    RAID_DSC = 22
    - 85    EXO_CHALLENGE = 23
    - 86    S12_WRATHBORN = 24
    - 87    EMPIRE_HUNTS = 25
    - 88    S13_BATTLEGROUNDS = 26
    - 89    EXOTIC_QUEST = 27
    - 90    RAID_VOG = 28
    - 91    S14_EXPUNGE = 30
    - 92    S15_ASTRAL_ALIGNMENT = 31
    - 93    S15_SHATTERED_RELAM = 32
    - 94    SHATTERED_THRONE = 33
    - 95    PROPHECY = 34
    - 96    PIT_OF_HERESY = 35
    - 97    DOE = 36
    - 98    """Dares of Eternity."""
    - 99    DUNGEON_GOA = 37
    -100    """Grasp of Avarice."""
    -101    VOW_OF_THE_DISCPILE = 38
    -102    CAMPAIGN = 39
    -103    WELLSPRING = 40
    -104    S16_BATTLEGROUNDS = 41
    -105    S17_NIGHTMARE_CONTAINMENT = 44
    -106    S17_SEVER = 45
    -
    + +
    Returns
    -

    An enum for the fireteam activities.

    +
    -
    -
    - ALL = <FireteamActivity.ALL: 0> - - -
    - - - -
    -
    -
    - CRUCIBLE = <FireteamActivity.CRUCIBLE: 2> - - -
    - - - +
    + +
    + + def + deserialize_clan_members( self, data: dict[str, typing.Any], /) -> aiobungie.Iterator[aiobungie.crates.clans.ClanMember]: -
    -
    -
    - TRIALS_OF_OSIRIS = <FireteamActivity.TRIALS_OF_OSIRIS: 3> + -
    - - - - -
    -
    -
    - NIGHTFALL = <FireteamActivity.NIGHTFALL: 4> + +
    315    def deserialize_clan_members(
    +316        self, data: typedefs.JSONObject, /
    +317    ) -> iterators.Iterator[clans.ClanMember]:
    +318        return iterators.Iterator(
    +319            [self.deserialize_clan_member(member) for member in data["results"]]
    +320        )
    +
    - -
    - - - -
    -
    -
    - ANY = <FireteamActivity.ANY: 5> +

    Deserialize a JSON payload of a clan members information.

    - -
    - - - +
    Parameters
    -
    -
    -
    - GAMBIT = <FireteamActivity.GAMBIT: 6> + - -
    - - - +
    Returns
    -
    -
    -
    - BLIND_WELL = <FireteamActivity.BLIND_WELL: 7> + +
    - -
    - - -
    -
    -
    - NIGHTMARE_HUNTS = <FireteamActivity.NIGHTMARE_HUNTS: 12> - - -
    - - - +
    + +
    + + def + deserialize_group_member( self, payload: dict[str, typing.Any]) -> aiobungie.crates.clans.GroupMember: -
    -
    -
    - ALTARS_OF_SORROWS = <FireteamActivity.ALTARS_OF_SORROWS: 14> + -
    - - - - -
    -
    -
    - DUNGEON = <FireteamActivity.DUNGEON: 15> + +
    322    def deserialize_group_member(
    +323        self, payload: typedefs.JSONObject
    +324    ) -> clans.GroupMember:
    +325        member = payload["member"]
    +326        return clans.GroupMember(
    +327            net=self._net,
    +328            join_date=time.clean_date(member["joinDate"]),
    +329            group_id=int(member["groupId"]),
    +330            member_type=enums.ClanMemberType(member["memberType"]),
    +331            is_online=member["isOnline"],
    +332            last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])),
    +333            inactive_memberships=payload.get("areAllMembershipsInactive", None),
    +334            member=self.deserialize_destiny_membership(member["destinyUserInfo"]),
    +335            group=self.deserialize_clan(payload["group"]),
    +336        )
    +
    - -
    - - - -
    -
    -
    - RAID_LW = <FireteamActivity.RAID_LW: 20> +

    Deserialize a JSON payload of group information for a member.

    - -
    - - - +
    Parameters
    -
    -
    -
    - RAID_GOS = <FireteamActivity.RAID_GOS: 21> + - -
    - - - +
    Returns
    -
    -
    -
    - RAID_DSC = <FireteamActivity.RAID_DSC: 22> + +
    - -
    - - -
    -
    -
    - EXO_CHALLENGE = <FireteamActivity.EXO_CHALLENGE: 23> - - -
    - - - +
    + +
    + + def + deserialize_clan_conversations( self, payload: list[typing.Any]) -> collections.abc.Sequence[aiobungie.crates.clans.ClanConversation]: -
    -
    -
    - S12_WRATHBORN = <FireteamActivity.S12_WRATHBORN: 24> + -
    - - - + +
    354    def deserialize_clan_conversations(
    +355        self, payload: typedefs.JSONArray
    +356    ) -> collections.Sequence[clans.ClanConversation]:
    +357        return [self._deserialize_clan_conversation(conv) for conv in payload]
    +
    -
    -
    -
    - EMPIRE_HUNTS = <FireteamActivity.EMPIRE_HUNTS: 25> - -
    - - - +

    Deserialize a JSON array of a clan conversations information.

    -
    -
    -
    - S13_BATTLEGROUNDS = <FireteamActivity.S13_BATTLEGROUNDS: 26> +
    Parameters
    - -
    - - - + -
    -
    -
    - EXOTIC_QUEST = <FireteamActivity.EXOTIC_QUEST: 27> +
    Returns
    + + +
    - -
    - - -
    -
    -
    - RAID_VOG = <FireteamActivity.RAID_VOG: 28> +
    + +
    + + def + deserialize_app_owner( self, payload: dict[str, typing.Any]) -> aiobungie.crates.application.ApplicationOwner: + + -
    - - - + +
    359    def deserialize_app_owner(
    +360        self, payload: typedefs.JSONObject
    +361    ) -> application.ApplicationOwner:
    +362        return application.ApplicationOwner(
    +363            net=self._net,
    +364            name=payload.get("bungieGlobalDisplayName", undefined.Undefined),
    +365            id=int(payload["membershipId"]),
    +366            type=enums.MembershipType(payload["membershipType"]),
    +367            icon=assets.Image(str(payload["iconPath"])),
    +368            is_public=payload["isPublic"],
    +369            code=payload.get("bungieGlobalDisplayNameCode", None),
    +370        )
    +
    -
    -
    -
    - S14_EXPUNGE = <FireteamActivity.S14_EXPUNGE: 30> - -
    - - - +

    Deserialize a JSON payload of Bungie Developer portal application owner information.

    + +
    Parameters
    -
    -
    -
    - S15_ASTRAL_ALIGNMENT = <FireteamActivity.S15_ASTRAL_ALIGNMENT: 31> + - -
    - - - +
    Returns
    -
    -
    -
    - S15_SHATTERED_RELAM = <FireteamActivity.S15_SHATTERED_RELAM: 32> +
      +
    • aiobungie.crates.application.ApplicationOwner: An application owner.
    • +
    +
    - -
    - - -
    -
    -
    - SHATTERED_THRONE = <FireteamActivity.SHATTERED_THRONE: 33> +
    + +
    + + def + deserialize_app( self, payload: dict[str, typing.Any]) -> aiobungie.crates.application.Application: + + -
    - - - + +
    372    def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application:
    +373        return application.Application(
    +374            id=int(payload["applicationId"]),
    +375            name=payload["name"],
    +376            link=payload["link"],
    +377            status=payload["status"],
    +378            redirect_url=payload.get("redirectUrl", None),
    +379            created_at=time.clean_date(str(payload["creationDate"])),
    +380            published_at=time.clean_date(str(payload["firstPublished"])),
    +381            owner=self.deserialize_app_owner(payload["team"][0]["user"]),  # type: ignore
    +382            scope=payload.get("scope", undefined.Undefined),
    +383        )
    +
    -
    -
    -
    - PROPHECY = <FireteamActivity.PROPHECY: 34> - -
    - - - +

    Deserialize a JSON payload of Bungie Developer portal application information.

    -
    -
    -
    - PIT_OF_HERESY = <FireteamActivity.PIT_OF_HERESY: 35> +
    Parameters
    - -
    - - - + -
    -
    -
    - DOE = <FireteamActivity.DOE: 36> +
    Returns
    - -
    - - -

    Dares of Eternity.

    +
      +
    • aiobungie.crates.application.Application: An application.
    • +
    -
    -
    - DUNGEON_GOA = <FireteamActivity.DUNGEON_GOA: 37> +
    + +
    + + def + deserialize_profile( self, payload: dict[str, typing.Any], /) -> Optional[aiobungie.crates.profile.Profile]: + + -
    - - -

    Grasp of Avarice.

    -
    + +
    406    def deserialize_profile(
    +407        self, payload: typedefs.JSONObject, /
    +408    ) -> typing.Optional[profile.Profile]:
    +409        if (raw_profile := payload.get("data")) is None:
    +410            return None
    +411
    +412        payload = raw_profile
    +413        id = int(payload["userInfo"]["membershipId"])
    +414        name = payload["userInfo"]["displayName"]
    +415        is_public = payload["userInfo"]["isPublic"]
    +416        type = enums.MembershipType(payload["userInfo"]["membershipType"])
    +417        last_played = time.clean_date(str(payload["dateLastPlayed"]))
    +418        character_ids = [int(cid) for cid in payload["characterIds"]]
    +419        power_cap = payload["currentSeasonRewardPowerCap"]
    +420
    +421        return profile.Profile(
    +422            id=int(id),
    +423            name=name,
    +424            is_public=is_public,
    +425            type=type,
    +426            last_played=last_played,
    +427            character_ids=character_ids,
    +428            power_cap=power_cap,
    +429            net=self._net,
    +430        )
    +
    -
    -
    -
    - VOW_OF_THE_DISCPILE = <FireteamActivity.VOW_OF_THE_DISCPILE: 38> +

    Deserialize a JSON payload of Bungie.net profile information.

    - -
    - - - +
    Parameters
    -
    -
    -
    - CAMPAIGN = <FireteamActivity.CAMPAIGN: 39> + - -
    - - - +
    Returns
    -
    -
    -
    - WELLSPRING = <FireteamActivity.WELLSPRING: 40> + +
    - -
    - - -
    -
    -
    - S16_BATTLEGROUNDS = <FireteamActivity.S16_BATTLEGROUNDS: 41> +
    + +
    + + def + deserialize_profile_item( self, payload: dict[str, typing.Any]) -> aiobungie.crates.profile.ProfileItemImpl: + + -
    - - - + +
    432    def deserialize_profile_item(
    +433        self, payload: typedefs.JSONObject
    +434    ) -> profile.ProfileItemImpl:
    +435
    +436        instance_id: typing.Optional[int] = None
    +437        if raw_instance_id := payload.get("itemInstanceId"):
    +438            instance_id = int(raw_instance_id)
    +439
    +440        version_number: typing.Optional[int] = None
    +441        if raw_version := payload.get("versionNumber"):
    +442            version_number = int(raw_version)
    +443
    +444        transfer_status = enums.TransferStatus(payload["transferStatus"])
    +445
    +446        return profile.ProfileItemImpl(
    +447            net=self._net,
    +448            hash=payload["itemHash"],
    +449            quantity=payload["quantity"],
    +450            bind_status=enums.ItemBindStatus(payload["bindStatus"]),
    +451            location=enums.ItemLocation(payload["location"]),
    +452            bucket=payload["bucketHash"],
    +453            transfer_status=transfer_status,
    +454            lockable=payload["lockable"],
    +455            state=enums.ItemState(payload["state"]),
    +456            dismantel_permissions=payload["dismantlePermission"],
    +457            is_wrapper=payload["isWrapper"],
    +458            instance_id=instance_id,
    +459            version_number=version_number,
    +460            ornament_id=payload.get("overrideStyleItemHash"),
    +461        )
    +
    -
    -
    -
    - S17_NIGHTMARE_CONTAINMENT = <FireteamActivity.S17_NIGHTMARE_CONTAINMENT: 44> - -
    - - - +

    Deserialize a JSON payload of a singular profile component item.

    -
    -
    -
    - S17_SEVER = <FireteamActivity.S17_SEVER: 45> +
    Parameters
    - -
    - - - + -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    +
    Returns
    -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    + +
    -
    - -
    -
    -
    - -
    -
    @typing.final
    - class - FireteamDate(builtins.int, aiobungie.Enum): +
    +
    + +
    + + def + deserialize_objectives( self, payload: dict[str, typing.Any]) -> aiobungie.crates.records.Objective: - +
    - -
    132@typing.final
    -133class FireteamDate(int, enums.Enum):
    -134    """An enum for fireteam date ranges."""
    -135
    -136    ALL = 0
    -137    NOW = 1
    -138    TODAY = 2
    -139    TWO_DAYS = 3
    -140    THIS_WEEK = 4
    +    
    +            
    463    def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective:
    +464        return records.Objective(
    +465            net=self._net,
    +466            hash=payload["objectiveHash"],
    +467            visible=payload["visible"],
    +468            complete=payload["complete"],
    +469            completion_value=payload["completionValue"],
    +470            progress=payload.get("progress"),
    +471            destination_hash=payload.get("destinationHash"),
    +472            activity_hash=payload.get("activityHash"),
    +473        )
     
    -

    An enum for fireteam date ranges.

    -
    +

    Deserialize a JSON payload of an objective found in a record profile component.

    +
    Parameters
    -
    -
    - ALL = <FireteamDate.ALL: 0> +
      +
    • payload (aiobungie.internal.helpers.JsonObject): +The JSON payload.
    • +
    - -
    - - - +
    Returns
    -
    -
    -
    - NOW = <FireteamDate.NOW: 1> +
      +
    • aiobungie.crates.records.Objective: A record objective object.
    • +
    +
    - -
    - - -
    -
    -
    - TODAY = <FireteamDate.TODAY: 2> +
    + +
    + + def + deserialize_records( self, payload: dict[str, typing.Any], scores: Optional[aiobungie.crates.records.RecordScores] = None, **nodes: int) -> aiobungie.crates.records.Record: + + -
    - - - + +
    475    def deserialize_records(
    +476        self,
    +477        payload: typedefs.JSONObject,
    +478        scores: typing.Optional[records.RecordScores] = None,
    +479        **nodes: int,
    +480    ) -> records.Record:
    +481        objectives: typing.Optional[list[records.Objective]] = None
    +482        interval_objectives: typing.Optional[list[records.Objective]] = None
    +483        record_state: typedefs.IntAnd[records.RecordState]
    +484
    +485        record_state = records.RecordState(payload["state"])
    +486
    +487        if raw_objs := payload.get("objectives"):
    +488            objectives = [self.deserialize_objectives(obj) for obj in raw_objs]
    +489
    +490        if raw_interval_objs := payload.get("intervalObjectives"):
    +491            interval_objectives = [
    +492                self.deserialize_objectives(obj) for obj in raw_interval_objs
    +493            ]
    +494
    +495        return records.Record(
    +496            scores=scores,
    +497            categories_node_hash=nodes.get("categories_hash", undefined.Undefined),
    +498            seals_node_hash=nodes.get("seals_hash", undefined.Undefined),
    +499            state=record_state,
    +500            objectives=objectives,
    +501            interval_objectives=interval_objectives,
    +502            redeemed_count=payload.get("intervalsRedeemedCount", 0),
    +503            completion_times=payload.get("completedCount", None),
    +504            reward_visibility=payload.get("rewardVisibilty", None),
    +505        )
    +
    -
    -
    -
    - TWO_DAYS = <FireteamDate.TWO_DAYS: 3> - -
    - - - +

    Deserialize a JSON object of a profile record component.

    -
    -
    -
    - THIS_WEEK = <FireteamDate.THIS_WEEK: 4> +
    Parameters
    + +
      +
    • payload (aiobungie.internal.helpers.JsonObject): +The JSON object payload
    • +
    • scores (typing.Optional[records.RecordScores]): +The records scores object. +This exists only to keep the signature of aiobungie.crates.CharacterRecord with the record object. +As it will always be None in that object.
    • +
    • **nodes (int): +An int kwargs use to grab the node hashes while deserializing components.
    • +
    - -
    - - - +
    Returns
    -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    +
      +
    • aiobungie.records.Record: A standard implementation of a profile record component.
    • +
    +
    -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    -
    -
    -
    -
    - -
    -
    @typing.final
    - - class - FireteamLanguage(builtins.str, aiobungie.Enum): +
    + +
    + + def + deserialize_character_records( self, payload: dict[str, typing.Any], scores: Optional[aiobungie.crates.records.RecordScores] = None, record_hashes: Optional[list[int]] = None) -> aiobungie.crates.records.CharacterRecord: - +
    - -
    109@typing.final
    -110class FireteamLanguage(str, enums.Enum):
    -111    """An enum for fireteams languages filters."""
    -112
    -113    ALL = ""
    -114    ENGLISH = "en"
    -115    FRENCH = "fr"
    -116    ESPANOL = "es"
    -117    DEUTSCH = "de"
    -118    ITALIAN = "it"
    -119    JAPANESE = "ja"
    -120    PORTUGUESE = "pt-br"
    -121    RUSSIAN = "ru"
    -122    POLISH = "pl"
    -123    KOREAN = "ko"
    -124    # ? China
    -125    ZH_CHT = "zh-cht"
    -126    ZH_CHS = "zh-chs"
    -127
    -128    def __str__(self) -> str:
    -129        return str(self.value)
    +    
    +            
    507    def deserialize_character_records(
    +508        self,
    +509        payload: typedefs.JSONObject,
    +510        scores: typing.Optional[records.RecordScores] = None,
    +511        record_hashes: typing.Optional[list[int]] = None,
    +512    ) -> records.CharacterRecord:
    +513
    +514        record = self.deserialize_records(payload, scores)
    +515        return records.CharacterRecord(
    +516            scores=scores,
    +517            categories_node_hash=record.categories_node_hash,
    +518            seals_node_hash=record.seals_node_hash,
    +519            state=record.state,
    +520            objectives=record.objectives,
    +521            interval_objectives=record.interval_objectives,
    +522            redeemed_count=payload.get("intervalsRedeemedCount", 0),
    +523            completion_times=payload.get("completedCount"),
    +524            reward_visibility=payload.get("rewardVisibilty"),
    +525            record_hashes=record_hashes or [],
    +526        )
     
    -

    An enum for fireteams languages filters.

    -
    +

    Deserialize a JSON object of a profile character record component.

    +

    This almost does the same this as deserialize_records but +has more fields which can only be found in a character record.

    -
    -
    - ALL = <FireteamLanguage.ALL: > +
    Parameters
    - -
    - - - +
      +
    • payload (aiobungie.internal.helpers.JsonObject): +The JSON object payload
    • +
    -
    -
    -
    - ENGLISH = <FireteamLanguage.ENGLISH: en> +
    Returns
    + +
      +
    • aiobungie.records.CharacterRecord: A standard implementation of a profile character record component.
    • +
    +
    - -
    - - -
    -
    -
    - FRENCH = <FireteamLanguage.FRENCH: fr> +
    + +
    + + def + deserialize_character_dye(self, payload: dict[str, typing.Any]) -> aiobungie.crates.character.Dye: + + -
    - - - + +
    528    def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye:
    +529        return character.Dye(
    +530            channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"]
    +531        )
    +
    -
    -
    -
    - ESPANOL = <FireteamLanguage.ESPANOL: es> - -
    - - - +

    Deserialize a JSON payload of a character's dye information.

    -
    -
    -
    - DEUTSCH = <FireteamLanguage.DEUTSCH: de> +
    Parameters
    - -
    - - - + -
    -
    -
    - ITALIAN = <FireteamLanguage.ITALIAN: it> +
    Returns
    + +
      +
    • aiobungie.crates.character.Dye: Information about a character dye object.
    • +
    +
    - -
    - - -
    -
    -
    - JAPANESE = <FireteamLanguage.JAPANESE: ja> +
    + +
    + + def + deserialize_character_customization( self, payload: dict[str, typing.Any]) -> aiobungie.crates.character.CustomizationOptions: + + -
    - - - + +
    533    def deserialize_character_customization(
    +534        self, payload: typedefs.JSONObject
    +535    ) -> character.CustomizationOptions:
    +536        return character.CustomizationOptions(
    +537            personality=payload["personality"],
    +538            face=payload["face"],
    +539            skin_color=payload["skinColor"],
    +540            lip_color=payload["lipColor"],
    +541            eye_color=payload["eyeColor"],
    +542            hair_colors=payload.get("hairColors", []),
    +543            feature_colors=payload.get("featureColors", []),
    +544            decal_color=payload["decalColor"],
    +545            wear_helmet=payload["wearHelmet"],
    +546            hair_index=payload["hairIndex"],
    +547            feature_index=payload["featureIndex"],
    +548            decal_index=payload["decalIndex"],
    +549        )
    +
    -
    -
    -
    - PORTUGUESE = <FireteamLanguage.PORTUGUESE: pt-br> - -
    - - - +

    Deserialize a JSON payload of a character customization information found in character +render data profile component.

    -
    -
    -
    - RUSSIAN = <FireteamLanguage.RUSSIAN: ru> +
    Parameters
    - -
    - - - + -
    -
    -
    - POLISH = <FireteamLanguage.POLISH: pl> +
    Returns
    + +
      +
    • aiobungie.crates.character.CustomizationOptions: Information about a character customs object.
    • +
    +
    - -
    - - -
    -
    -
    - KOREAN = <FireteamLanguage.KOREAN: ko> +
    + +
    + + def + deserialize_character_minimal_equipments( self, payload: dict[str, typing.Any]) -> aiobungie.crates.character.MinimalEquipments: + + -
    - - - + +
    551    def deserialize_character_minimal_equipments(
    +552        self, payload: typedefs.JSONObject
    +553    ) -> character.MinimalEquipments:
    +554        dyes = None
    +555        if raw_dyes := payload.get("dyes"):
    +556            if raw_dyes:
    +557                dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes]
    +558        return character.MinimalEquipments(
    +559            net=self._net, item_hash=payload["itemHash"], dyes=dyes
    +560        )
    +
    -
    -
    -
    - ZH_CHT = <FireteamLanguage.ZH_CHT: zh-cht> - -
    - - - +

    Deserialize a singular JSON peer view of equipment found in character render data profile component.

    -
    -
    -
    - ZH_CHS = <FireteamLanguage.ZH_CHS: zh-chs> +
    Parameters
    - -
    - - - + -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    +
    Returns
    -
    -
    builtins.str
    -
    encode
    -
    replace
    -
    split
    -
    rsplit
    -
    join
    -
    capitalize
    -
    casefold
    -
    title
    -
    center
    -
    count
    -
    expandtabs
    -
    find
    -
    partition
    -
    index
    -
    ljust
    -
    lower
    -
    lstrip
    -
    rfind
    -
    rindex
    -
    rjust
    -
    rstrip
    -
    rpartition
    -
    splitlines
    -
    strip
    -
    swapcase
    -
    translate
    -
    upper
    -
    startswith
    -
    endswith
    -
    removeprefix
    -
    removesuffix
    -
    isascii
    -
    islower
    -
    isupper
    -
    istitle
    -
    isspace
    -
    isdecimal
    -
    isdigit
    -
    isnumeric
    -
    isalpha
    -
    isalnum
    -
    isidentifier
    -
    isprintable
    -
    zfill
    -
    format
    -
    format_map
    -
    maketrans
    +
      +
    • aiobungie.crates.character.MinimalEquipments: A minimal equipment object.
    • +
    +
    -
    - -
    -
    -
    - -
    -
    @typing.final
    - class - FireteamPlatform(builtins.int, aiobungie.Enum): +
    +
    + +
    + + def + deserialize_character_render_data( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.character.RenderedData: - +
    - -
    55@typing.final
    -56class FireteamPlatform(int, enums.Enum):
    -57    """An enum for fireteam related to bungie fireteams.
    -58    This is different from the normal `aiobungie.MembershipType`.
    -59    """
    -60
    -61    ANY = 0
    -62    PSN_NETWORK = 1
    -63    XBOX_LIVE = 2
    -64    STEAM = 4
    -65    STADIA = 5
    +    
    +            
    562    def deserialize_character_render_data(
    +563        self, payload: typedefs.JSONObject, /
    +564    ) -> character.RenderedData:
    +565        return character.RenderedData(
    +566            net=self._net,
    +567            customization=self.deserialize_character_customization(
    +568                payload["customization"]
    +569            ),
    +570            custom_dyes=[
    +571                self.deserialize_character_dye(dye)
    +572                for dye in payload["customDyes"]
    +573                if dye
    +574            ],
    +575            equipment=[
    +576                self.deserialize_character_minimal_equipments(equipment)
    +577                for equipment in payload["peerView"]["equipment"]
    +578            ],
    +579        )
     
    -

    An enum for fireteam related to bungie fireteams. -This is different from the normal aiobungie.MembershipType.

    -
    +

    Deserialize a JSON payload of a profile character render data component.

    +
    Parameters
    -
    -
    - ANY = <FireteamPlatform.ANY: 0> + - -
    - - - +
    Returns
    -
    -
    -
    - PSN_NETWORK = <FireteamPlatform.PSN_NETWORK: 1> + +
    - -
    - - -
    -
    -
    - XBOX_LIVE = <FireteamPlatform.XBOX_LIVE: 2> +
    + +
    + + def + deserialize_available_activity( self, payload: dict[str, typing.Any]) -> aiobungie.crates.activity.AvailableActivity: + + -
    - - - + +
    581    def deserialize_available_activity(
    +582        self, payload: typedefs.JSONObject
    +583    ) -> activity.AvailableActivity:
    +584        return activity.AvailableActivity(
    +585            hash=payload["activityHash"],
    +586            is_new=payload["isNew"],
    +587            is_completed=payload["isCompleted"],
    +588            is_visible=payload["isVisible"],
    +589            display_level=payload.get("displayLevel"),
    +590            recommended_light=payload.get("recommendedLight"),
    +591            difficulty=activity.Difficulty(payload["difficultyTier"]),
    +592            can_join=payload["canJoin"],
    +593            can_lead=payload["canLead"],
    +594        )
    +
    -
    -
    -
    - STEAM = <FireteamPlatform.STEAM: 4> - -
    - - - +

    Deserialize a JSON payload of an available activities.

    -
    -
    -
    - STADIA = <FireteamPlatform.STADIA: 5> +

    This method is used to deserialize an array of aiobungie.crates.CharacterActivity.available_activities.

    - -
    - - - +
    Parameters
    -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    + + +
    Returns
    + + +
    -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    -
    -
    -
    -
    - -
    +
    + +
    - class - Flag(enum.Flag): + def + deserialize_character_activity( self, payload: dict[str, typing.Any]) -> aiobungie.crates.activity.CharacterActivity: - +
    - -
    102class Flag(__enum.Flag):
    -103    """Builtin Python enum flag with extra handlings."""
    -104
    -105    # Needs to type this here for mypy
    -106    _value_: int
    -107
    -108    @property
    -109    def name(self) -> str:  # type: ignore[override]
    -110        if self._name_ is None:
    -111            self._name_ = f"UNKNOWN {self._value_}"
    -112
    -113        return self._name_
    -114
    -115    @property
    -116    def value(self) -> int:  # type: ignore[override]
    -117        return self._value_
    -118
    -119    def __str__(self) -> str:
    -120        return self.name
    -121
    -122    def __repr__(self) -> str:
    -123        return f"<{type(self).__name__}.{self.name}: {self._value_!s}>"
    -124
    -125    def __int__(self) -> int:
    -126        if isinstance(self.value, _ITERABLE):
    -127            raise TypeError(
    -128                f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.",
    -129            )
    -130        return int(self.value)
    -131
    -132    def __or__(self, other: typing.Union[Flag, int]) -> Flag:
    -133        return self.__class__(self._value_ | int(other))
    -134
    -135    def __xor__(self, other: typing.Union[Flag, int]) -> Flag:
    -136        return self.__class__(self._value_ ^ int(other))
    -137
    -138    def __and__(self, other: typing.Union[Flag, int]) -> Flag:
    -139        return self.__class__(other & int(other))
    -140
    -141    def __invert__(self) -> Flag:
    -142        return self.__class__(~self._value_)
    -143
    -144    def __contains__(self, other: typing.Union[Flag, int]) -> bool:
    -145        return self.value & int(other) == int(other)
    +    
    +            
    596    def deserialize_character_activity(
    +597        self, payload: typedefs.JSONObject
    +598    ) -> activity.CharacterActivity:
    +599        current_mode: typing.Optional[enums.GameMode] = None
    +600        if raw_current_mode := payload.get("currentActivityModeType"):
    +601            current_mode = enums.GameMode(raw_current_mode)
    +602
    +603        current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None
    +604        if raw_current_modes := payload.get("currentActivityModeTypes"):
    +605            current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes]
    +606
    +607        return activity.CharacterActivity(
    +608            date_started=time.clean_date(payload["dateActivityStarted"]),
    +609            current_hash=payload["currentActivityHash"],
    +610            current_mode_hash=payload["currentActivityModeHash"],
    +611            current_mode=current_mode,
    +612            current_mode_hashes=payload.get("currentActivityModeHashes"),
    +613            current_mode_types=current_mode_types,
    +614            current_playlist_hash=payload.get("currentPlaylistActivityHash"),
    +615            last_story_hash=payload["lastCompletedStoryHash"],
    +616            available_activities=[
    +617                self.deserialize_available_activity(activity_)
    +618                for activity_ in payload["availableActivities"]
    +619            ],
    +620        )
     
    -

    Builtin Python enum flag with extra handlings.

    +

    Deserialize a JSON payload of character activity profile component.

    + +
    Parameters
    + + + +
    Returns
    + +
    -
    -
    - name: str +
    +
    + +
    + + def + deserialize_profile_items( self, payload: dict[str, typing.Any], /) -> list[aiobungie.crates.profile.ProfileItemImpl]: + + -
    - - - + +
    622    def deserialize_profile_items(
    +623        self, payload: typedefs.JSONObject, /
    +624    ) -> list[profile.ProfileItemImpl]:
    +625        return [self.deserialize_profile_item(item) for item in payload["items"]]
    +
    + + +

    Deserialize a JSON payload of profile items component information.

    + +

    This may deserialize profileInventories or profileCurrencies or any +other alternatives.

    + +
    Parameters
    + + + +
    Returns
    + + +
    +
    -
    -
    - value: int +
    + +
    + + def + deserialize_progressions( self, payload: dict[str, typing.Any]) -> aiobungie.crates.progressions.Progression: + + -
    - - + +
    668    def deserialize_progressions(
    +669        self, payload: typedefs.JSONObject
    +670    ) -> progressions.Progression:
    +671        return progressions.Progression(
    +672            hash=int(payload["progressionHash"]),
    +673            level=int(payload["level"]),
    +674            cap=int(payload["levelCap"]),
    +675            daily_limit=int(payload["dailyLimit"]),
    +676            weekly_limit=int(payload["weeklyLimit"]),
    +677            current_progress=int(payload["currentProgress"]),
    +678            daily_progress=int(payload["dailyProgress"]),
    +679            needed=int(payload["progressToNextLevel"]),
    +680            next_level=int(payload["nextLevelAt"]),
    +681        )
    +
    + +
    -
    -
    - -
    +
    + +
    - class - FlatIterator(typing.Generic[~Item]): - - - -
    - -
     45class FlatIterator(typing.Generic[Item]):
    - 46    """A Flat, In-Memory iterator for sequenced based data.
    - 47
    - 48    Example
    - 49    -------
    - 50    ```py
    - 51    iterator = FlatIterator([1, 2, 3])
    - 52
    - 53    # Map the results.
    - 54    for item in iterator.map(lambda item: item * 2):
    - 55        print(item)
    - 56    # 2
    - 57    # 4
    - 58
    - 59    # Indexing is also supported.
    - 60    print(iterator[0])
    - 61    # 1
    - 62
    - 63    # Normal iteration.
    - 64    for item in iterator:
    - 65        print(item)
    - 66    # 1
    - 67    # 2
    - 68    # 3
    - 69
    - 70    # Union two iterators.
    - 71    iterator2 = FlatIterator([4, 5, 6])
    - 72    final = iterator | iterator2
    - 73    # <FlatIterator([1, 2, 3, 4, 5, 6])>
    - 74    ```
    - 75
    - 76    Parameters
    - 77    ----------
    - 78    items: `collections.Iterable[Item]`
    - 79        The items to iterate over.
    - 80    """
    - 81
    - 82    __slots__ = ("_items",)
    - 83
    - 84    def __init__(self, items: collections.Iterable[Item]) -> None:
    - 85        self._items = iter(items)
    - 86
    - 87    @typing.overload
    - 88    def collect(self) -> list[Item]:
    - 89        ...
    - 90
    - 91    @typing.overload
    - 92    def collect(self, casting: _B) -> list[_B]:
    - 93        ...
    - 94
    - 95    def collect(
    - 96        self, casting: typing.Optional[_B] = None
    - 97    ) -> typing.Union[list[Item], list[_B]]:
    - 98        """Collects all items in the iterator into a list and cast them into an object if provided.
    - 99
    -100        Example
    -101        -------
    -102        >>> iterator = FlatIterator([1, 2, 3])
    -103        >>> iterator.collect(casting=str)
    -104        ["1", "2", "3"]
    -105
    -106        Parameters
    -107        ----------
    -108        casting: `T | None`
    -109            The type to cast the items to. If `None` is provided, the items will be returned as is.
    -110
    -111        Raises
    -112        ------
    -113        `StopIteration`
    -114            If no elements are left in the iterator.
    -115        """
    -116        if casting is not None:
    -117            return typing.cast(list[_B], list(map(casting, self._items)))
    -118
    -119        return list(self._items)
    -120
    -121    def next(self) -> Item:
    -122        """Returns the next item in the iterator.
    -123
    -124        Example
    -125        -------
    -126        ```py
    -127        iterator = FlatIterator(["1", "2", "3"])
    -128        item = iterator.next()
    -129        assert item == "1"
    -130        item = iterator.next()
    -131        assert item == "2"
    -132        ```
    -133
    -134        Raises
    -135        ------
    -136        `StopIteration`
    -137            If no elements are left in the iterator.
    -138        """
    -139        try:
    -140            return self.__next__()
    -141        except StopIteration:
    -142            self._ok()
    -143
    -144    def map(
    -145        self, predicate: collections.Callable[[Item], OtherItem]
    -146    ) -> FlatIterator[OtherItem]:
    -147        """Maps each item in the iterator to its predicated value.
    -148
    -149        Example
    -150        -------
    -151        ```py
    -152        iterator = FlatIterator(["1", "2", "3"]).map(lambda value: int(value))
    -153        print(iterator)
    -154        # <FlatIterator([1, 2, 3])>
    -155        ```
    -156
    -157        Parameters
    -158        ----------
    -159        predicate: `collections.Callable[[Item], OtherItem]`
    -160            The function to map each item in the iterator to its predicated value.
    -161
    -162        Returns
    -163        -------
    -164        `FlatIterator[OtherItem]`
    -165            The mapped iterator.
    -166
    -167        Raises
    -168        ------
    -169        `StopIteration`
    -170            If no elements are left in the iterator.
    -171        """
    -172        return FlatIterator(map(predicate, self._items))
    -173
    -174    def take(self, n: int) -> FlatIterator[Item]:
    -175        """Take the first number of items until the number of items are yielded or
    -176        the end of the iterator is reached.
    -177
    -178        Example
    -179        -------
    -180        ```py
    -181        iterator = FlatIterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
    -182        print(iterator.take(2))
    -183        # <FlatIterator([GameMode.RAID, GameMode.STRIKE])>
    -184        ```
    -185
    -186        Parameters
    -187        ----------
    -188        n: `int`
    -189            The number of items to take.
    -190
    -191        Raises
    -192        ------
    -193        `StopIteration`
    -194            If no elements are left in the iterator.
    -195        """
    -196        return FlatIterator(itertools.islice(self._items, n))
    -197
    -198    def take_while(
    -199        self, predicate: collections.Callable[[Item], bool]
    -200    ) -> FlatIterator[Item]:
    -201        """Yields items from the iterator while predicate returns `True`.
    -202
    -203        Example
    -204        -------
    -205        ```py
    -206        iterator = FlatIterator([STEAM, XBOX, STADIA])
    -207        print(iterator.take_while(lambda platform: platform is not XBOX))
    -208        # <FlatIterator([STEAM])>
    -209        ```
    -210
    -211        Parameters
    -212        ----------
    -213        predicate: `collections.Callable[[Item], bool]`
    -214            The function to predicate each item in the iterator.
    -215
    -216        Raises
    -217        ------
    -218        `StopIteration`
    -219            If no elements are left in the iterator.
    -220        """
    -221        return FlatIterator(itertools.takewhile(predicate, self._items))
    -222
    -223    def drop_while(
    -224        self, predicate: collections.Callable[[Item], bool]
    -225    ) -> FlatIterator[Item]:
    -226        """Yields items from the iterator while predicate returns `False`.
    -227
    -228        Example
    -229        -------
    -230        ```py
    -231        iterator = FlatIterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
    -232        print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
    -233        # <FlatIterator([DestinyMembership(name="Bob")])>
    -234        ```
    -235
    -236        Parameters
    -237        ----------
    -238        predicate: `collections.Callable[[Item], bool]`
    -239            The function to predicate each item in the iterator.
    -240
    -241        Raises
    -242        ------
    -243        `StopIteration`
    -244            If no elements are left in the iterator.
    -245        """
    -246        return FlatIterator(itertools.dropwhile(predicate, self._items))
    -247
    -248    def filter(
    -249        self, predicate: collections.Callable[[Item], bool]
    -250    ) -> FlatIterator[Item]:
    -251        """Filters the iterator to only yield items that match the predicate.
    -252
    -253        Example
    -254        -------
    -255        ```py
    -256        names = FlatIterator(["Jim", "Bob", "Mike", "Jess"])
    -257        print(names.filter(lambda n: n != "Jim"))
    -258        # <FlatIterator(["Bob", "Mike", "Jess"])>
    -259        ```
    -260        """
    -261        return FlatIterator(filter(predicate, self._items))
    -262
    -263    def skip(self, n: int) -> FlatIterator[Item]:
    -264        """Skips the first number of items in the iterator.
    -265
    -266        Example
    -267        -------
    -268        ```py
    -269        iterator = FlatIterator([STEAM, XBOX, STADIA])
    -270        print(iterator.skip(1))
    -271        # <FlatIterator([XBOX, STADIA])>
    -272        ```
    -273        """
    -274        return FlatIterator(itertools.islice(self._items, n, None))
    -275
    -276    def discard(
    -277        self, predicate: collections.Callable[[Item], bool]
    -278    ) -> FlatIterator[Item]:
    -279        """Discards all elements in the iterator for which the predicate function returns true.
    -280
    -281        Example
    -282        -------
    -283        ```py
    -284        iterator = FlatIterator(['A', 'B', 'C'])
    -285        print(iterator.discard(lambda x: x == 'B'))
    -286        # <FlatIterator(['A', 'C'])>
    -287        ```
    -288
    -289        Parameters
    -290        ----------
    -291        predicate: `collections.Callable[[Item], bool]`
    -292            The function to test each item in the iterator.
    -293
    -294        Raises
    -295        ------
    -296        `StopIteration`
    -297            If no elements are left in the iterator.
    -298        """
    -299        return FlatIterator(filter(lambda x: not predicate(x), self._items))
    -300
    -301    def zip(
    -302        self, other: FlatIterator[OtherItem]
    -303    ) -> FlatIterator[tuple[Item, OtherItem]]:
    -304        """Zips the iterator with another iterable.
    -305
    -306        Example
    -307        -------
    -308        ```py
    -309        iterator = FlatIterator([1, 3, 5])
    -310        other = FlatIterator([2, 4, 6])
    -311        for item, other_item in iterator.zip(other):
    -312            print(item, other_item)
    -313        # <FlatIterator([(1, 2), (3, 4), (5, 6)])>
    -314        ```
    -315
    -316        Parameters
    -317        ----------
    -318        other: `FlatIterator[OtherItem]`
    -319            The iterable to zip with.
    -320
    -321        Raises
    -322        ------
    -323        `StopIteration`
    -324            If no elements are left in the iterator.
    -325        """
    -326        return FlatIterator(zip(self._items, other))
    -327
    -328    def all(self, predicate: collections.Callable[[Item], bool]) -> bool:
    -329        """`True` if all items in the iterator match the predicate.
    -330
    -331        Example
    -332        -------
    -333        ```py
    -334        iterator = FlatIterator([1, 2, 3])
    -335        while iterator.all(lambda item: isinstance(item, int)):
    -336            print("Still all integers")
    -337            continue
    -338        # Still all integers
    -339        ```
    -340
    -341        Parameters
    -342        ----------
    -343        predicate: `collections.Callable[[Item], bool]`
    -344            The function to test each item in the iterator.
    -345
    -346        Raises
    -347        ------
    -348        `StopIteration`
    -349            If no elements are left in the iterator.
    -350        """
    -351        return all(predicate(item) for item in self)
    -352
    -353    def any(self, predicate: collections.Callable[[Item], bool]) -> bool:
    -354        """`True` if any items in the iterator match the predicate.
    -355
    -356        Example
    -357        -------
    -358        ```py
    -359        iterator = FlatIterator([1, 2, 3])
    -360        if iterator.any(lambda item: isinstance(item, int)):
    -361            print("At least one item is an int.")
    -362        # At least one item is an int.
    -363        ```
    -364
    -365        Parameters
    -366        ----------
    -367        predicate: `collections.Callable[[Item], bool]`
    -368            The function to test each item in the iterator.
    -369
    -370        Raises
    -371        ------
    -372        `StopIteration`
    -373            If no elements are left in the iterator.
    -374        """
    -375        return any(predicate(item) for item in self)
    -376
    -377    def sort(
    -378        self,
    -379        *,
    -380        key: collections.Callable[[Item], typeshed.SupportsRichComparison],
    -381        reverse: bool = False,
    -382    ) -> FlatIterator[Item]:
    -383        """Sorts the iterator.
    -384
    -385        Example
    -386        -------
    -387        ```py
    -388        iterator = FlatIterator([3, 1, 6, 7])
    -389        print(iterator.sort(key=lambda item: item))
    -390        # <FlatIterator([1, 3, 6, 7])>
    -391        ```
    -392
    -393        Parameters
    -394        ----------
    -395        key: `collections.Callable[[Item], Any]`
    -396            The function to sort by.
    -397        reverse: `bool`
    -398            Whether to reverse the sort.
    -399
    -400        Raises
    -401        ------
    -402        `StopIteration`
    -403            If no elements are left in the iterator.
    -404        """
    -405        return FlatIterator(sorted(self._items, key=key, reverse=reverse))
    -406
    -407    def first(self) -> Item:
    -408        """Returns the first item in the iterator.
    -409
    -410        Example
    -411        -------
    -412        ```py
    -413        iterator = FlatIterator([3, 1, 6, 7])
    -414        print(iterator.first())
    -415        3
    -416        ```
    -417
    -418        Raises
    -419        ------
    -420        `StopIteration`
    -421            If no elements are left in the iterator.
    -422        """
    -423        return self.take(1).next()
    -424
    -425    def reversed(self) -> FlatIterator[Item]:
    -426        """Returns a new iterator that yields the items in the iterator in reverse order.
    -427
    -428        Example
    -429        -------
    -430        ```py
    -431        iterator = FlatIterator([3, 1, 6, 7])
    -432        print(iterator.reversed())
    -433        # <FlatIterator([7, 6, 1, 3])>
    -434        ```
    -435
    -436        Raises
    -437        ------
    -438        `StopIteration`
    -439            If no elements are left in the iterator.
    -440        """
    -441        return FlatIterator(reversed(self.collect()))
    -442
    -443    def count(self) -> int:
    -444        """Returns the number of items in the iterator.
    -445
    -446        Example
    -447        -------
    -448        ```py
    -449        iterator = FlatIterator([3, 1, 6, 7])
    -450        print(iterator.count())
    -451        4
    -452        ```
    -453        """
    -454        count = 0
    -455        for _ in self:
    -456            count += 1
    -457
    -458        return count
    -459
    -460    def union(self, other: FlatIterator[Item]) -> FlatIterator[Item]:
    -461        """Returns a new iterator that yields all items from both iterators.
    -462
    -463        Example
    -464        -------
    -465        ```py
    -466        iterator = FlatIterator([1, 2, 3])
    -467        other = FlatIterator([4, 5, 6])
    -468        print(iterator.union(other))
    -469        # <FlatIterator([1, 2, 3, 4, 5, 6])>
    -470        ```
    -471
    -472        Parameters
    -473        ----------
    -474        other: `FlatIterator[Item]`
    -475            The iterable to union with.
    -476
    -477        Raises
    -478        ------
    -479        `StopIteration`
    -480            If no elements are left in the iterator.
    -481        """
    -482        return FlatIterator(itertools.chain(self._items, other))
    -483
    -484    def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None:
    -485        """Calls the function on each item in the iterator.
    -486
    -487        Example
    -488        -------
    -489        ```py
    -490        iterator = FlatIterator([1, 2, 3])
    -491        iterator.for_each(lambda item: print(item))
    -492        # 1
    -493        # 2
    -494        # 3
    -495        ```
    -496
    -497        Parameters
    -498        ----------
    -499        func: `typeshed.Callable[[Item], None]`
    -500            The function to call on each item in the iterator.
    -501        """
    -502        for item in self:
    -503            func(item)
    -504
    -505    async def async_for_each(
    -506        self,
    -507        func: collections.Callable[[Item], collections.Coroutine[None, None, None]],
    -508    ) -> None:
    -509        """Calls the async function on each item in the iterator concurrently.
    -510
    -511        Example
    -512        -------
    -513        ```py
    -514        async def signup(username: str) -> None:
    -515            async with aiohttp.request('POST', '...') as r:
    -516                # Actual logic.
    -517                ...
    -518
    -519        async def main():
    -520            users = aiobungie.into_iter(["user_danny", "user_jojo"])
    -521            await users.async_for_each(lambda username: signup(username))
    -522        ```
    -523
    -524        Parameters
    -525        ----------
    -526        func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]`
    -527            The async function to call on each item in the iterator.
    -528        """
    -529        await _helpers.awaits(*(func(item) for item in self))
    -530
    -531    def enumerate(self, *, start: int = 0) -> FlatIterator[tuple[int, Item]]:
    -532        """Returns a new iterator that yields tuples of the index and item.
    -533
    -534        Example
    -535        -------
    -536        ```py
    -537        iterator = FlatIterator([1, 2, 3])
    -538        for index, item in iterator.enumerate():
    -539            print(index, item)
    -540        # 0 1
    -541        # 1 2
    -542        # 2 3
    -543        ```
    -544
    -545        Raises
    -546        ------
    -547        `StopIteration`
    -548            If no elements are left in the iterator.
    -549        """
    -550        return FlatIterator(enumerate(self._items, start=start))
    -551
    -552    def _ok(self) -> typing.NoReturn:
    -553        raise StopIteration("No more items in the iterator.") from None
    -554
    -555    def __getitem__(self, index: int) -> Item:
    -556        try:
    -557            return self.skip(index).first()
    -558        except IndexError:
    -559            self._ok()
    -560
    -561    def __or__(self, other: FlatIterator[Item]) -> FlatIterator[Item]:
    -562        return self.union(other)
    -563
    -564    # This is a never.
    -565    def __setitem__(self) -> typing.NoReturn:
    -566        raise TypeError(
    -567            f"{type(self).__name__} doesn't support item assignment."
    -568        ) from None
    -569
    -570    def __repr__(self) -> str:
    -571        return f'<{self.__class__.__name__}({", ".join([str(item) for item in self])})>'
    -572
    -573    def __len__(self) -> int:
    -574        return self.count()
    -575
    -576    def __iter__(self) -> FlatIterator[Item]:
    -577        return self
    -578
    -579    def __next__(self) -> Item:
    -580        try:
    -581            item = next(self._items)
    -582        except StopIteration:
    -583            self._ok()
    -584
    -585        return item
    +        def
    +        deserialize_milestone(	self,	payload: dict[str, typing.Any]) -> aiobungie.crates.milestones.Milestone:
    +
    +                
    +
    +    
    + +
    769    def deserialize_milestone(
    +770        self, payload: typedefs.JSONObject
    +771    ) -> milestones.Milestone:
    +772        start_date: typing.Optional[datetime.datetime] = None
    +773        if raw_start_date := payload.get("startDate"):
    +774            start_date = time.clean_date(raw_start_date)
    +775
    +776        end_date: typing.Optional[datetime.datetime] = None
    +777        if raw_end_date := payload.get("endDate"):
    +778            end_date = time.clean_date(raw_end_date)
    +779
    +780        rewards: typing.Optional[
    +781            collections.Collection[milestones.MilestoneReward]
    +782        ] = None
    +783        if raw_rewards := payload.get("rewards"):
    +784            rewards = [
    +785                self._deserialize_milestone_rewards(reward) for reward in raw_rewards
    +786            ]
    +787
    +788        activities: typing.Optional[
    +789            collections.Sequence[milestones.MilestoneActivity]
    +790        ] = None
    +791        if raw_activities := payload.get("activities"):
    +792            activities = [
    +793                self._deserialize_milestone_activity(active)
    +794                for active in raw_activities
    +795            ]
    +796
    +797        quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None
    +798        if raw_quests := payload.get("availableQuests"):
    +799            quests = [
    +800                self._deserialize_milestone_available_quest(quest)
    +801                for quest in raw_quests
    +802            ]
    +803
    +804        vendors: typing.Optional[
    +805            collections.Sequence[milestones.MilestoneVendor]
    +806        ] = None
    +807        if raw_vendors := payload.get("vendors"):
    +808            vendors = [
    +809                milestones.MilestoneVendor(
    +810                    vendor_hash=vendor["vendorHash"],
    +811                    preview_itemhash=vendor.get("previewItemHash"),
    +812                )
    +813                for vendor in raw_vendors
    +814            ]
    +815
    +816        return milestones.Milestone(
    +817            hash=payload["milestoneHash"],
    +818            start_date=start_date,
    +819            end_date=end_date,
    +820            order=payload["order"],
    +821            rewards=rewards,
    +822            available_quests=quests,
    +823            activities=activities,
    +824            vendors=vendors,
    +825        )
     
    -

    A Flat, In-Memory iterator for sequenced based data.

    + -
    Example
    +
    +
    + +
    + + def + deserialize_characters( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.character.Character]: -
    iterator = FlatIterator([1, 2, 3])
    +                
     
    -# Map the results.
    -for item in iterator.map(lambda item: item * 2):
    -    print(item)
    -# 2
    -# 4
    +    
    + +
    842    def deserialize_characters(
    +843        self, payload: typedefs.JSONObject
    +844    ) -> collections.Mapping[int, character.Character]:
    +845        return {
    +846            int(char_id): self._set_character_attrs(char)
    +847            for char_id, char in payload["data"].items()
    +848        }
    +
    -# Indexing is also supported. -print(iterator[0]) -# 1 -# Normal iteration. -for item in iterator: - print(item) -# 1 -# 2 -# 3 + -# Union two iterators. -iterator2 = FlatIterator([4, 5, 6]) -final = iterator | iterator2 -# <FlatIterator([1, 2, 3, 4, 5, 6])> -
    +
    +
    + +
    + + def + deserialize_character( self, payload: dict[str, typing.Any]) -> aiobungie.crates.character.Character: -
    Parameters
    + + +
    + +
    850    def deserialize_character(
    +851        self, payload: typedefs.JSONObject
    +852    ) -> character.Character:
    +853        return self._set_character_attrs(payload)
    +
    -
      -
    • items (collections.Iterable[Item]): -The items to iterate over.
    • -
    -
    + -
    - +
    +
    +
    - FlatIterator(items: collections.abc.Iterable[~Item]) + def + deserialize_character_equipments( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, collections.abc.Sequence[aiobungie.crates.profile.ProfileItemImpl]]: - +
    - -
    84    def __init__(self, items: collections.Iterable[Item]) -> None:
    -85        self._items = iter(items)
    +    
    +            
    855    def deserialize_character_equipments(
    +856        self, payload: typedefs.JSONObject
    +857    ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]:
    +858        return {
    +859            int(char_id): self.deserialize_profile_items(item)
    +860            for char_id, item in payload["data"].items()
    +861        }
     
    -
    - +
    +
    def - collect( self, casting: 'typing.Optional[_B]' = None) -> 'typing.Union[list[Item], list[_B]]': - - - -
    - -
     95    def collect(
    - 96        self, casting: typing.Optional[_B] = None
    - 97    ) -> typing.Union[list[Item], list[_B]]:
    - 98        """Collects all items in the iterator into a list and cast them into an object if provided.
    - 99
    -100        Example
    -101        -------
    -102        >>> iterator = FlatIterator([1, 2, 3])
    -103        >>> iterator.collect(casting=str)
    -104        ["1", "2", "3"]
    -105
    -106        Parameters
    -107        ----------
    -108        casting: `T | None`
    -109            The type to cast the items to. If `None` is provided, the items will be returned as is.
    -110
    -111        Raises
    -112        ------
    -113        `StopIteration`
    -114            If no elements are left in the iterator.
    -115        """
    -116        if casting is not None:
    -117            return typing.cast(list[_B], list(map(casting, self._items)))
    -118
    -119        return list(self._items)
    -
    + deserialize_character_activities( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.activity.CharacterActivity]: + -

    Collects all items in the iterator into a list and cast them into an object if provided.

    +
    + +
    863    def deserialize_character_activities(
    +864        self, payload: typedefs.JSONObject
    +865    ) -> collections.Mapping[int, activity.CharacterActivity]:
    +866        return {
    +867            int(char_id): self.deserialize_character_activity(data)
    +868            for char_id, data in payload["data"].items()
    +869        }
    +
    -
    Example
    -
    >>> iterator = FlatIterator([1, 2, 3])
    ->>> iterator.collect(casting=str)
    -["1", "2", "3"]
    -
    + -
    Parameters
    +
    +
    + +
    + + def + deserialize_characters_render_data( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.character.RenderedData]: -
      -
    • casting (T | None): -The type to cast the items to. If None is provided, the items will be returned as is.
    • -
    + -
    Raises
    +
    + +
    871    def deserialize_characters_render_data(
    +872        self, payload: typedefs.JSONObject
    +873    ) -> collections.Mapping[int, character.RenderedData]:
    +874        return {
    +875            int(char_id): self.deserialize_character_render_data(data)
    +876            for char_id, data in payload["data"].items()
    +877        }
    +
    -
      -
    • StopIteration: If no elements are left in the iterator.
    • -
    -
    +
    -
    - +
    +
    def - next(self) -> ~Item: + deserialize_character_progressions( self, payload: dict[str, typing.Any]) -> aiobungie.crates.character.CharacterProgression: + + - - -
    - -
    121    def next(self) -> Item:
    -122        """Returns the next item in the iterator.
    -123
    -124        Example
    -125        -------
    -126        ```py
    -127        iterator = FlatIterator(["1", "2", "3"])
    -128        item = iterator.next()
    -129        assert item == "1"
    -130        item = iterator.next()
    -131        assert item == "2"
    -132        ```
    -133
    -134        Raises
    -135        ------
    -136        `StopIteration`
    -137            If no elements are left in the iterator.
    -138        """
    -139        try:
    -140            return self.__next__()
    -141        except StopIteration:
    -142            self._ok()
    +    
    + +
    879    def deserialize_character_progressions(
    +880        self, payload: typedefs.JSONObject
    +881    ) -> character.CharacterProgression:
    +882        progressions_ = {
    +883            int(prog_id): self.deserialize_progressions(prog)
    +884            for prog_id, prog in payload["progressions"].items()
    +885        }
    +886
    +887        factions = {
    +888            int(faction_id): self._deserialize_factions(faction)
    +889            for faction_id, faction in payload["factions"].items()
    +890        }
    +891
    +892        milestones_ = {
    +893            int(milestone_hash): self.deserialize_milestone(milestone)
    +894            for milestone_hash, milestone in payload["milestones"].items()
    +895        }
    +896
    +897        uninstanced_item_objectives = {
    +898            int(item_hash): [self.deserialize_objectives(ins) for ins in obj]
    +899            for item_hash, obj in payload["uninstancedItemObjectives"].items()
    +900        }
    +901
    +902        artifact = payload["seasonalArtifact"]
    +903        seasonal_artifact = season.CharacterScopedArtifact(
    +904            hash=artifact["artifactHash"],
    +905            points_used=artifact["pointsUsed"],
    +906            reset_count=artifact["resetCount"],
    +907            tiers=[
    +908                self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"]
    +909            ],
    +910        )
    +911        checklists = payload["checklists"]
    +912
    +913        return character.CharacterProgression(
    +914            progressions=progressions_,
    +915            factions=factions,
    +916            checklists=checklists,
    +917            milestones=milestones_,
    +918            seasonal_artifact=seasonal_artifact,
    +919            uninstanced_item_objectives=uninstanced_item_objectives,
    +920        )
     
    -

    Returns the next item in the iterator.

    + -
    Example
    +
    +
    + +
    + + def + deserialize_character_progressions_mapping( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.character.CharacterProgression]: -
    iterator = FlatIterator(["1", "2", "3"])
    -item = iterator.next()
    -assert item == "1"
    -item = iterator.next()
    -assert item == "2"
    -
    + -
    Raises
    +
    + +
    922    def deserialize_character_progressions_mapping(
    +923        self, payload: typedefs.JSONObject
    +924    ) -> collections.Mapping[int, character.CharacterProgression]:
    +925        character_progressions: collections.Mapping[
    +926            int, character.CharacterProgression
    +927        ] = {}
    +928        for char_id, data in payload["data"].items():
    +929            # A little hack to stop mypy complaining about Mapping <-> dict
    +930            character_progressions[int(char_id)] = self.deserialize_character_progressions(data)  # type: ignore[index]
    +931        return character_progressions
    +
    -
      -
    • StopIteration: If no elements are left in the iterator.
    • -
    -
    +
    -
    - +
    +
    def - map( self, predicate: 'collections.Callable[[Item], OtherItem]') -> 'FlatIterator[OtherItem]': - - - -
    - -
    144    def map(
    -145        self, predicate: collections.Callable[[Item], OtherItem]
    -146    ) -> FlatIterator[OtherItem]:
    -147        """Maps each item in the iterator to its predicated value.
    -148
    -149        Example
    -150        -------
    -151        ```py
    -152        iterator = FlatIterator(["1", "2", "3"]).map(lambda value: int(value))
    -153        print(iterator)
    -154        # <FlatIterator([1, 2, 3])>
    -155        ```
    -156
    -157        Parameters
    -158        ----------
    -159        predicate: `collections.Callable[[Item], OtherItem]`
    -160            The function to map each item in the iterator to its predicated value.
    -161
    -162        Returns
    -163        -------
    -164        `FlatIterator[OtherItem]`
    -165            The mapped iterator.
    -166
    -167        Raises
    -168        ------
    -169        `StopIteration`
    -170            If no elements are left in the iterator.
    -171        """
    -172        return FlatIterator(map(predicate, self._items))
    +        deserialize_characters_records(	self,	payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.records.CharacterRecord]:
    +
    +                
    +
    +    
    + +
    933    def deserialize_characters_records(
    +934        self,
    +935        payload: typedefs.JSONObject,
    +936    ) -> collections.Mapping[int, records.CharacterRecord]:
    +937
    +938        return {
    +939            int(rec_id): self.deserialize_character_records(
    +940                rec, record_hashes=payload.get("featuredRecordHashes")
    +941            )
    +942            for rec_id, rec in payload["records"].items()
    +943        }
     
    -

    Maps each item in the iterator to its predicated value.

    + -
    Example
    +
    +
    + +
    + + def + deserialize_profile_records( self, payload: dict[str, typing.Any]) -> collections.abc.Mapping[int, aiobungie.crates.records.Record]: -
    iterator = FlatIterator(["1", "2", "3"]).map(lambda value: int(value))
    -print(iterator)
    -# <FlatIterator([1, 2, 3])>
    -
    + -
    Parameters
    +
    + +
    945    def deserialize_profile_records(
    +946        self, payload: typedefs.JSONObject
    +947    ) -> collections.Mapping[int, records.Record]:
    +948        raw_profile_records = payload["data"]
    +949        scores = records.RecordScores(
    +950            current_score=raw_profile_records["score"],
    +951            legacy_score=raw_profile_records["legacyScore"],
    +952            lifetime_score=raw_profile_records["lifetimeScore"],
    +953        )
    +954        return {
    +955            int(record_id): self.deserialize_records(
    +956                record,
    +957                scores,
    +958                categories_hash=raw_profile_records["recordCategoriesRootNodeHash"],
    +959                seals_hash=raw_profile_records["recordSealsRootNodeHash"],
    +960            )
    +961            for record_id, record in raw_profile_records["records"].items()
    +962        }
    +
    -
      -
    • predicate (collections.Callable[[Item], OtherItem]): -The function to map each item in the iterator to its predicated value.
    • -
    -
    Returns
    + -
      -
    • FlatIterator[OtherItem]: The mapped iterator.
    • -
    +
    +
    + +
    + + def + deserialize_craftables_component( self, payload: dict[str, typing.Any]) -> aiobungie.crates.components.CraftablesComponent: -
    Raises
    + + +
    + +
     999    def deserialize_craftables_component(
    +1000        self, payload: typedefs.JSONObject
    +1001    ) -> components.CraftablesComponent:
    +1002        return components.CraftablesComponent(
    +1003            net=self._net,
    +1004            craftables={
    +1005                int(item_id): self._deserialize_craftable_item(item)
    +1006                for item_id, item in payload["craftables"].items()
    +1007                if item is not None
    +1008            },
    +1009            crafting_root_node_hash=payload["craftingRootNodeHash"],
    +1010        )
    +
    -
      -
    • StopIteration: If no elements are left in the iterator.
    • -
    -
    +
    -
    - +
    +
    def - take(self, n: int) -> aiobungie.FlatIterator[~Item]: - - - -
    - -
    174    def take(self, n: int) -> FlatIterator[Item]:
    -175        """Take the first number of items until the number of items are yielded or
    -176        the end of the iterator is reached.
    -177
    -178        Example
    -179        -------
    -180        ```py
    -181        iterator = FlatIterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
    -182        print(iterator.take(2))
    -183        # <FlatIterator([GameMode.RAID, GameMode.STRIKE])>
    -184        ```
    -185
    -186        Parameters
    -187        ----------
    -188        n: `int`
    -189            The number of items to take.
    -190
    -191        Raises
    -192        ------
    -193        `StopIteration`
    -194            If no elements are left in the iterator.
    -195        """
    -196        return FlatIterator(itertools.islice(self._items, n))
    -
    + deserialize_components( self, payload: dict[str, typing.Any]) -> aiobungie.crates.components.Component: + -

    Take the first number of items until the number of items are yielded or -the end of the iterator is reached.

    +
    + +
    1012    def deserialize_components(  # noqa: C901 Too complex.
    +1013        self, payload: typedefs.JSONObject
    +1014    ) -> components.Component:
    +1015
    +1016        profile_: typing.Optional[profile.Profile] = None
    +1017        if raw_profile := payload.get("profile"):
    +1018            profile_ = self.deserialize_profile(raw_profile)
    +1019
    +1020        profile_progression: typing.Optional[profile.ProfileProgression] = None
    +1021        if raw_profile_progression := payload.get("profileProgression"):
    +1022            profile_progression = self.deserialize_profile_progression(
    +1023                raw_profile_progression
    +1024            )
    +1025
    +1026        profile_currencies: typing.Optional[
    +1027            collections.Sequence[profile.ProfileItemImpl]
    +1028        ] = None
    +1029        if raw_profile_currencies := payload.get("profileCurrencies"):
    +1030            if "data" in raw_profile_currencies:
    +1031                profile_currencies = self.deserialize_profile_items(
    +1032                    raw_profile_currencies["data"]
    +1033                )
    +1034
    +1035        profile_inventories: typing.Optional[
    +1036            collections.Sequence[profile.ProfileItemImpl]
    +1037        ] = None
    +1038        if raw_profile_inventories := payload.get("profileInventory"):
    +1039            if "data" in raw_profile_inventories:
    +1040                profile_inventories = self.deserialize_profile_items(
    +1041                    raw_profile_inventories["data"]
    +1042                )
    +1043
    +1044        profile_records: typing.Optional[
    +1045            collections.Mapping[int, records.Record]
    +1046        ] = None
    +1047
    +1048        if raw_profile_records_ := payload.get("profileRecords"):
    +1049            profile_records = self.deserialize_profile_records(raw_profile_records_)
    +1050
    +1051        characters: typing.Optional[typing.Mapping[int, character.Character]] = None
    +1052        if raw_characters := payload.get("characters"):
    +1053            characters = self.deserialize_characters(raw_characters)
    +1054
    +1055        character_records: typing.Optional[
    +1056            collections.Mapping[int, records.CharacterRecord]
    +1057        ] = None
    +1058
    +1059        if raw_character_records := payload.get("characterRecords"):
    +1060            # Had to do it in two steps..
    +1061            to_update: typedefs.JSONObject = {}
    +1062            for _, data in raw_character_records["data"].items():
    +1063                for record_id, record in data.items():
    +1064                    to_update[record_id] = record
    +1065
    +1066            character_records = {
    +1067                int(rec_id): self.deserialize_character_records(
    +1068                    rec, record_hashes=to_update.get("featuredRecordHashes")
    +1069                )
    +1070                for rec_id, rec in to_update["records"].items()
    +1071            }
    +1072
    +1073        character_equipments: typing.Optional[
    +1074            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
    +1075        ] = None
    +1076        if raw_character_equips := payload.get("characterEquipment"):
    +1077            character_equipments = self.deserialize_character_equipments(
    +1078                raw_character_equips
    +1079            )
    +1080
    +1081        character_inventories: typing.Optional[
    +1082            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
    +1083        ] = None
    +1084        if raw_character_inventories := payload.get("characterInventories"):
    +1085            if "data" in raw_character_inventories:
    +1086                character_inventories = self.deserialize_character_equipments(
    +1087                    raw_character_inventories
    +1088                )
    +1089
    +1090        character_activities: typing.Optional[
    +1091            collections.Mapping[int, activity.CharacterActivity]
    +1092        ] = None
    +1093        if raw_char_acts := payload.get("characterActivities"):
    +1094            character_activities = self.deserialize_character_activities(raw_char_acts)
    +1095
    +1096        character_render_data: typing.Optional[
    +1097            collections.Mapping[int, character.RenderedData]
    +1098        ] = None
    +1099        if raw_character_render_data := payload.get("characterRenderData"):
    +1100            character_render_data = self.deserialize_characters_render_data(
    +1101                raw_character_render_data
    +1102            )
    +1103
    +1104        character_progressions: typing.Optional[
    +1105            collections.Mapping[int, character.CharacterProgression]
    +1106        ] = None
    +1107
    +1108        if raw_character_progressions := payload.get("characterProgressions"):
    +1109            character_progressions = self.deserialize_character_progressions_mapping(
    +1110                raw_character_progressions
    +1111            )
    +1112
    +1113        profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None
    +1114        if raw_profile_string_vars := payload.get("profileStringVariables"):
    +1115            profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"]
    +1116
    +1117        character_string_vars: typing.Optional[
    +1118            collections.Mapping[int, collections.Mapping[int, int]]
    +1119        ] = None
    +1120        if raw_character_string_vars := payload.get("characterStringVariables"):
    +1121            character_string_vars = {
    +1122                int(char_id): data["integerValuesByHash"]
    +1123                for char_id, data in raw_character_string_vars["data"].items()
    +1124            }
    +1125
    +1126        metrics: typing.Optional[
    +1127            collections.Sequence[
    +1128                collections.Mapping[
    +1129                    int, tuple[bool, typing.Optional[records.Objective]]
    +1130                ]
    +1131            ]
    +1132        ] = None
    +1133        root_node_hash: typing.Optional[int] = None
    +1134
    +1135        if raw_metrics := payload.get("metrics"):
    +1136            root_node_hash = raw_metrics["data"]["metricsRootNodeHash"]
    +1137            metrics = [
    +1138                {
    +1139                    int(metrics_hash): (
    +1140                        data["invisible"],
    +1141                        self.deserialize_objectives(data["objectiveProgress"])
    +1142                        if "objectiveProgress" in data
    +1143                        else None,
    +1144                    )
    +1145                    for metrics_hash, data in raw_metrics["data"]["metrics"].items()
    +1146                }
    +1147            ]
    +1148        transitory: typing.Optional[fireteams.FireteamParty] = None
    +1149        if raw_transitory := payload.get("profileTransitoryData"):
    +1150            if "data" in raw_transitory:
    +1151                transitory = self.deserialize_fireteam_party(raw_transitory["data"])
    +1152
    +1153        item_components: typing.Optional[components.ItemsComponent] = None
    +1154        if raw_item_components := payload.get("itemComponents"):
    +1155            item_components = self.deserialize_items_component(raw_item_components)
    +1156
    +1157        profile_plugsets: typing.Optional[
    +1158            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    +1159        ] = None
    +1160
    +1161        if raw_profile_plugs := payload.get("profilePlugSets"):
    +1162            profile_plugsets = {
    +1163                int(index): [self.deserialize_plug_item_state(state) for state in data]
    +1164                for index, data in raw_profile_plugs["data"]["plugs"].items()
    +1165            }
    +1166
    +1167        character_plugsets: typing.Optional[
    +1168            collections.Mapping[
    +1169                int, collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    +1170            ]
    +1171        ] = None
    +1172        if raw_char_plugsets := payload.get("characterPlugSets"):
    +1173            character_plugsets = {
    +1174                int(char_id): {
    +1175                    int(index): [
    +1176                        self.deserialize_plug_item_state(state) for state in data
    +1177                    ]
    +1178                    for index, data in inner["plugs"].items()
    +1179                }
    +1180                for char_id, inner in raw_char_plugsets["data"].items()
    +1181            }
    +1182
    +1183        character_collectibles: typing.Optional[
    +1184            collections.Mapping[int, items.Collectible]
    +1185        ] = None
    +1186        if raw_character_collectibles := payload.get("characterCollectibles"):
    +1187            character_collectibles = {
    +1188                int(char_id): self._deserialize_collectible(data)
    +1189                for char_id, data in raw_character_collectibles["data"].items()
    +1190            }
    +1191
    +1192        profile_collectibles: typing.Optional[items.Collectible] = None
    +1193        if raw_profile_collectibles := payload.get("profileCollectibles"):
    +1194            profile_collectibles = self._deserialize_collectible(
    +1195                raw_profile_collectibles["data"]
    +1196            )
    +1197
    +1198        profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
    +1199        if raw_profile_nodes := payload.get("profilePresentationNodes"):
    +1200            profile_nodes = {
    +1201                int(node_hash): self._deserialize_node(node)
    +1202                for node_hash, node in raw_profile_nodes["data"]["nodes"].items()
    +1203            }
    +1204
    +1205        character_nodes: typing.Optional[
    +1206            collections.Mapping[int, collections.Mapping[int, records.Node]]
    +1207        ] = None
    +1208        if raw_character_nodes := payload.get("characterPresentationNodes"):
    +1209            character_nodes = {
    +1210                int(char_id): {
    +1211                    int(node_hash): self._deserialize_node(node)
    +1212                    for node_hash, node in each_character["nodes"].items()
    +1213                }
    +1214                for char_id, each_character in raw_character_nodes["data"].items()
    +1215            }
    +1216
    +1217        platform_silver: typing.Optional[
    +1218            collections.Mapping[str, profile.ProfileItemImpl]
    +1219        ] = None
    +1220        if raw_platform_silver := payload.get("platformSilver"):
    +1221            if "data" in raw_platform_silver:
    +1222                platform_silver = {
    +1223                    platform_name: self.deserialize_profile_item(item)
    +1224                    for platform_name, item in raw_platform_silver["data"][
    +1225                        "platformSilver"
    +1226                    ].items()
    +1227                }
    +1228
    +1229        character_currency_lookups: typing.Optional[
    +1230            collections.Mapping[int, collections.Sequence[items.Currency]]
    +1231        ] = None
    +1232        if raw_char_lookups := payload.get("characterCurrencyLookups"):
    +1233            if "data" in raw_char_lookups:
    +1234                character_currency_lookups = {
    +1235                    int(char_id): self._deserialize_currencies(currencie)
    +1236                    for char_id, currencie in raw_char_lookups["data"].items()
    +1237                }
    +1238
    +1239        character_craftables: typing.Optional[
    +1240            collections.Mapping[int, components.CraftablesComponent]
    +1241        ] = None
    +1242        if raw_character_craftables := payload.get("characterCraftables"):
    +1243
    +1244            if "data" in raw_character_craftables:
    +1245                character_craftables = {
    +1246                    int(char_id): self.deserialize_craftables_component(craftable)
    +1247                    for char_id, craftable in raw_character_craftables["data"].items()
    +1248                }
    +1249
    +1250        return components.Component(
    +1251            profiles=profile_,
    +1252            profile_progression=profile_progression,
    +1253            profile_currencies=profile_currencies,
    +1254            profile_inventories=profile_inventories,
    +1255            profile_records=profile_records,
    +1256            characters=characters,
    +1257            character_records=character_records,
    +1258            character_equipments=character_equipments,
    +1259            character_inventories=character_inventories,
    +1260            character_activities=character_activities,
    +1261            character_render_data=character_render_data,
    +1262            character_progressions=character_progressions,
    +1263            profile_string_variables=profile_string_vars,
    +1264            character_string_variables=character_string_vars,
    +1265            metrics=metrics,
    +1266            root_node_hash=root_node_hash,
    +1267            transitory=transitory,
    +1268            item_components=item_components,
    +1269            profile_plugsets=profile_plugsets,
    +1270            character_plugsets=character_plugsets,
    +1271            character_collectibles=character_collectibles,
    +1272            profile_collectibles=profile_collectibles,
    +1273            profile_nodes=profile_nodes,
    +1274            character_nodes=character_nodes,
    +1275            platform_silver=platform_silver,
    +1276            character_currency_lookups=character_currency_lookups,
    +1277            character_craftables=character_craftables,
    +1278        )
    +
    -
    Example
    -
    iterator = FlatIterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
    -print(iterator.take(2))
    -# <FlatIterator([GameMode.RAID, GameMode.STRIKE])>
    -
    +

    Deserialize a JSON payload of Bungie.net profile components information.

    Parameters
      -
    • n (int): -The number of items to take.
    • +
    • payload (aiobungie.internal.helpers.JsonObject): +The JSON payload.
    -
    Raises
    +
    Returns
      -
    • StopIteration: If no elements are left in the iterator.
    • +
    • aiobungie.crates.Component: A component implementation that includes all other components +of the deserialized payload.
    -
    - +
    +
    def - take_while( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.FlatIterator[~Item]: - - - -
    - -
    198    def take_while(
    -199        self, predicate: collections.Callable[[Item], bool]
    -200    ) -> FlatIterator[Item]:
    -201        """Yields items from the iterator while predicate returns `True`.
    -202
    -203        Example
    -204        -------
    -205        ```py
    -206        iterator = FlatIterator([STEAM, XBOX, STADIA])
    -207        print(iterator.take_while(lambda platform: platform is not XBOX))
    -208        # <FlatIterator([STEAM])>
    -209        ```
    -210
    -211        Parameters
    -212        ----------
    -213        predicate: `collections.Callable[[Item], bool]`
    -214            The function to predicate each item in the iterator.
    -215
    -216        Raises
    -217        ------
    -218        `StopIteration`
    -219            If no elements are left in the iterator.
    -220        """
    -221        return FlatIterator(itertools.takewhile(predicate, self._items))
    -
    - - -

    Yields items from the iterator while predicate returns True.

    - -
    Example
    - -
    iterator = FlatIterator([STEAM, XBOX, STADIA])
    -print(iterator.take_while(lambda platform: platform is not XBOX))
    -# <FlatIterator([STEAM])>
    -
    + deserialize_items_component( self, payload: dict[str, typing.Any]) -> aiobungie.crates.components.ItemsComponent: -
    Parameters
    + -
      -
    • predicate (collections.Callable[[Item], bool]): -The function to predicate each item in the iterator.
    • -
    +
    + +
    1280    def deserialize_items_component(
    +1281        self, payload: typedefs.JSONObject
    +1282    ) -> components.ItemsComponent:
    +1283        instances: typing.Optional[
    +1284            collections.Sequence[collections.Mapping[int, items.ItemInstance]]
    +1285        ] = None
    +1286        if raw_instances := payload.get("instances"):
    +1287            instances = [
    +1288                {
    +1289                    int(ins_id): self.deserialize_instanced_item(item)
    +1290                    for ins_id, item in raw_instances["data"].items()
    +1291                }
    +1292            ]
    +1293
    +1294        render_data: typing.Optional[
    +1295            collections.Mapping[int, tuple[bool, dict[int, int]]]
    +1296        ] = None
    +1297        if raw_render_data := payload.get("renderData"):
    +1298            render_data = {
    +1299                int(ins_id): (data["useCustomDyes"], data["artRegions"])
    +1300                for ins_id, data in raw_render_data["data"].items()
    +1301            }
    +1302
    +1303        stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None
    +1304        if raw_stats := payload.get("stats"):
    +1305            builder: collections.Mapping[int, items.ItemStatsView] = {}
    +1306            for ins_id, stat in raw_stats["data"].items():
    +1307                for _, items_ in stat.items():
    +1308                    builder[int(ins_id)] = self.deserialize_item_stats_view(items_)  # type: ignore[index]
    +1309            stats = builder
    +1310
    +1311        sockets: typing.Optional[
    +1312            collections.Mapping[int, collections.Sequence[items.ItemSocket]]
    +1313        ] = None
    +1314        if raw_sockets := payload.get("sockets"):
    +1315            sockets = {
    +1316                int(ins_id): [
    +1317                    self.deserialize_item_socket(socket) for socket in item["sockets"]
    +1318                ]
    +1319                for ins_id, item in raw_sockets["data"].items()
    +1320            }
    +1321
    +1322        objeectives: typing.Optional[
    +1323            collections.Mapping[int, collections.Sequence[records.Objective]]
    +1324        ] = None
    +1325        if raw_objectives := payload.get("objectives"):
    +1326            objeectives = {
    +1327                int(ins_id): [self.deserialize_objectives(objective)]
    +1328                for ins_id, data in raw_objectives["data"].items()
    +1329                for objective in data["objectives"]
    +1330            }
    +1331
    +1332        perks: typing.Optional[
    +1333            collections.Mapping[int, collections.Collection[items.ItemPerk]]
    +1334        ] = None
    +1335        if raw_perks := payload.get("perks"):
    +1336            perks = {
    +1337                int(ins_id): [
    +1338                    self.deserialize_item_perk(perk) for perk in item["perks"]
    +1339                ]
    +1340                for ins_id, item in raw_perks["data"].items()
    +1341            }
    +1342
    +1343        plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None
    +1344        if raw_plug_states := payload.get("plugStates"):
    +1345            pending_states: list[items.PlugItemState] = []
    +1346            for _, plug in raw_plug_states["data"].items():
    +1347                pending_states.append(self.deserialize_plug_item_state(plug))
    +1348            plug_states = pending_states
    +1349
    +1350        reusable_plugs: typing.Optional[
    +1351            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
    +1352        ] = None
    +1353        if raw_re_plugs := payload.get("reusablePlugs"):
    +1354            reusable_plugs = {
    +1355                int(ins_id): [
    +1356                    self.deserialize_plug_item_state(state) for state in inner
    +1357                ]
    +1358                for ins_id, plug in raw_re_plugs["data"].items()
    +1359                for inner in list(plug["plugs"].values())
    +1360            }
    +1361
    +1362        plug_objectives: typing.Optional[
    +1363            collections.Mapping[
    +1364                int, collections.Mapping[int, collections.Collection[records.Objective]]
    +1365            ]
    +1366        ] = None
    +1367        if raw_plug_objectives := payload.get("plugObjectives"):
    +1368            plug_objectives = {
    +1369                int(ins_id): {
    +1370                    int(obj_hash): [self.deserialize_objectives(obj) for obj in objs]
    +1371                    for obj_hash, objs in inner["objectivesPerPlug"].items()
    +1372                }
    +1373                for ins_id, inner in raw_plug_objectives["data"].items()
    +1374            }
    +1375
    +1376        return components.ItemsComponent(
    +1377            sockets=sockets,
    +1378            stats=stats,
    +1379            render_data=render_data,
    +1380            instances=instances,
    +1381            objectives=objeectives,
    +1382            perks=perks,
    +1383            plug_states=plug_states,
    +1384            reusable_plugs=reusable_plugs,
    +1385            plug_objectives=plug_objectives,
    +1386        )
    +
    -
    Raises
    -
      -
    • StopIteration: If no elements are left in the iterator.
    • -
    +

    Deserialize a JSON objects within the itemComponents key.`

    -
    - +
    +
    def - drop_while( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.FlatIterator[~Item]: - - - -
    - -
    223    def drop_while(
    -224        self, predicate: collections.Callable[[Item], bool]
    -225    ) -> FlatIterator[Item]:
    -226        """Yields items from the iterator while predicate returns `False`.
    -227
    -228        Example
    -229        -------
    -230        ```py
    -231        iterator = FlatIterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
    -232        print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
    -233        # <FlatIterator([DestinyMembership(name="Bob")])>
    -234        ```
    -235
    -236        Parameters
    -237        ----------
    -238        predicate: `collections.Callable[[Item], bool]`
    -239            The function to predicate each item in the iterator.
    -240
    -241        Raises
    -242        ------
    -243        `StopIteration`
    -244            If no elements are left in the iterator.
    -245        """
    -246        return FlatIterator(itertools.dropwhile(predicate, self._items))
    -
    + deserialize_character_component( self, payload: dict[str, typing.Any]) -> aiobungie.crates.components.CharacterComponent: + -

    Yields items from the iterator while predicate returns False.

    +
    + +
    1388    def deserialize_character_component(  # type: ignore[call-arg]
    +1389        self, payload: typedefs.JSONObject
    +1390    ) -> components.CharacterComponent:
    +1391
    +1392        character_: typing.Optional[character.Character] = None
    +1393        if raw_singuler_character := payload.get("character"):
    +1394            character_ = self.deserialize_character(raw_singuler_character["data"])
    +1395
    +1396        inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
    +1397        if raw_inventory := payload.get("inventory"):
    +1398            if "data" in raw_inventory:
    +1399                inventory = self.deserialize_profile_items(raw_inventory["data"])
    +1400
    +1401        activities: typing.Optional[activity.CharacterActivity] = None
    +1402        if raw_activities := payload.get("activities"):
    +1403            activities = self.deserialize_character_activity(raw_activities["data"])
    +1404
    +1405        equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
    +1406        if raw_equipments := payload.get("equipment"):
    +1407            equipment = self.deserialize_profile_items(raw_equipments["data"])
    +1408
    +1409        progressions_: typing.Optional[character.CharacterProgression] = None
    +1410        if raw_progressions := payload.get("progressions"):
    +1411            progressions_ = self.deserialize_character_progressions(
    +1412                raw_progressions["data"]
    +1413            )
    +1414
    +1415        render_data: typing.Optional[character.RenderedData] = None
    +1416        if raw_render_data := payload.get("renderData"):
    +1417            render_data = self.deserialize_character_render_data(
    +1418                raw_render_data["data"]
    +1419            )
    +1420
    +1421        character_records: typing.Optional[
    +1422            collections.Mapping[int, records.CharacterRecord]
    +1423        ] = None
    +1424        if raw_char_records := payload.get("records"):
    +1425            character_records = self.deserialize_characters_records(
    +1426                raw_char_records["data"]
    +1427            )
    +1428
    +1429        item_components: typing.Optional[components.ItemsComponent] = None
    +1430        if raw_item_components := payload.get("itemComponents"):
    +1431            item_components = self.deserialize_items_component(raw_item_components)
    +1432
    +1433        nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
    +1434        if raw_nodes := payload.get("presentationNodes"):
    +1435            nodes = {
    +1436                int(node_hash): self._deserialize_node(node)
    +1437                for node_hash, node in raw_nodes["data"]["nodes"].items()
    +1438            }
    +1439
    +1440        collectibles: typing.Optional[items.Collectible] = None
    +1441        if raw_collectibles := payload.get("collectibles"):
    +1442            collectibles = self._deserialize_collectible(raw_collectibles["data"])
    +1443
    +1444        currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None
    +1445        if raw_currencies := payload.get("currencyLookups"):
    +1446            if "data" in raw_currencies:
    +1447                currency_lookups = self._deserialize_currencies(raw_currencies)
    +1448
    +1449        return components.CharacterComponent(
    +1450            activities=activities,
    +1451            equipment=equipment,
    +1452            inventory=inventory,
    +1453            progressions=progressions_,
    +1454            render_data=render_data,
    +1455            character=character_,
    +1456            character_records=character_records,
    +1457            profile_records=None,
    +1458            item_components=item_components,
    +1459            currency_lookups=currency_lookups,
    +1460            collectibles=collectibles,
    +1461            nodes=nodes,
    +1462        )
    +
    -
    Example
    -
    iterator = FlatIterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
    -print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
    -# <FlatIterator([DestinyMembership(name="Bob")])>
    -
    +

    Deserialize a JSON payload of Destiny 2 character component.

    Parameters
      -
    • predicate (collections.Callable[[Item], bool]): -The function to predicate each item in the iterator.
    • +
    • payload (aiobungie.typedefs.JSONObject): +The JSON payload.
    -
    Raises
    +
    Returns
    -
    - +
    +
    def - filter( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.FlatIterator[~Item]: + deserialize_inventory_results( self, payload: dict[str, typing.Any]) -> aiobungie.Iterator[aiobungie.crates.entity.SearchableEntity]: - +
    - -
    248    def filter(
    -249        self, predicate: collections.Callable[[Item], bool]
    -250    ) -> FlatIterator[Item]:
    -251        """Filters the iterator to only yield items that match the predicate.
    -252
    -253        Example
    -254        -------
    -255        ```py
    -256        names = FlatIterator(["Jim", "Bob", "Mike", "Jess"])
    -257        print(names.filter(lambda n: n != "Jim"))
    -258        # <FlatIterator(["Bob", "Mike", "Jess"])>
    -259        ```
    -260        """
    -261        return FlatIterator(filter(predicate, self._items))
    +    
    +            
    1490    def deserialize_inventory_results(
    +1491        self, payload: typedefs.JSONObject
    +1492    ) -> iterators.Iterator[entity.SearchableEntity]:
    +1493        suggested_words: list[str] = payload["suggestedWords"]
    +1494
    +1495        def _check_unknown(s: str) -> undefined.UndefinedOr[str]:
    +1496            return s if not typedefs.is_unknown(s) else undefined.Undefined
    +1497
    +1498        return iterators.Iterator(
    +1499            [
    +1500                entity.SearchableEntity(
    +1501                    net=self._net,
    +1502                    hash=data["hash"],
    +1503                    entity_type=data["entityType"],
    +1504                    weight=data["weight"],
    +1505                    suggested_words=suggested_words,
    +1506                    name=data["displayProperties"]["name"],
    +1507                    has_icon=data["displayProperties"]["hasIcon"],
    +1508                    description=_check_unknown(
    +1509                        data["displayProperties"]["description"]
    +1510                    ),
    +1511                    icon=assets.Image(data["displayProperties"]["icon"]),
    +1512                )
    +1513                for data in payload["results"]["results"]
    +1514            ]
    +1515        )
     
    -

    Filters the iterator to only yield items that match the predicate.

    +

    Deserialize results of searched Destiny2 entities.

    -
    Example
    +
    Parameters
    -
    names = FlatIterator(["Jim", "Bob", "Mike", "Jess"])
    -print(names.filter(lambda n: n != "Jim"))
    -# <FlatIterator(["Bob", "Mike", "Jess"])>
    -
    + + +
    Returns
    + +
    -
    - +
    +
    def - skip(self, n: int) -> aiobungie.FlatIterator[~Item]: + deserialize_inventory_entity( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.entity.InventoryEntity: - +
    - -
    263    def skip(self, n: int) -> FlatIterator[Item]:
    -264        """Skips the first number of items in the iterator.
    -265
    -266        Example
    -267        -------
    -268        ```py
    -269        iterator = FlatIterator([STEAM, XBOX, STADIA])
    -270        print(iterator.skip(1))
    -271        # <FlatIterator([XBOX, STADIA])>
    -272        ```
    -273        """
    -274        return FlatIterator(itertools.islice(self._items, n, None))
    +    
    +            
    1544    def deserialize_inventory_entity(  # noqa: C901 Too complex.
    +1545        self, payload: typedefs.JSONObject, /
    +1546    ) -> entity.InventoryEntity:
    +1547
    +1548        props = self._set_entity_attrs(payload)
    +1549        objects = self._deserialize_inventory_item_objects(payload)
    +1550
    +1551        collectible_hash: typing.Optional[int] = None
    +1552        if raw_collectible_hash := payload.get("collectibleHash"):
    +1553            collectible_hash = int(raw_collectible_hash)
    +1554
    +1555        secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    +1556        if raw_second_icon := payload.get("secondaryIcon"):
    +1557            secondary_icon = assets.Image(raw_second_icon)
    +1558
    +1559        secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    +1560        if raw_second_overlay := payload.get("secondaryOverlay"):
    +1561            secondary_overlay = assets.Image(raw_second_overlay)
    +1562
    +1563        secondary_special: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    +1564        if raw_second_special := payload.get("secondarySpecial"):
    +1565            secondary_special = assets.Image(raw_second_special)
    +1566
    +1567        screenshot: undefined.UndefinedOr[assets.Image] = undefined.Undefined
    +1568        if raw_screenshot := payload.get("screenshot"):
    +1569            screenshot = assets.Image(raw_screenshot)
    +1570
    +1571        watermark_icon: typing.Optional[assets.Image] = None
    +1572        if raw_watermark_icon := payload.get("iconWatermark"):
    +1573            watermark_icon = assets.Image(raw_watermark_icon)
    +1574
    +1575        watermark_shelved: typing.Optional[assets.Image] = None
    +1576        if raw_watermark_shelved := payload.get("iconWatermarkShelved"):
    +1577            watermark_shelved = assets.Image(raw_watermark_shelved)
    +1578
    +1579        about: undefined.UndefinedOr[str] = undefined.Undefined
    +1580        if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown(
    +1581            raw_about
    +1582        ):
    +1583            about = raw_about
    +1584
    +1585        ui_item_style: undefined.UndefinedOr[str] = undefined.Undefined
    +1586        if (
    +1587            raw_ui_style := payload.get("uiItemDisplayStyle")
    +1588        ) and not typedefs.is_unknown(raw_ui_style):
    +1589            ui_item_style = raw_ui_style
    +1590
    +1591        tier_and_name: undefined.UndefinedOr[str] = undefined.Undefined
    +1592        if (
    +1593            raw_tier_and_name := payload.get("itemTypeAndTierDisplayName")
    +1594        ) and not typedefs.is_unknown(raw_tier_and_name):
    +1595            tier_and_name = raw_tier_and_name
    +1596
    +1597        type_name: undefined.UndefinedOr[str] = undefined.Undefined
    +1598        if (
    +1599            raw_type_name := payload.get("itemTypeDisplayName")
    +1600        ) and not typedefs.is_unknown(raw_type_name):
    +1601            type_name = raw_type_name
    +1602
    +1603        display_source: undefined.UndefinedOr[str] = undefined.Undefined
    +1604        if (
    +1605            raw_display_source := payload.get("displaySource")
    +1606        ) and not typedefs.is_unknown(raw_display_source):
    +1607            display_source = raw_display_source
    +1608
    +1609        lorehash: typing.Optional[int] = None
    +1610        if raw_lore_hash := payload.get("loreHash"):
    +1611            lorehash = int(raw_lore_hash)
    +1612
    +1613        summary_hash: typing.Optional[int] = None
    +1614        if raw_summary_hash := payload.get("summaryItemHash"):
    +1615            summary_hash = raw_summary_hash
    +1616
    +1617        breaker_type_hash: typing.Optional[int] = None
    +1618        if raw_breaker_type_hash := payload.get("breakerTypeHash"):
    +1619            breaker_type_hash = int(raw_breaker_type_hash)
    +1620
    +1621        damage_types: typing.Optional[collections.Sequence[int]] = None
    +1622        if raw_damage_types := payload.get("damageTypes"):
    +1623            damage_types = [int(type_) for type_ in raw_damage_types]
    +1624
    +1625        damagetype_hashes: typing.Optional[collections.Sequence[int]] = None
    +1626        if raw_damagetype_hashes := payload.get("damageTypeHashes"):
    +1627            damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes]
    +1628
    +1629        default_damagetype_hash: typing.Optional[int] = None
    +1630        if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"):
    +1631            default_damagetype_hash = int(raw_defaultdmg_hash)
    +1632
    +1633        emblem_objective_hash: typing.Optional[int] = None
    +1634        if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"):
    +1635            emblem_objective_hash = int(raw_emblem_obj_hash)
    +1636
    +1637        tier_type: typing.Optional[enums.TierType] = None
    +1638        tier: typing.Optional[enums.ItemTier] = None
    +1639        bucket_hash: typing.Optional[int] = None
    +1640        recovery_hash: typing.Optional[int] = None
    +1641        tier_name: undefined.UndefinedOr[str] = undefined.Undefined
    +1642        isinstance_item: bool = False
    +1643        expire_tool_tip: undefined.UndefinedOr[str] = undefined.Undefined
    +1644        expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.Undefined
    +1645        suppress_expiration: bool = False
    +1646        max_stack_size: typing.Optional[int] = None
    +1647        stack_label: undefined.UndefinedOr[str] = undefined.Undefined
    +1648
    +1649        if inventory := payload.get("inventory"):
    +1650            tier_type = enums.TierType(int(inventory["tierType"]))
    +1651            tier = enums.ItemTier(int(inventory["tierTypeHash"]))
    +1652            bucket_hash = int(inventory["bucketTypeHash"])
    +1653            recovery_hash = int(inventory["recoveryBucketTypeHash"])
    +1654            tier_name = inventory["tierTypeName"]
    +1655            isinstance_item = inventory["isInstanceItem"]
    +1656            suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"]
    +1657            max_stack_size = int(inventory["maxStackSize"])
    +1658
    +1659            try:
    +1660                stack_label = inventory["stackUniqueLabel"]
    +1661            except KeyError:
    +1662                pass
    +1663
    +1664        return entity.InventoryEntity(
    +1665            net=self._net,
    +1666            collectible_hash=collectible_hash,
    +1667            name=props.name,
    +1668            about=about,
    +1669            emblem_objective_hash=emblem_objective_hash,
    +1670            suppress_expiration=suppress_expiration,
    +1671            max_stack_size=max_stack_size,
    +1672            stack_label=stack_label,
    +1673            tier=tier,
    +1674            tier_type=tier_type,
    +1675            tier_name=tier_name,
    +1676            bucket_hash=bucket_hash,
    +1677            recovery_bucket_hash=recovery_hash,
    +1678            isinstance_item=isinstance_item,
    +1679            expire_in_orbit_message=expire_in_orbit_message,
    +1680            expiration_tooltip=expire_tool_tip,
    +1681            lore_hash=lorehash,
    +1682            type_and_tier_name=tier_and_name,
    +1683            summary_hash=summary_hash,
    +1684            ui_display_style=ui_item_style,
    +1685            type_name=type_name,
    +1686            breaker_type_hash=breaker_type_hash,
    +1687            description=props.description,
    +1688            display_source=display_source,
    +1689            hash=props.hash,
    +1690            damage_types=damage_types,
    +1691            index=props.index,
    +1692            icon=props.icon,
    +1693            has_icon=props.has_icon,
    +1694            screenshot=screenshot,
    +1695            watermark_icon=watermark_icon,
    +1696            watermark_shelved=watermark_shelved,
    +1697            secondary_icon=secondary_icon,
    +1698            secondary_overlay=secondary_overlay,
    +1699            secondary_special=secondary_special,
    +1700            type=enums.ItemType(int(payload["itemType"])),
    +1701            trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])],
    +1702            trait_ids=[trait for trait in payload.get("traitIds", [])],
    +1703            category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]],
    +1704            item_class=enums.Class(int(payload["classType"])),
    +1705            sub_type=enums.ItemSubType(int(payload["itemSubType"])),
    +1706            breaker_type=int(payload["breakerType"]),
    +1707            default_damagetype=int(payload["defaultDamageType"]),
    +1708            default_damagetype_hash=default_damagetype_hash,
    +1709            damagetype_hashes=damagetype_hashes,
    +1710            tooltip_notifications=payload["tooltipNotifications"],
    +1711            not_transferable=payload["nonTransferrable"],
    +1712            allow_actions=payload["allowActions"],
    +1713            is_equippable=payload["equippable"],
    +1714            objects=objects,
    +1715            background_colors=payload.get("backgroundColor", {}),
    +1716            season_hash=payload.get("seasonHash"),
    +1717            has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"],
    +1718        )
     
    -

    Skips the first number of items in the iterator.

    +

    Deserialize a JSON payload of an inventory entity item information.

    -
    Example
    +

    This can be any item from DestinyInventoryItemDefinition definition.

    -
    iterator = FlatIterator([STEAM, XBOX, STADIA])
    -print(iterator.skip(1))
    -# <FlatIterator([XBOX, STADIA])>
    -
    +
    Parameters
    + + + +
    Returns
    + +
    -
    - +
    +
    def - discard( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.FlatIterator[~Item]: - - - -
    - -
    276    def discard(
    -277        self, predicate: collections.Callable[[Item], bool]
    -278    ) -> FlatIterator[Item]:
    -279        """Discards all elements in the iterator for which the predicate function returns true.
    -280
    -281        Example
    -282        -------
    -283        ```py
    -284        iterator = FlatIterator(['A', 'B', 'C'])
    -285        print(iterator.discard(lambda x: x == 'B'))
    -286        # <FlatIterator(['A', 'C'])>
    -287        ```
    -288
    -289        Parameters
    -290        ----------
    -291        predicate: `collections.Callable[[Item], bool]`
    -292            The function to test each item in the iterator.
    -293
    -294        Raises
    -295        ------
    -296        `StopIteration`
    -297            If no elements are left in the iterator.
    -298        """
    -299        return FlatIterator(filter(lambda x: not predicate(x), self._items))
    -
    - - -

    Discards all elements in the iterator for which the predicate function returns true.

    + deserialize_objective_entity( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.entity.ObjectiveEntity: -
    Example
    + + +
    + +
    1720    def deserialize_objective_entity(
    +1721        self, payload: typedefs.JSONObject, /
    +1722    ) -> entity.ObjectiveEntity:
    +1723        props = self._set_entity_attrs(payload)
    +1724        return entity.ObjectiveEntity(
    +1725            net=self._net,
    +1726            hash=props.hash,
    +1727            index=props.index,
    +1728            description=props.description,
    +1729            name=props.name,
    +1730            has_icon=props.has_icon,
    +1731            icon=props.icon,
    +1732            unlock_value_hash=payload["unlockValueHash"],
    +1733            completion_value=payload["completionValue"],
    +1734            scope=entity.GatingScope(int(payload["scope"])),
    +1735            location_hash=payload["locationHash"],
    +1736            allowed_negative_value=payload["allowNegativeValue"],
    +1737            allowed_value_change=payload["allowValueChangeWhenCompleted"],
    +1738            counting_downward=payload["isCountingDownward"],
    +1739            value_style=entity.ValueUIStyle(int(payload["valueStyle"])),
    +1740            progress_description=payload["progressDescription"],
    +1741            perks=payload["perks"],
    +1742            stats=payload["stats"],
    +1743            minimum_visibility=payload["minimumVisibilityThreshold"],
    +1744            allow_over_completion=payload["allowOvercompletion"],
    +1745            show_value_style=payload["showValueOnComplete"],
    +1746            display_only_objective=payload["isDisplayOnlyObjective"],
    +1747            complete_value_style=entity.ValueUIStyle(
    +1748                int(payload["completedValueStyle"])
    +1749            ),
    +1750            progress_value_style=entity.ValueUIStyle(
    +1751                int(payload["inProgressValueStyle"])
    +1752            ),
    +1753            ui_label=payload["uiLabel"],
    +1754            ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])),
    +1755        )
    +
    -
    iterator = FlatIterator(['A', 'B', 'C'])
    -print(iterator.discard(lambda x: x == 'B'))
    -# <FlatIterator(['A', 'C'])>
    -
    + +

    Deserialize a JSON payload of an objective entity information.

    Parameters
      -
    • predicate (collections.Callable[[Item], bool]): -The function to test each item in the iterator.
    • +
    • payload (aiobungie.typedefs.JSONObject): +The JSON payload.
    -
    Raises
    +
    Returns
    -
    - +
    +
    def - zip( self, other: 'FlatIterator[OtherItem]') -> 'FlatIterator[tuple[Item, OtherItem]]': - - - -
    - -
    301    def zip(
    -302        self, other: FlatIterator[OtherItem]
    -303    ) -> FlatIterator[tuple[Item, OtherItem]]:
    -304        """Zips the iterator with another iterable.
    -305
    -306        Example
    -307        -------
    -308        ```py
    -309        iterator = FlatIterator([1, 3, 5])
    -310        other = FlatIterator([2, 4, 6])
    -311        for item, other_item in iterator.zip(other):
    -312            print(item, other_item)
    -313        # <FlatIterator([(1, 2), (3, 4), (5, 6)])>
    -314        ```
    -315
    -316        Parameters
    -317        ----------
    -318        other: `FlatIterator[OtherItem]`
    -319            The iterable to zip with.
    -320
    -321        Raises
    -322        ------
    -323        `StopIteration`
    -324            If no elements are left in the iterator.
    -325        """
    -326        return FlatIterator(zip(self._items, other))
    -
    + deserialize_activity( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.activity.Activity: + -

    Zips the iterator with another iterable.

    +
    + +
    1783    def deserialize_activity(
    +1784        self,
    +1785        payload: typedefs.JSONObject,
    +1786        /,
    +1787    ) -> activity.Activity:
    +1788        period = time.clean_date(payload["period"])
    +1789        details = payload["activityDetails"]
    +1790        ref_id = int(details["referenceId"])
    +1791        instance_id = int(details["instanceId"])
    +1792        mode = enums.GameMode(details["mode"])
    +1793        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
    +1794        is_private = details["isPrivate"]
    +1795        membership_type = enums.MembershipType(int(details["membershipType"]))
    +1796
    +1797        # Since we're using the same fields for post activity method
    +1798        # this check is required since post activity doesn't values values
    +1799        values = self._deserialize_activity_values(payload["values"])
    +1800
    +1801        return activity.Activity(
    +1802            net=self._net,
    +1803            hash=ref_id,
    +1804            instance_id=instance_id,
    +1805            mode=mode,
    +1806            modes=modes,
    +1807            is_private=is_private,
    +1808            membership_type=membership_type,
    +1809            occurred_at=period,
    +1810            values=values,
    +1811        )
    +
    -
    Example
    -
    iterator = FlatIterator([1, 3, 5])
    -other = FlatIterator([2, 4, 6])
    -for item, other_item in iterator.zip(other):
    -    print(item, other_item)
    -# <FlatIterator([(1, 2), (3, 4), (5, 6)])>
    -
    +

    Deserialize a JSON payload of an activity history information.

    Parameters
    -
    Raises
    +
    Returns
    -
    - +
    +
    def - all(self, predicate: collections.abc.Callable[[~Item], bool]) -> bool: - - - -
    - -
    328    def all(self, predicate: collections.Callable[[Item], bool]) -> bool:
    -329        """`True` if all items in the iterator match the predicate.
    -330
    -331        Example
    -332        -------
    -333        ```py
    -334        iterator = FlatIterator([1, 2, 3])
    -335        while iterator.all(lambda item: isinstance(item, int)):
    -336            print("Still all integers")
    -337            continue
    -338        # Still all integers
    -339        ```
    -340
    -341        Parameters
    -342        ----------
    -343        predicate: `collections.Callable[[Item], bool]`
    -344            The function to test each item in the iterator.
    -345
    -346        Raises
    -347        ------
    -348        `StopIteration`
    -349            If no elements are left in the iterator.
    -350        """
    -351        return all(predicate(item) for item in self)
    -
    + deserialize_activities( self, payload: dict[str, typing.Any]) -> aiobungie.Iterator[aiobungie.crates.activity.Activity]: + -

    True if all items in the iterator match the predicate.

    +
    + +
    1813    def deserialize_activities(
    +1814        self, payload: typedefs.JSONObject
    +1815    ) -> iterators.Iterator[activity.Activity]:
    +1816        return iterators.Iterator(
    +1817            [
    +1818                self.deserialize_activity(activity_)
    +1819                for activity_ in payload["activities"]
    +1820            ]
    +1821        )
    +
    -
    Example
    -
    iterator = FlatIterator([1, 2, 3])
    -while iterator.all(lambda item: isinstance(item, int)):
    -    print("Still all integers")
    -    continue
    -# Still all integers
    -
    +

    Deserialize a JSON payload of an array of activity history information.

    Parameters
      -
    • predicate (collections.Callable[[Item], bool]): -The function to test each item in the iterator.
    • +
    • payload (aiobungie.typedefs.JSONObject): +The JSON payload.
    -
    Raises
    +
    Returns
      -
    • StopIteration: If no elements are left in the iterator.
    • +
    • aiobungie.iterators.Iterator[aiobungie.crates.Activity]: Am iterator over activity objects of the deserialized payload.
    -
    - +
    +
    def - any(self, predicate: collections.abc.Callable[[~Item], bool]) -> bool: - - - -
    - -
    353    def any(self, predicate: collections.Callable[[Item], bool]) -> bool:
    -354        """`True` if any items in the iterator match the predicate.
    -355
    -356        Example
    -357        -------
    -358        ```py
    -359        iterator = FlatIterator([1, 2, 3])
    -360        if iterator.any(lambda item: isinstance(item, int)):
    -361            print("At least one item is an int.")
    -362        # At least one item is an int.
    -363        ```
    -364
    -365        Parameters
    -366        ----------
    -367        predicate: `collections.Callable[[Item], bool]`
    -368            The function to test each item in the iterator.
    -369
    -370        Raises
    -371        ------
    -372        `StopIteration`
    -373            If no elements are left in the iterator.
    -374        """
    -375        return any(predicate(item) for item in self)
    -
    + deserialize_extended_weapon_values( self, payload: dict[str, typing.Any]) -> aiobungie.crates.activity.ExtendedWeaponValues: + -

    True if any items in the iterator match the predicate.

    +
    + +
    1823    def deserialize_extended_weapon_values(
    +1824        self, payload: typedefs.JSONObject
    +1825    ) -> activity.ExtendedWeaponValues:
    +1826
    +1827        assists: typing.Optional[int] = None
    +1828        if raw_assists := payload["values"].get("uniqueWeaponAssists"):
    +1829            assists = raw_assists["basic"]["value"]
    +1830        assists_damage: typing.Optional[int] = None
    +1831
    +1832        if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"):
    +1833            assists_damage = raw_assists_damage["basic"]["value"]
    +1834
    +1835        return activity.ExtendedWeaponValues(
    +1836            reference_id=int(payload["referenceId"]),
    +1837            kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"],
    +1838            precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][
    +1839                "value"
    +1840            ],
    +1841            assists=assists,
    +1842            assists_damage=assists_damage,
    +1843            precision_kills_percentage=(
    +1844                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"],
    +1845                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][
    +1846                    "displayValue"
    +1847                ],
    +1848            ),
    +1849        )
    +
    -
    Example
    -
    iterator = FlatIterator([1, 2, 3])
    -if iterator.any(lambda item: isinstance(item, int)):
    -    print("At least one item is an int.")
    -# At least one item is an int.
    -
    +

    Deserialize values of extended weapons JSON object.

    Parameters
      -
    • predicate (collections.Callable[[Item], bool]): -The function to test each item in the iterator.
    • +
    • payload (aiobungie.typedefs.JSONObject): +The JSON payload.
    -
    Raises
    +
    Returns
    -
    - +
    +
    def - sort( self, *, key: 'collections.Callable[[Item], typeshed.SupportsRichComparison]', reverse: bool = False) -> aiobungie.FlatIterator[~Item]: - - - -
    - -
    377    def sort(
    -378        self,
    -379        *,
    -380        key: collections.Callable[[Item], typeshed.SupportsRichComparison],
    -381        reverse: bool = False,
    -382    ) -> FlatIterator[Item]:
    -383        """Sorts the iterator.
    -384
    -385        Example
    -386        -------
    -387        ```py
    -388        iterator = FlatIterator([3, 1, 6, 7])
    -389        print(iterator.sort(key=lambda item: item))
    -390        # <FlatIterator([1, 3, 6, 7])>
    -391        ```
    -392
    -393        Parameters
    -394        ----------
    -395        key: `collections.Callable[[Item], Any]`
    -396            The function to sort by.
    -397        reverse: `bool`
    -398            Whether to reverse the sort.
    -399
    -400        Raises
    -401        ------
    -402        `StopIteration`
    -403            If no elements are left in the iterator.
    -404        """
    -405        return FlatIterator(sorted(self._items, key=key, reverse=reverse))
    -
    + deserialize_post_activity_player( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.activity.PostActivityPlayer: + -

    Sorts the iterator.

    +
    + +
    1872    def deserialize_post_activity_player(
    +1873        self, payload: typedefs.JSONObject, /
    +1874    ) -> activity.PostActivityPlayer:
    +1875        player = payload["player"]
    +1876
    +1877        class_hash: typedefs.NoneOr[int] = None
    +1878        if (class_hash := player.get("classHash")) is not None:
    +1879            class_hash = class_hash
    +1880
    +1881        race_hash: typedefs.NoneOr[int] = None
    +1882        if (race_hash := player.get("raceHash")) is not None:
    +1883            race_hash = race_hash
    +1884
    +1885        gender_hash: typedefs.NoneOr[int] = None
    +1886        if (gender_hash := player.get("genderHash")) is not None:
    +1887            gender_hash = gender_hash
    +1888
    +1889        character_class: undefined.UndefinedOr[str] = undefined.Undefined
    +1890        if (
    +1891            character_class := player.get("characterClass")
    +1892        ) and not typedefs.is_unknown(character_class):
    +1893            character_class = character_class
    +1894
    +1895        character_level: typedefs.NoneOr[int] = None
    +1896        if (character_level := player.get("characterLevel")) is not None:
    +1897            character_level = character_level
    +1898
    +1899        return activity.PostActivityPlayer(
    +1900            standing=int(payload["standing"]),
    +1901            score=int(payload["score"]["basic"]["value"]),
    +1902            character_id=payload["characterId"],
    +1903            destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]),
    +1904            character_class=character_class,
    +1905            character_level=character_level,
    +1906            race_hash=race_hash,
    +1907            gender_hash=gender_hash,
    +1908            class_hash=class_hash,
    +1909            light_level=int(player["lightLevel"]),
    +1910            emblem_hash=int(player["emblemHash"]),
    +1911            values=self._deserialize_activity_values(payload["values"]),
    +1912            extended_values=self._deserialize_extended_values(payload["extended"]),
    +1913        )
    +
    -
    Example
    -
    iterator = FlatIterator([3, 1, 6, 7])
    -print(iterator.sort(key=lambda item: item))
    -# <FlatIterator([1, 3, 6, 7])>
    -
    +

    Deserialize a JSON payload of a post activity player information.

    Parameters
      -
    • key (collections.Callable[[Item], Any]): -The function to sort by.
    • -
    • reverse (bool): -Whether to reverse the sort.
    • +
    • payload (aiobungie.typedefs.JSONObject): +The JSON payload.
    -
    Raises
    +
    Returns
    -
    - +
    +
    def - first(self) -> ~Item: + deserialize_post_activity( self, payload: dict[str, typing.Any]) -> aiobungie.crates.activity.PostActivity: - +
    - -
    407    def first(self) -> Item:
    -408        """Returns the first item in the iterator.
    -409
    -410        Example
    -411        -------
    -412        ```py
    -413        iterator = FlatIterator([3, 1, 6, 7])
    -414        print(iterator.first())
    -415        3
    -416        ```
    -417
    -418        Raises
    -419        ------
    -420        `StopIteration`
    -421            If no elements are left in the iterator.
    -422        """
    -423        return self.take(1).next()
    +    
    +            
    1925    def deserialize_post_activity(
    +1926        self, payload: typedefs.JSONObject
    +1927    ) -> activity.PostActivity:
    +1928        period = time.clean_date(payload["period"])
    +1929        details = payload["activityDetails"]
    +1930        ref_id = int(details["referenceId"])
    +1931        instance_id = int(details["instanceId"])
    +1932        mode = enums.GameMode(details["mode"])
    +1933        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
    +1934        is_private = details["isPrivate"]
    +1935        membership_type = enums.MembershipType(int(details["membershipType"]))
    +1936        return activity.PostActivity(
    +1937            net=self._net,
    +1938            hash=ref_id,
    +1939            membership_type=membership_type,
    +1940            instance_id=instance_id,
    +1941            mode=mode,
    +1942            modes=modes,
    +1943            is_private=is_private,
    +1944            occurred_at=period,
    +1945            starting_phase=int(payload["startingPhaseIndex"]),
    +1946            players=[
    +1947                self.deserialize_post_activity_player(player)
    +1948                for player in payload["entries"]
    +1949            ],
    +1950            teams=[
    +1951                self._deserialize_post_activity_team(team) for team in payload["teams"]
    +1952            ],
    +1953        )
     
    -

    Returns the first item in the iterator.

    +

    Deserialize a JSON payload of a post activity information.

    -
    Example
    +
    Parameters
    -
    iterator = FlatIterator([3, 1, 6, 7])
    -print(iterator.first())
    -3
    -
    + -
    Raises
    +
    Returns
    -
    - +
    +
    def - reversed(self) -> aiobungie.FlatIterator[~Item]: + deserialize_aggregated_activity( self, payload: dict[str, typing.Any]) -> aiobungie.crates.activity.AggregatedActivity: - +
    - -
    425    def reversed(self) -> FlatIterator[Item]:
    -426        """Returns a new iterator that yields the items in the iterator in reverse order.
    -427
    -428        Example
    -429        -------
    -430        ```py
    -431        iterator = FlatIterator([3, 1, 6, 7])
    -432        print(iterator.reversed())
    -433        # <FlatIterator([7, 6, 1, 3])>
    -434        ```
    -435
    -436        Raises
    -437        ------
    -438        `StopIteration`
    -439            If no elements are left in the iterator.
    -440        """
    -441        return FlatIterator(reversed(self.collect()))
    +    
    +            
    1991    def deserialize_aggregated_activity(
    +1992        self, payload: typedefs.JSONObject
    +1993    ) -> activity.AggregatedActivity:
    +1994        return activity.AggregatedActivity(
    +1995            hash=int(payload["activityHash"]),
    +1996            values=self._deserialize_aggregated_activity_values(payload["values"]),
    +1997        )
     
    -

    Returns a new iterator that yields the items in the iterator in reverse order.

    +

    Deserialize a JSON payload of an aggregated activity.

    -
    Example
    +
    Parameters
    -
    iterator = FlatIterator([3, 1, 6, 7])
    -print(iterator.reversed())
    -# <FlatIterator([7, 6, 1, 3])>
    -
    + -
    Raises
    +
    Returns
    -
    - +
    +
    def - count(self) -> int: + deserialize_aggregated_activities( self, payload: dict[str, typing.Any]) -> aiobungie.Iterator[aiobungie.crates.activity.AggregatedActivity]: - +
    - -
    443    def count(self) -> int:
    -444        """Returns the number of items in the iterator.
    -445
    -446        Example
    -447        -------
    -448        ```py
    -449        iterator = FlatIterator([3, 1, 6, 7])
    -450        print(iterator.count())
    -451        4
    -452        ```
    -453        """
    -454        count = 0
    -455        for _ in self:
    -456            count += 1
    -457
    -458        return count
    +    
    +            
    1999    def deserialize_aggregated_activities(
    +2000        self, payload: typedefs.JSONObject
    +2001    ) -> iterators.Iterator[activity.AggregatedActivity]:
    +2002        return iterators.Iterator(
    +2003            [
    +2004                self.deserialize_aggregated_activity(activity)
    +2005                for activity in payload["activities"]
    +2006            ]
    +2007        )
     
    -

    Returns the number of items in the iterator.

    +

    Deserialize a JSON payload of an array of aggregated activities.

    -
    Example
    +
    Parameters
    -
    iterator = FlatIterator([3, 1, 6, 7])
    -print(iterator.count())
    -4
    -
    + + +
    Returns
    + +
    -
    - +
    +
    def - union( self, other: aiobungie.FlatIterator[~Item]) -> aiobungie.FlatIterator[~Item]: - - - -
    - -
    460    def union(self, other: FlatIterator[Item]) -> FlatIterator[Item]:
    -461        """Returns a new iterator that yields all items from both iterators.
    -462
    -463        Example
    -464        -------
    -465        ```py
    -466        iterator = FlatIterator([1, 2, 3])
    -467        other = FlatIterator([4, 5, 6])
    -468        print(iterator.union(other))
    -469        # <FlatIterator([1, 2, 3, 4, 5, 6])>
    -470        ```
    -471
    -472        Parameters
    -473        ----------
    -474        other: `FlatIterator[Item]`
    -475            The iterable to union with.
    -476
    -477        Raises
    -478        ------
    -479        `StopIteration`
    -480            If no elements are left in the iterator.
    -481        """
    -482        return FlatIterator(itertools.chain(self._items, other))
    -
    + deserialize_linked_profiles( self, payload: dict[str, typing.Any]) -> aiobungie.crates.profile.LinkedProfile: + -

    Returns a new iterator that yields all items from both iterators.

    +
    + +
    2009    def deserialize_linked_profiles(
    +2010        self, payload: typedefs.JSONObject
    +2011    ) -> profile.LinkedProfile:
    +2012        bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"])
    +2013        error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
    +2014        profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
    +2015
    +2016        if raw_profile := payload.get("profiles"):
    +2017            for pfile in raw_profile:
    +2018                profiles_vec.append(self.deserialize_destiny_membership(pfile))
    +2019
    +2020        if raw_profiles_with_errors := payload.get("profilesWithErrors"):
    +2021            for raw_error_pfile in raw_profiles_with_errors:
    +2022                if error_pfile := raw_error_pfile.get("infoCard"):
    +2023                    error_profiles_vec.append(
    +2024                        self.deserialize_destiny_membership(error_pfile)
    +2025                    )
    +2026
    +2027        return profile.LinkedProfile(
    +2028            net=self._net,
    +2029            bungie=bungie_user,
    +2030            profiles=profiles_vec,
    +2031            profiles_with_errors=error_profiles_vec,
    +2032        )
    +
    -
    Example
    -
    iterator = FlatIterator([1, 2, 3])
    -other = FlatIterator([4, 5, 6])
    -print(iterator.union(other))
    -# <FlatIterator([1, 2, 3, 4, 5, 6])>
    -
    +

    Deserialize a JSON payload of Bungie.net hard linked profile information.

    Parameters
    -
    Raises
    +
    Returns
    -
    - +
    +
    def - for_each(self, func: collections.abc.Callable[[~Item], typing.Any]) -> None: + deserialize_clan_banners( self, payload: dict[str, typing.Any]) -> collections.abc.Sequence[aiobungie.crates.clans.ClanBanner]: + + - - -
    - -
    484    def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None:
    -485        """Calls the function on each item in the iterator.
    -486
    -487        Example
    -488        -------
    -489        ```py
    -490        iterator = FlatIterator([1, 2, 3])
    -491        iterator.for_each(lambda item: print(item))
    -492        # 1
    -493        # 2
    -494        # 3
    -495        ```
    -496
    -497        Parameters
    -498        ----------
    -499        func: `typeshed.Callable[[Item], None]`
    -500            The function to call on each item in the iterator.
    -501        """
    -502        for item in self:
    -503            func(item)
    +    
    + +
    2034    def deserialize_clan_banners(
    +2035        self, payload: typedefs.JSONObject
    +2036    ) -> collections.Sequence[clans.ClanBanner]:
    +2037        banners_seq: typing.MutableSequence[clans.ClanBanner] = []
    +2038        if banners := payload.get("clanBannerDecals"):
    +2039            for k, v in banners.items():
    +2040                banner_obj = clans.ClanBanner(
    +2041                    id=int(k),
    +2042                    foreground=assets.Image(v["foregroundPath"]),
    +2043                    background=assets.Image(v["backgroundPath"]),
    +2044                )
    +2045                banners_seq.append(banner_obj)
    +2046        return banners_seq
     
    -

    Calls the function on each item in the iterator.

    +

    Deserialize a JSON array of a clan banners information.

    -
    Example
    +
    Parameters
    -
    iterator = FlatIterator([1, 2, 3])
    -iterator.for_each(lambda item: print(item))
    -# 1
    -# 2
    -# 3
    -
    + -
    Parameters
    +
    Returns
      -
    • func (typeshed.Callable[[Item], None]): -The function to call on each item in the iterator.
    • +
    • collections.Sequence[aiobungie.crates.ClanBanner]: A sequence of clan banners of the deserialized payload.
    -
    - +
    +
    - async def - async_for_each( self, func: collections.abc.Callable[[~Item], collections.abc.Coroutine[None, None, None]]) -> None: + def + deserialize_public_milestone_content( self, payload: dict[str, typing.Any]) -> aiobungie.crates.milestones.MilestoneContent: - - -
    - -
    505    async def async_for_each(
    -506        self,
    -507        func: collections.Callable[[Item], collections.Coroutine[None, None, None]],
    -508    ) -> None:
    -509        """Calls the async function on each item in the iterator concurrently.
    -510
    -511        Example
    -512        -------
    -513        ```py
    -514        async def signup(username: str) -> None:
    -515            async with aiohttp.request('POST', '...') as r:
    -516                # Actual logic.
    -517                ...
    -518
    -519        async def main():
    -520            users = aiobungie.into_iter(["user_danny", "user_jojo"])
    -521            await users.async_for_each(lambda username: signup(username))
    -522        ```
    -523
    -524        Parameters
    -525        ----------
    -526        func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]`
    -527            The async function to call on each item in the iterator.
    -528        """
    -529        await _helpers.awaits(*(func(item) for item in self))
    -
    + +
    + +
    2048    def deserialize_public_milestone_content(
    +2049        self, payload: typedefs.JSONObject
    +2050    ) -> milestones.MilestoneContent:
    +2051        items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None
    +2052        if raw_categories := payload.get("itemCategories"):
    +2053            for item in raw_categories:
    +2054                title = undefined.Undefined
    +2055                if raw_title := item.get("title"):
    +2056                    if raw_title != typedefs.Unknown:
    +2057                        title = raw_title
    +2058                if raw_hashes := item.get("itemHashes"):
    +2059                    hashes: collections.Sequence[int] = raw_hashes
    +2060
    +2061                items_categoris = milestones.MilestoneItems(title=title, hashes=hashes)
    +2062
    +2063        about = undefined.Undefined
    +2064        if (raw_about := payload["about"]) != typedefs.Unknown:
    +2065            about = raw_about
    +2066
    +2067        status = undefined.Undefined
    +2068        if (raw_status := payload["status"]) != typedefs.Unknown:
    +2069            status = raw_status
    +2070
    +2071        tips: typing.MutableSequence[undefined.UndefinedOr[str]] = []
    +2072        if raw_tips := payload.get("tips"):
    +2073            for raw_tip in raw_tips:
    +2074                if raw_tip == typedefs.Unknown:
    +2075                    raw_tip = undefined.Undefined
    +2076                tips.append(raw_tip)
    +2077
    +2078        return milestones.MilestoneContent(
    +2079            about=about, status=status, tips=tips, items=items_categoris
    +2080        )
    +
    -

    Calls the async function on each item in the iterator concurrently.

    -
    Example
    +

    Deserialize a JSON payload of milestone content information.

    -
    async def signup(username: str) -> None:
    -    async with aiohttp.request('POST', '...') as r:
    -        # Actual logic.
    -        ...
    +
    Parameters
    -async def main(): - users = aiobungie.into_iter(["user_danny", "user_jojo"]) - await users.async_for_each(lambda username: signup(username)) -
    + -
    Parameters
    +
    Returns
      -
    • func (collections.Callable[[Item], collections.Coroutine[None, None, None]]): -The async function to call on each item in the iterator.
    • +
    • aiobungie.crates.MilestoneContent: A milestone content.
    -
    - +
    +
    def - enumerate( self, *, start: int = 0) -> aiobungie.FlatIterator[tuple[int, ~Item]]: - - - -
    - -
    531    def enumerate(self, *, start: int = 0) -> FlatIterator[tuple[int, Item]]:
    -532        """Returns a new iterator that yields tuples of the index and item.
    -533
    -534        Example
    -535        -------
    -536        ```py
    -537        iterator = FlatIterator([1, 2, 3])
    -538        for index, item in iterator.enumerate():
    -539            print(index, item)
    -540        # 0 1
    -541        # 1 2
    -542        # 2 3
    -543        ```
    -544
    -545        Raises
    -546        ------
    -547        `StopIteration`
    -548            If no elements are left in the iterator.
    -549        """
    -550        return FlatIterator(enumerate(self._items, start=start))
    -
    + deserialize_friend( self, payload: dict[str, typing.Any], /) -> aiobungie.crates.friends.Friend: + -

    Returns a new iterator that yields tuples of the index and item.

    +
    + +
    2082    def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend:
    +2083        name = undefined.Undefined
    +2084        if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown:
    +2085            name = raw_name
    +2086
    +2087        bungie_user: typedefs.NoneOr[user.BungieUser] = None
    +2088
    +2089        if raw_bungie_user := payload.get("bungieNetUser"):
    +2090            bungie_user = self.deserialize_bungie_user(raw_bungie_user)
    +2091
    +2092        return friends.Friend(
    +2093            net=self._net,
    +2094            id=int(payload["lastSeenAsMembershipId"]),
    +2095            name=name,
    +2096            code=payload.get("bungieGlobalDisplayNameCode"),
    +2097            relationship=enums.Relationship(payload["relationship"]),
    +2098            user=bungie_user,
    +2099            online_status=enums.Presence(payload["onlineStatus"]),
    +2100            online_title=payload["onlineTitle"],
    +2101            type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]),
    +2102        )
    +
    -
    Example
    -
    iterator = FlatIterator([1, 2, 3])
    -for index, item in iterator.enumerate():
    -    print(index, item)
    -# 0 1
    -# 1 2
    -# 2 3
    -
    +

    Deserialize a JSON payload of a Bungie friend information.

    + +
    Parameters
    -
    Raises
    + + +
    Returns
    -
    -
    - -
    -
    @attrs.define(auto_exc=True)
    - - class - Forbidden(aiobungie.HTTPException): +
    + +
    + + def + deserialize_friends( self, payload: dict[str, typing.Any]) -> collections.abc.Sequence[aiobungie.crates.friends.Friend]: - +
    - -
    120@attrs.define(auto_exc=True)
    -121class Forbidden(HTTPException):
    -122    """Exception that's raised for when status code 403 occurs."""
    -123
    -124    http_status: http.HTTPStatus = attrs.field(
    -125        default=http.HTTPStatus.FORBIDDEN, init=False
    -126    )
    +    
    +            
    2104    def deserialize_friends(
    +2105        self, payload: typedefs.JSONObject
    +2106    ) -> collections.Sequence[friends.Friend]:
    +2107        mut_seq: typing.MutableSequence[friends.Friend] = []
    +2108        if raw_friends := payload.get("friends"):
    +2109            for friend in raw_friends:
    +2110                mut_seq.append(self.deserialize_friend(friend))
    +2111        return mut_seq
     
    -

    Exception that's raised for when status code 403 occurs.

    +

    Deserialize a JSON sequence of Bungie friends information.

    + +

    This is usually used to deserialize the incoming/outgoing friend requests.

    + +
    Parameters
    + + + +
    Returns
    + +
    -
    - +
    +
    +
    - Forbidden( *, error_code: int, throttle_seconds: int, url: Union[str, yarl.URL, NoneType], body: Any, headers: multidict._multidict.CIMultiDictProxy[str], message: str, error_status: str, message_data: dict[str, str]) + def + deserialize_friend_requests( self, payload: dict[str, typing.Any]) -> aiobungie.crates.friends.FriendRequestView: - +
    - -
     2def __init__(self, *, error_code, throttle_seconds, url, body, headers, message, error_status, message_data):
    - 3    self.error_code = error_code
    - 4    self.throttle_seconds = throttle_seconds
    - 5    self.url = url
    - 6    self.body = body
    - 7    self.headers = headers
    - 8    self.message = message
    - 9    self.error_status = error_status
    -10    self.message_data = message_data
    -11    self.http_status = attr_dict['http_status'].default
    -12    BaseException.__init__(self, self.error_code,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
    +    
    +            
    2113    def deserialize_friend_requests(
    +2114        self, payload: typedefs.JSONObject
    +2115    ) -> friends.FriendRequestView:
    +2116        incoming: typing.MutableSequence[friends.Friend] = []
    +2117        outgoing: typing.MutableSequence[friends.Friend] = []
    +2118
    +2119        if raw_incoming_requests := payload.get("incomingRequests"):
    +2120            for incoming_request in raw_incoming_requests:
    +2121                incoming.append(self.deserialize_friend(incoming_request))
    +2122
    +2123        if raw_outgoing_requests := payload.get("outgoingRequests"):
    +2124            for outgoing_request in raw_outgoing_requests:
    +2125                outgoing.append(self.deserialize_friend(outgoing_request))
    +2126
    +2127        return friends.FriendRequestView(incoming=incoming, outgoing=outgoing)
     
    -

    Method generated by attrs for class Forbidden.

    -
    +

    Deserialize a JSON sequence of Bungie friend requests information.

    +

    This is used for incoming/outgoing friend requests.

    -
    -
    -
    - http_status: http.HTTPStatus +
    Parameters
    - -
    - - -

    The request response http status.

    -
    + +
    Returns
    -
    -
    -
    Inherited Members
    -
    -
    HTTPException
    -
    error_code
    -
    throttle_seconds
    -
    url
    -
    body
    -
    headers
    -
    message
    -
    error_status
    -
    message_data
    + +
    -
    -
    builtins.BaseException
    -
    with_traceback
    -
    args
    -
    -
    -
    -
    - -
    -
    @typing.final
    - - class - GameMode(builtins.int, aiobungie.Enum): +
    + +
    + + def + deserialize_fireteams( self, payload: dict[str, typing.Any]) -> Optional[collections.abc.Sequence[aiobungie.crates.fireteams.Fireteam]]: - +
    - -
    274@typing.final
    -275class GameMode(int, Enum):
    -276    """An Enum for all available gamemodes in Destiny 2."""
    -277
    -278    NONE = 0
    -279    STORY = 2
    -280    STRIKE = 3
    -281    RAID = 4
    -282    ALLPVP = 5
    -283    PATROL = 6
    -284    ALLPVE = 7
    -285    RESERVED9 = 9
    -286    CONTROL = 10
    -287    RESERVED11 = 11
    -288    CLASH = 12
    -289    RESERVED13 = 13
    -290    CRIMSONDOUBLES = 15
    -291    NIGHTFALL = 16
    -292    HEROICNIGHTFALL = 17
    -293    ALLSTRIKES = 18
    -294    IRONBANNER = 19
    -295    RESERVED20 = 20
    -296    RESERVED21 = 21
    -297    RESERVED22 = 22
    -298    RESERVED24 = 24
    -299    ALLMAYHEM = 25
    -300    RESERVED26 = 26
    -301    RESERVED27 = 27
    -302    RESERVED28 = 28
    -303    RESERVED29 = 29
    -304    RESERVED30 = 30
    -305    SUPREMACY = 31
    -306    PRIVATEMATCHESALL = 32
    -307    SURVIVAL = 37
    -308    COUNTDOWN = 38
    -309    TRIALSOFTHENINE = 39
    -310    SOCIAL = 40
    -311    TRIALSCOUNTDOWN = 41
    -312    TRIALSSURVIVAL = 42
    -313    IRONBANNERCONTROL = 43
    -314    IRONBANNERCLASH = 44
    -315    IRONBANNERSUPREMACY = 45
    -316    SCOREDNIGHTFALL = 46
    -317    SCOREDHEROICNIGHTFALL = 47
    -318    RUMBLE = 48
    -319    ALLDOUBLES = 49
    -320    DOUBLES = 50
    -321    PRIVATEMATCHESCLASH = 51
    -322    PRIVATEMATCHESCONTROL = 52
    -323    PRIVATEMATCHESSUPREMACY = 53
    -324    PRIVATEMATCHESCOUNTDOWN = 54
    -325    PRIVATEMATCHESSURVIVAL = 55
    -326    PRIVATEMATCHESMAYHEM = 56
    -327    PRIVATEMATCHESRUMBLE = 57
    -328    HEROICADVENTURE = 58
    -329    SHOWDOWN = 59
    -330    LOCKDOWN = 60
    -331    SCORCHED = 61
    -332    SCORCHEDTEAM = 62
    -333    GAMBIT = 63
    -334    ALLPVECOMPETITIVE = 64
    -335    BREAKTHROUGH = 65
    -336    BLACKARMORYRUN = 66
    -337    SALVAGE = 67
    -338    IRONBANNERSALVAGE = 68
    -339    PVPCOMPETITIVE = 69
    -340    PVPQUICKPLAY = 70
    -341    CLASHQUICKPLAY = 71
    -342    CLASHCOMPETITIVE = 72
    -343    CONTROLQUICKPLAY = 73
    -344    CONTROLCOMPETITIVE = 74
    -345    GAMBITPRIME = 75
    -346    RECKONING = 76
    -347    MENAGERIE = 77
    -348    VEXOFFENSIVE = 78
    -349    NIGHTMAREHUNT = 79
    -350    ELIMINATION = 80
    -351    MOMENTUM = 81
    -352    DUNGEON = 82
    -353    SUNDIAL = 83
    -354    TRIALS_OF_OSIRIS = 84
    -355    DARES = 85
    -356    OFFENSIVE = 86
    -357    LOSTSECTOR = 87
    -358    RIFT = 88
    -359    ZONECONTROL = 89
    -360    IRONBANNERRIFT = 90
    +    
    +            
    2152    def deserialize_fireteams(
    +2153        self, payload: typedefs.JSONObject
    +2154    ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]:
    +2155        fireteams_: typing.MutableSequence[fireteams.Fireteam] = []
    +2156
    +2157        result: list[typedefs.JSONObject]
    +2158        if not (result := payload["results"]):
    +2159            return None
    +2160        for elem in result:
    +2161            fireteams_.append(
    +2162                self._set_fireteam_fields(
    +2163                    elem, total_results=int(payload["totalResults"])
    +2164                )
    +2165            )
    +2166        return fireteams_
     
    -

    An Enum for all available gamemodes in Destiny 2.

    -
    +

    Deserialize a JSON sequence of Bungie fireteams information.

    +
    Parameters
    -
    -
    - NONE = <GameMode.NONE: 0> + - -
    - - - +
    Returns
    -
    -
    -
    - STORY = <GameMode.STORY: 2> + +
    - -
    - - -
    -
    -
    - STRIKE = <GameMode.STRIKE: 3> - - -
    - - - +
    + +
    + + def + deserialize_fireteam_destiny_users( self, payload: dict[str, typing.Any]) -> aiobungie.crates.fireteams.FireteamUser: -
    -
    -
    - RAID = <GameMode.RAID: 4> + -
    - - - - -
    -
    -
    - ALLPVP = <GameMode.ALLPVP: 5> + +
    2168    def deserialize_fireteam_destiny_users(
    +2169        self, payload: typedefs.JSONObject
    +2170    ) -> fireteams.FireteamUser:
    +2171        destiny_obj = self.deserialize_destiny_membership(payload)
    +2172        # We could helpers.just return a DestinyMembership object but this is
    +2173        # missing the fireteam display name and id fields.
    +2174        return fireteams.FireteamUser(
    +2175            net=self._net,
    +2176            id=destiny_obj.id,
    +2177            code=destiny_obj.code,
    +2178            icon=destiny_obj.icon,
    +2179            types=destiny_obj.types,
    +2180            type=destiny_obj.type,
    +2181            is_public=destiny_obj.is_public,
    +2182            crossave_override=destiny_obj.crossave_override,
    +2183            name=destiny_obj.name,
    +2184            last_seen_name=destiny_obj.last_seen_name,
    +2185            fireteam_display_name=payload["FireteamDisplayName"],
    +2186            fireteam_membership_id=enums.MembershipType(
    +2187                payload["FireteamMembershipType"]
    +2188            ),
    +2189        )
    +
    - -
    - - - -
    -
    -
    - PATROL = <GameMode.PATROL: 6> +

    Deserialize a JSON payload of Bungie fireteam destiny users information.

    - -
    - - - +
    Parameters
    -
    -
    -
    - ALLPVE = <GameMode.ALLPVE: 7> + - -
    - - - +
    Returns
    -
    -
    -
    - RESERVED9 = <GameMode.RESERVED9: 9> + +
    - -
    - - -
    -
    -
    - CONTROL = <GameMode.CONTROL: 10> +
    + +
    + + def + deserialize_fireteam_members( self, payload: dict[str, typing.Any], *, alternatives: bool = False) -> Optional[collections.abc.Sequence[aiobungie.crates.fireteams.FireteamMember]]: + + -
    - - - + +
    2191    def deserialize_fireteam_members(
    +2192        self, payload: typedefs.JSONObject, *, alternatives: bool = False
    +2193    ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]:
    +2194        members_: list[fireteams.FireteamMember] = []
    +2195        if members := payload.get("Members" if not alternatives else "Alternates"):
    +2196            for member in members:
    +2197                bungie_fields = self.deserialize_partial_bungie_user(member)
    +2198                members_fields = fireteams.FireteamMember(
    +2199                    destiny_user=self.deserialize_fireteam_destiny_users(member),
    +2200                    has_microphone=member["hasMicrophone"],
    +2201                    character_id=int(member["characterId"]),
    +2202                    date_joined=time.clean_date(member["dateJoined"]),
    +2203                    last_platform_invite_date=time.clean_date(
    +2204                        member["lastPlatformInviteAttemptDate"]
    +2205                    ),
    +2206                    last_platform_invite_result=int(
    +2207                        member["lastPlatformInviteAttemptResult"]
    +2208                    ),
    +2209                    net=self._net,
    +2210                    name=bungie_fields.name,
    +2211                    id=bungie_fields.id,
    +2212                    icon=bungie_fields.icon,
    +2213                    is_public=bungie_fields.is_public,
    +2214                    crossave_override=bungie_fields.crossave_override,
    +2215                    types=bungie_fields.types,
    +2216                    type=bungie_fields.type,
    +2217                )
    +2218                members_.append(members_fields)
    +2219        else:
    +2220            return None
    +2221        return members_
    +
    -
    -
    -
    - RESERVED11 = <GameMode.RESERVED11: 11> - -
    - - - +

    Deserialize a JSON sequence of Bungie fireteam members information.

    -
    -
    -
    - CLASH = <GameMode.CLASH: 12> +
    Parameters
    - -
    - - - +
      +
    • payload (aiobungie.typedefs.JSONObject): +The JSON payload.
    • +
    • alternatives (bool): +If set to True, Then it will deserialize the alternatives data in the payload. +If not the it will just deserialize the members data.
    • +
    -
    -
    -
    - RESERVED13 = <GameMode.RESERVED13: 13> +
    Returns
    + + +
    - -
    - - -
    -
    -
    - CRIMSONDOUBLES = <GameMode.CRIMSONDOUBLES: 15> +
    + +
    + + def + deserialize_available_fireteams( self, data: dict[str, typing.Any], *, no_results: bool = False) -> Union[aiobungie.crates.fireteams.AvailableFireteam, collections.abc.Sequence[aiobungie.crates.fireteams.AvailableFireteam]]: + + -
    - - - + +
    2223    def deserialize_available_fireteams(
    +2224        self,
    +2225        data: typedefs.JSONObject,
    +2226        *,
    +2227        no_results: bool = False,
    +2228    ) -> typing.Union[
    +2229        fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam]
    +2230    ]:
    +2231        fireteams_: list[fireteams.AvailableFireteam] = []
    +2232
    +2233        # This needs to be used outside the results
    +2234        # JSON key.
    +2235        if no_results is True:
    +2236            payload = data
    +2237
    +2238        if result := payload.get("results"):
    +2239
    +2240            for fireteam in result:
    +2241                found_fireteams = self._set_fireteam_fields(fireteam["Summary"])
    +2242                fireteams_fields = fireteams.AvailableFireteam(
    +2243                    id=found_fireteams.id,
    +2244                    group_id=found_fireteams.group_id,
    +2245                    platform=found_fireteams.platform,
    +2246                    activity_type=found_fireteams.activity_type,
    +2247                    is_immediate=found_fireteams.is_immediate,
    +2248                    is_public=found_fireteams.is_public,
    +2249                    is_valid=found_fireteams.is_valid,
    +2250                    owner_id=found_fireteams.owner_id,
    +2251                    player_slot_count=found_fireteams.player_slot_count,
    +2252                    available_player_slots=found_fireteams.available_player_slots,
    +2253                    available_alternate_slots=found_fireteams.available_alternate_slots,
    +2254                    title=found_fireteams.title,
    +2255                    date_created=found_fireteams.date_created,
    +2256                    locale=found_fireteams.locale,
    +2257                    last_modified=found_fireteams.last_modified,
    +2258                    total_results=found_fireteams.total_results,
    +2259                    members=self.deserialize_fireteam_members(payload),
    +2260                    alternatives=self.deserialize_fireteam_members(
    +2261                        payload, alternatives=True
    +2262                    ),
    +2263                )
    +2264            fireteams_.append(fireteams_fields)
    +2265            if no_results:
    +2266                return fireteams_fields
    +2267        return fireteams_
    +
    -
    -
    -
    - NIGHTFALL = <GameMode.NIGHTFALL: 16> - -
    - - - +

    Deserialize a JSON payload of a sequence of/fireteam information.

    -
    -
    -
    - HEROICNIGHTFALL = <GameMode.HEROICNIGHTFALL: 17> +
    Parameters
    - -
    - - - +
      +
    • payload (aiobungie.typedefs.JSONObject): +The JSON payload.
    • +
    • no_results (bool): +Whether to deserialize the data from results in the payload or not.
    • +
    -
    -
    -
    - ALLSTRIKES = <GameMode.ALLSTRIKES: 18> +
    Returns
    + +
      +
    • typing.Union[aiobungie.crates.fireteams.AvailableFireteam, collections.Sequence[aiobungie.crates.fireteams.AvailableFireteam]] # noqa (E501): +An available fireteam or a sequence of available fireteam.
    • +
    +
    - -
    - - -
    -
    -
    - IRONBANNER = <GameMode.IRONBANNER: 19> +
    + +
    + + def + deserialize_fireteam_party( self, payload: dict[str, typing.Any]) -> aiobungie.crates.fireteams.FireteamParty: + + -
    - - - + +
    2269    def deserialize_fireteam_party(
    +2270        self, payload: typedefs.JSONObject
    +2271    ) -> fireteams.FireteamParty:
    +2272        last_destination_hash: typing.Optional[int] = None
    +2273        if raw_dest_hash := payload.get("lastOrbitedDestinationHash"):
    +2274            last_destination_hash = int(raw_dest_hash)
    +2275
    +2276        return fireteams.FireteamParty(
    +2277            members=[
    +2278                self._deserialize_fireteam_party_member(member)
    +2279                for member in payload["partyMembers"]
    +2280            ],
    +2281            activity=self._deserialize_fireteam_party_current_activity(
    +2282                payload["currentActivity"]
    +2283            ),
    +2284            settings=self._deserialize_fireteam_party_settings(payload["joinability"]),
    +2285            last_destination_hash=last_destination_hash,
    +2286            tracking=payload["tracking"],
    +2287        )
    +
    -
    -
    -
    - RESERVED20 = <GameMode.RESERVED20: 20> - -
    - - - +

    Deserialize a JSON payload of profileTransitory component response.

    -
    -
    -
    - RESERVED21 = <GameMode.RESERVED21: 21> +
    Parameters
    - -
    - - - + -
    -
    -
    - RESERVED22 = <GameMode.RESERVED22: 22> +
    Returns
    + + +
    - -
    - - -
    -
    -
    - RESERVED24 = <GameMode.RESERVED24: 24> +
    + +
    + + def + deserialize_seasonal_artifact(self, payload: dict[str, typing.Any]) -> aiobungie.crates.season.Artifact: + + -
    - - - + +
    2334    def deserialize_seasonal_artifact(
    +2335        self, payload: typedefs.JSONObject
    +2336    ) -> season.Artifact:
    +2337        if raw_artifact := payload.get("seasonalArtifact"):
    +2338            if points := raw_artifact.get("pointProgression"):
    +2339                points_prog = progressions.Progression(
    +2340                    hash=points["progressionHash"],
    +2341                    level=points["level"],
    +2342                    cap=points["levelCap"],
    +2343                    daily_limit=points["dailyLimit"],
    +2344                    weekly_limit=points["weeklyLimit"],
    +2345                    current_progress=points["currentProgress"],
    +2346                    daily_progress=points["dailyProgress"],
    +2347                    needed=points["progressToNextLevel"],
    +2348                    next_level=points["nextLevelAt"],
    +2349                )
    +2350
    +2351            if bonus := raw_artifact.get("powerBonusProgression"):
    +2352                power_bonus_prog = progressions.Progression(
    +2353                    hash=bonus["progressionHash"],
    +2354                    level=bonus["level"],
    +2355                    cap=bonus["levelCap"],
    +2356                    daily_limit=bonus["dailyLimit"],
    +2357                    weekly_limit=bonus["weeklyLimit"],
    +2358                    current_progress=bonus["currentProgress"],
    +2359                    daily_progress=bonus["dailyProgress"],
    +2360                    needed=bonus["progressToNextLevel"],
    +2361                    next_level=bonus["nextLevelAt"],
    +2362                )
    +2363            artifact = season.Artifact(
    +2364                net=self._net,
    +2365                hash=raw_artifact["artifactHash"],
    +2366                power_bonus=raw_artifact["powerBonus"],
    +2367                acquired_points=raw_artifact["pointsAcquired"],
    +2368                bonus=power_bonus_prog,
    +2369                points=points_prog,
    +2370            )
    +2371        return artifact
    +
    -
    -
    -
    - ALLMAYHEM = <GameMode.ALLMAYHEM: 25> - -
    - - - +

    Deserialize a JSON payload of a Destiny 2 seasonal artifact information.

    -
    -
    -
    - RESERVED26 = <GameMode.RESERVED26: 26> +
    Parameters
    - -
    - - - +
      +
    • payload (aiobungie.internal.helpers.JsonObject): +The JSON payload.
    • +
    -
    -
    -
    - RESERVED27 = <GameMode.RESERVED27: 27> +
    Returns
    + + +
    - -
    - - -
    -
    -
    - RESERVED28 = <GameMode.RESERVED28: 28> +
    + +
    + + def + deserialize_profile_progression( self, payload: dict[str, typing.Any]) -> aiobungie.crates.profile.ProfileProgression: + + -
    - - - + +
    2373    def deserialize_profile_progression(
    +2374        self, payload: typedefs.JSONObject
    +2375    ) -> profile.ProfileProgression:
    +2376        return profile.ProfileProgression(
    +2377            artifact=self.deserialize_seasonal_artifact(payload["data"]),
    +2378            checklist={
    +2379                int(check_id): checklists
    +2380                for check_id, checklists in payload["data"]["checklists"].items()
    +2381            },
    +2382        )
    +
    -
    -
    -
    - RESERVED29 = <GameMode.RESERVED29: 29> - -
    - - - +

    Deserialize a JSON payload of a profile progression component.

    -
    -
    -
    - RESERVED30 = <GameMode.RESERVED30: 30> +
    Parameters
    - -
    - - - +
      +
    • payload (aiobungie.internal.helpers.JsonObject): +The JSON payload.
    • +
    -
    -
    -
    - SUPREMACY = <GameMode.SUPREMACY: 31> +
    Returns
    + + +
    - -
    - - -
    -
    -
    - PRIVATEMATCHESALL = <GameMode.PRIVATEMATCHESALL: 32> +
    + +
    + + def + deserialize_instanced_item( self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.ItemInstance: + + -
    - - - + +
    2384    def deserialize_instanced_item(
    +2385        self, payload: typedefs.JSONObject
    +2386    ) -> items.ItemInstance:
    +2387        damage_type_hash: typing.Optional[int] = None
    +2388        if raw_damagetype_hash := payload.get("damageTypeHash"):
    +2389            damage_type_hash = int(raw_damagetype_hash)
    +2390
    +2391        required_hashes: typing.Optional[collections.Collection[int]] = None
    +2392        if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"):
    +2393            required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes]
    +2394
    +2395        breaker_type: typing.Optional[items.ItemBreakerType] = None
    +2396        if raw_break_type := payload.get("breakerType"):
    +2397            breaker_type = items.ItemBreakerType(int(raw_break_type))
    +2398
    +2399        breaker_type_hash: typing.Optional[int] = None
    +2400        if raw_break_type_hash := payload.get("breakerTypeHash"):
    +2401            breaker_type_hash = int(raw_break_type_hash)
    +2402
    +2403        energy: typing.Optional[items.ItemEnergy] = None
    +2404        if raw_energy := payload.get("energy"):
    +2405            energy = self.deserialize_item_energy(raw_energy)
    +2406
    +2407        primary_stats = None
    +2408        if raw_primary_stats := payload.get("primaryStat"):
    +2409            primary_stats = self.deserialize_item_stats_view(raw_primary_stats)
    +2410
    +2411        return items.ItemInstance(
    +2412            damage_type=enums.DamageType(int(payload["damageType"])),
    +2413            damage_type_hash=damage_type_hash,
    +2414            primary_stat=primary_stats,
    +2415            item_level=int(payload["itemLevel"]),
    +2416            quality=int(payload["quality"]),
    +2417            is_equipped=payload["isEquipped"],
    +2418            can_equip=payload["canEquip"],
    +2419            equip_required_level=int(payload["equipRequiredLevel"]),
    +2420            required_equip_unlock_hashes=required_hashes,
    +2421            cant_equip_reason=int(payload["cannotEquipReason"]),
    +2422            breaker_type=breaker_type,
    +2423            breaker_type_hash=breaker_type_hash,
    +2424            energy=energy,
    +2425        )
    +
    -
    -
    -
    - SURVIVAL = <GameMode.SURVIVAL: 37> - -
    - - - +

    Deserialize a JSON object into an instanced item.

    -
    -
    -
    - COUNTDOWN = <GameMode.COUNTDOWN: 38> +
    Parameters
    - -
    - - - +
      +
    • payload (aiobungie.internal.helpers.JsonObject): +The JSON payload.
    • +
    -
    -
    -
    - TRIALSOFTHENINE = <GameMode.TRIALSOFTHENINE: 39> +
    Returns
    + + +
    - -
    - - -
    -
    -
    - SOCIAL = <GameMode.SOCIAL: 40> +
    + +
    + + def + deserialize_item_energy( self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.ItemEnergy: + + -
    - - - + +
    2427    def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy:
    +2428        energy_hash: typing.Optional[int] = None
    +2429        if raw_energy_hash := payload.get("energyTypeHash"):
    +2430            energy_hash = int(raw_energy_hash)
    +2431
    +2432        return items.ItemEnergy(
    +2433            hash=energy_hash,
    +2434            type=items.ItemEnergyType(int(payload["energyType"])),
    +2435            capacity=int(payload["energyCapacity"]),
    +2436            used_energy=int(payload["energyUsed"]),
    +2437            unused_energy=int(payload["energyUnused"]),
    +2438        )
    +
    -
    -
    -
    - TRIALSCOUNTDOWN = <GameMode.TRIALSCOUNTDOWN: 41> - -
    - -
    -
    -
    - TRIALSSURVIVAL = <GameMode.TRIALSSURVIVAL: 42> +
    + +
    + + def + deserialize_item_perk(self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.ItemPerk: + + -
    - - - + +
    2440    def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk:
    +2441        perk_hash: typing.Optional[int] = None
    +2442        if raw_perk_hash := payload.get("perkHash"):
    +2443            perk_hash = int(raw_perk_hash)
    +2444
    +2445        return items.ItemPerk(
    +2446            hash=perk_hash,
    +2447            icon=assets.Image(payload["iconPath"]),
    +2448            is_active=payload["isActive"],
    +2449            is_visible=payload["visible"],
    +2450        )
    +
    -
    -
    -
    - IRONBANNERCONTROL = <GameMode.IRONBANNERCONTROL: 43> - -
    - -
    -
    -
    - IRONBANNERCLASH = <GameMode.IRONBANNERCLASH: 44> +
    + +
    + + def + deserialize_item_socket( self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.ItemSocket: + + -
    - - - + +
    2452    def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket:
    +2453        plug_hash: typing.Optional[int] = None
    +2454        if raw_plug_hash := payload.get("plugHash"):
    +2455            plug_hash = int(raw_plug_hash)
    +2456
    +2457        enable_fail_indexes: typing.Optional[list[int]] = None
    +2458        if raw_indexes := payload.get("enableFailIndexes"):
    +2459            enable_fail_indexes = [int(index) for index in raw_indexes]
    +2460
    +2461        return items.ItemSocket(
    +2462            plug_hash=plug_hash,
    +2463            is_enabled=payload["isEnabled"],
    +2464            enable_fail_indexes=enable_fail_indexes,
    +2465            is_visible=payload.get("visible"),
    +2466        )
    +
    -
    -
    -
    - IRONBANNERSUPREMACY = <GameMode.IRONBANNERSUPREMACY: 45> - -
    - -
    -
    -
    - SCOREDNIGHTFALL = <GameMode.SCOREDNIGHTFALL: 46> +
    + +
    + + def + deserialize_item_stats_view( self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.ItemStatsView: + + -
    - - - + +
    2468    def deserialize_item_stats_view(
    +2469        self, payload: typedefs.JSONObject
    +2470    ) -> items.ItemStatsView:
    +2471        return items.ItemStatsView(
    +2472            stat_hash=payload.get("statHash"), value=payload.get("value")
    +2473        )
    +
    -
    -
    -
    - SCOREDHEROICNIGHTFALL = <GameMode.SCOREDHEROICNIGHTFALL: 47> - -
    - -
    -
    -
    - RUMBLE = <GameMode.RUMBLE: 48> +
    + +
    + + def + deserialize_plug_item_state( self, payload: dict[str, typing.Any]) -> aiobungie.crates.items.PlugItemState: + + -
    - - - + +
    2475    def deserialize_plug_item_state(
    +2476        self, payload: typedefs.JSONObject
    +2477    ) -> items.PlugItemState:
    +2478        item_hash: typing.Optional[int] = None
    +2479        if raw_item_hash := payload.get("plugItemHash"):
    +2480            item_hash = int(raw_item_hash)
    +2481
    +2482        insert_fail_indexes: typedefs.NoneOr[list[int]] = None
    +2483        if raw_fail_indexes := payload.get("insertFailIndexes"):
    +2484            insert_fail_indexes = [int(k) for k in raw_fail_indexes]
    +2485
    +2486        enable_fail_indexes: typedefs.NoneOr[list[int]] = None
    +2487        if raw_enabled_indexes := payload.get("enableFailIndexes"):
    +2488            enable_fail_indexes = [int(k) for k in raw_enabled_indexes]
    +2489
    +2490        return items.PlugItemState(
    +2491            item_hash=item_hash,
    +2492            insert_fail_indexes=insert_fail_indexes,
    +2493            enable_fail_indexes=enable_fail_indexes,
    +2494            is_enabled=payload["enabled"],
    +2495            can_insert=payload["canInsert"],
    +2496        )
    +
    -
    -
    -
    - ALLDOUBLES = <GameMode.ALLDOUBLES: 49> - -
    - -
    -
    -
    - DOUBLES = <GameMode.DOUBLES: 50> +
    +
    + +
    +
    @typing.final
    - -
    - - - + class + FireteamActivity(builtins.int, aiobungie.Enum): - -
    -
    - PRIVATEMATCHESCLASH = <GameMode.PRIVATEMATCHESCLASH: 51> + -
    - - - + +
     67@typing.final
    + 68class FireteamActivity(int, enums.Enum):
    + 69    """An enum for the fireteam activities."""
    + 70
    + 71    ALL = 0
    + 72    CRUCIBLE = 2
    + 73    TRIALS_OF_OSIRIS = 3
    + 74    NIGHTFALL = 4
    + 75    ANY = 5
    + 76    GAMBIT = 6
    + 77    BLIND_WELL = 7
    + 78    NIGHTMARE_HUNTS = 12
    + 79    ALTARS_OF_SORROWS = 14
    + 80    DUNGEON = 15
    + 81    RAID_LW = 20
    + 82    RAID_GOS = 21
    + 83    RAID_DSC = 22
    + 84    EXO_CHALLENGE = 23
    + 85    S12_WRATHBORN = 24
    + 86    EMPIRE_HUNTS = 25
    + 87    S13_BATTLEGROUNDS = 26
    + 88    EXOTIC_QUEST = 27
    + 89    RAID_VOG = 28
    + 90    S14_EXPUNGE = 30
    + 91    S15_ASTRAL_ALIGNMENT = 31
    + 92    S15_SHATTERED_RELAM = 32
    + 93    SHATTERED_THRONE = 33
    + 94    PROPHECY = 34
    + 95    PIT_OF_HERESY = 35
    + 96    DOE = 36
    + 97    """Dares of Eternity."""
    + 98    DUNGEON_GOA = 37
    + 99    """Grasp of Avarice."""
    +100    VOW_OF_THE_DISCPILE = 38
    +101    CAMPAIGN = 39
    +102    WELLSPRING = 40
    +103    S16_BATTLEGROUNDS = 41
    +104    S17_NIGHTMARE_CONTAINMENT = 44
    +105    S17_SEVER = 45
    +
    -
    -
    -
    - PRIVATEMATCHESCONTROL = <GameMode.PRIVATEMATCHESCONTROL: 52> - -
    - - - +

    An enum for the fireteam activities.

    +
    -
    -
    + +
    - PRIVATEMATCHESSUPREMACY = <GameMode.PRIVATEMATCHESSUPREMACY: 53> + DOE = <FireteamActivity.DOE: 36>
    - - + +

    Dares of Eternity.

    +
    +
    -
    +
    - PRIVATEMATCHESCOUNTDOWN = <GameMode.PRIVATEMATCHESCOUNTDOWN: 54> + DUNGEON_GOA = <FireteamActivity.DUNGEON_GOA: 37>
    - - + +

    Grasp of Avarice.

    +
    +
    -
    -
    - PRIVATEMATCHESSURVIVAL = <GameMode.PRIVATEMATCHESSURVIVAL: 55> +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    - -
    - - - +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    +
    -
    -
    - PRIVATEMATCHESMAYHEM = <GameMode.PRIVATEMATCHESMAYHEM: 56> +
    +
    + +
    +
    @typing.final
    - -
    - - - + class + FireteamDate(builtins.int, aiobungie.Enum): - -
    -
    - PRIVATEMATCHESRUMBLE = <GameMode.PRIVATEMATCHESRUMBLE: 57> + -
    - - - + +
    131@typing.final
    +132class FireteamDate(int, enums.Enum):
    +133    """An enum for fireteam date ranges."""
    +134
    +135    ALL = 0
    +136    NOW = 1
    +137    TODAY = 2
    +138    TWO_DAYS = 3
    +139    THIS_WEEK = 4
    +
    -
    -
    -
    - HEROICADVENTURE = <GameMode.HEROICADVENTURE: 58> - -
    - - - +

    An enum for fireteam date ranges.

    +
    -
    -
    -
    - SHOWDOWN = <GameMode.SHOWDOWN: 59> - -
    - - - +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    + +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    +
    -
    -
    - LOCKDOWN = <GameMode.LOCKDOWN: 60> +
    +
    + +
    +
    @typing.final
    - -
    - - - + class + FireteamLanguage(builtins.str, aiobungie.Enum): - -
    -
    - SCORCHED = <GameMode.SCORCHED: 61> + -
    - - - + +
    108@typing.final
    +109class FireteamLanguage(str, enums.Enum):
    +110    """An enum for fireteams languages filters."""
    +111
    +112    ALL = ""
    +113    ENGLISH = "en"
    +114    FRENCH = "fr"
    +115    ESPANOL = "es"
    +116    DEUTSCH = "de"
    +117    ITALIAN = "it"
    +118    JAPANESE = "ja"
    +119    PORTUGUESE = "pt-br"
    +120    RUSSIAN = "ru"
    +121    POLISH = "pl"
    +122    KOREAN = "ko"
    +123    # ? China
    +124    ZH_CHT = "zh-cht"
    +125    ZH_CHS = "zh-chs"
    +126
    +127    def __str__(self) -> str:
    +128        return str(self.value)
    +
    -
    -
    -
    - SCORCHEDTEAM = <GameMode.SCORCHEDTEAM: 62> - -
    - - - +

    An enum for fireteams languages filters.

    +
    -
    -
    -
    - GAMBIT = <GameMode.GAMBIT: 63> - -
    - - - +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    + +
    +
    builtins.str
    +
    encode
    +
    replace
    +
    split
    +
    rsplit
    +
    join
    +
    capitalize
    +
    casefold
    +
    title
    +
    center
    +
    count
    +
    expandtabs
    +
    find
    +
    partition
    +
    index
    +
    ljust
    +
    lower
    +
    lstrip
    +
    rfind
    +
    rindex
    +
    rjust
    +
    rstrip
    +
    rpartition
    +
    splitlines
    +
    strip
    +
    swapcase
    +
    translate
    +
    upper
    +
    startswith
    +
    endswith
    +
    removeprefix
    +
    removesuffix
    +
    isascii
    +
    islower
    +
    isupper
    +
    istitle
    +
    isspace
    +
    isdecimal
    +
    isdigit
    +
    isnumeric
    +
    isalpha
    +
    isalnum
    +
    isidentifier
    +
    isprintable
    +
    zfill
    +
    format
    +
    format_map
    +
    maketrans
    +
    +
    -
    -
    - ALLPVECOMPETITIVE = <GameMode.ALLPVECOMPETITIVE: 64> +
    +
    + +
    +
    @typing.final
    - -
    - - - + class + FireteamPlatform(builtins.int, aiobungie.Enum): - -
    -
    - BREAKTHROUGH = <GameMode.BREAKTHROUGH: 65> + -
    - - - - -
    -
    -
    - BLACKARMORYRUN = <GameMode.BLACKARMORYRUN: 66> + +
    54@typing.final
    +55class FireteamPlatform(int, enums.Enum):
    +56    """An enum for fireteam related to bungie fireteams.
    +57    This is different from the normal `aiobungie.MembershipType`.
    +58    """
    +59
    +60    ANY = 0
    +61    PSN_NETWORK = 1
    +62    XBOX_LIVE = 2
    +63    STEAM = 4
    +64    STADIA = 5
    +
    - -
    - - - -
    -
    -
    - SALVAGE = <GameMode.SALVAGE: 67> +

    An enum for fireteam related to bungie fireteams. +This is different from the normal aiobungie.MembershipType.

    +
    - -
    - - - -
    -
    -
    - IRONBANNERSALVAGE = <GameMode.IRONBANNERSALVAGE: 68> +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    - -
    - - - +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    +
    -
    -
    - PVPCOMPETITIVE = <GameMode.PVPCOMPETITIVE: 69> - - -
    - - - +
    +
    + +
    + + class + Flag(enum.Flag): -
    -
    -
    - PVPQUICKPLAY = <GameMode.PVPQUICKPLAY: 70> + -
    - - - - -
    -
    -
    - CLASHQUICKPLAY = <GameMode.CLASHQUICKPLAY: 71> + +
     97class Flag(__enum.Flag):
    + 98    """Builtin Python enum flag with extra handlings."""
    + 99
    +100    # Needs to type this here for mypy
    +101    _value_: int
    +102
    +103    @property
    +104    def name(self) -> str:  # type: ignore[override]
    +105        if self._name_ is None:
    +106            self._name_ = f"UNKNOWN {self._value_}"
    +107
    +108        return self._name_
    +109
    +110    @property
    +111    def value(self) -> int:  # type: ignore[override]
    +112        return self._value_
    +113
    +114    def __str__(self) -> str:
    +115        return self.name
    +116
    +117    def __repr__(self) -> str:
    +118        return f"<{type(self).__name__}.{self.name}: {self._value_!s}>"
    +119
    +120    def __int__(self) -> int:
    +121        if isinstance(self.value, _ITERABLE):
    +122            raise TypeError(
    +123                f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.",
    +124            )
    +125        return int(self.value)
    +126
    +127    def __or__(self, other: typing.Union[Flag, int]) -> Flag:
    +128        return self.__class__(self._value_ | int(other))
    +129
    +130    def __xor__(self, other: typing.Union[Flag, int]) -> Flag:
    +131        return self.__class__(self._value_ ^ int(other))
    +132
    +133    def __and__(self, other: typing.Union[Flag, int]) -> Flag:
    +134        return self.__class__(other & int(other))
    +135
    +136    def __invert__(self) -> Flag:
    +137        return self.__class__(~self._value_)
    +138
    +139    def __contains__(self, other: typing.Union[Flag, int]) -> bool:
    +140        return self.value & int(other) == int(other)
    +
    - -
    - - - -
    -
    -
    - CLASHCOMPETITIVE = <GameMode.CLASHCOMPETITIVE: 72> +

    Builtin Python enum flag with extra handlings.

    +
    - -
    - - - -
    -
    +
    - CONTROLQUICKPLAY = <GameMode.CONTROLQUICKPLAY: 73> + name: str
    - - + +

    The name of the Enum member.

    +
    -
    -
    -
    - CONTROLCOMPETITIVE = <GameMode.CONTROLCOMPETITIVE: 74> - - -
    - - -
    -
    +
    - GAMBITPRIME = <GameMode.GAMBITPRIME: 75> + value: int
    - - + +

    The value of the Enum member.

    +
    -
    -
    -
    - RECKONING = <GameMode.RECKONING: 76> - - -
    - - -
    -
    -
    - MENAGERIE = <GameMode.MENAGERIE: 77> +
    +
    + +
    +
    @attrs.define(auto_exc=True)
    - -
    - - - + class + Forbidden(aiobungie.HTTPException): - -
    -
    - VEXOFFENSIVE = <GameMode.VEXOFFENSIVE: 78> + -
    - - - + +
    120@attrs.define(auto_exc=True)
    +121class Forbidden(HTTPException):
    +122    """Exception that's raised for when status code 403 occurs."""
    +123
    +124    http_status: http.HTTPStatus = attrs.field(
    +125        default=http.HTTPStatus.FORBIDDEN, init=False
    +126    )
    +
    -
    -
    -
    - NIGHTMAREHUNT = <GameMode.NIGHTMAREHUNT: 79> - -
    - - - +

    Exception that's raised for when status code 403 occurs.

    +
    -
    -
    -
    - ELIMINATION = <GameMode.ELIMINATION: 80> - -
    - - - +
    + +
    + + Forbidden( *, error_code: int, throttle_seconds: int, url: Union[str, yarl.URL, NoneType], body: Any, headers: multidict._multidict.CIMultiDictProxy[str], message: str, error_status: str, message_data: dict[str, str]) -
    -
    -
    - MOMENTUM = <GameMode.MOMENTUM: 81> + -
    - - - - -
    -
    -
    - DUNGEON = <GameMode.DUNGEON: 82> + +
     2def __init__(self, *, error_code, throttle_seconds, url, body, headers, message, error_status, message_data):
    + 3    self.error_code = error_code
    + 4    self.throttle_seconds = throttle_seconds
    + 5    self.url = url
    + 6    self.body = body
    + 7    self.headers = headers
    + 8    self.message = message
    + 9    self.error_status = error_status
    +10    self.message_data = message_data
    +11    self.http_status = attr_dict['http_status'].default
    +12    BaseException.__init__(self, self.error_code,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
    +
    - -
    - - - -
    -
    -
    - SUNDIAL = <GameMode.SUNDIAL: 83> +

    Method generated by attrs for class Forbidden.

    +
    - -
    - - -
    -
    +
    - TRIALS_OF_OSIRIS = <GameMode.TRIALS_OF_OSIRIS: 84> + http_status: http.HTTPStatus
    - - + +

    The request response http status.

    +
    -
    -
    -
    - DARES = <GameMode.DARES: 85> - - -
    - - -
    -
    -
    - OFFENSIVE = <GameMode.OFFENSIVE: 86> +
    +
    Inherited Members
    +
    + - - - +
    +
    builtins.BaseException
    +
    with_traceback
    +
    +
    -
    -
    - LOSTSECTOR = <GameMode.LOSTSECTOR: 87> +
    +
    + +
    +
    @typing.final
    - -
    - - - + class + GameMode(builtins.int, aiobungie.Enum): - -
    -
    - RIFT = <GameMode.RIFT: 88> + -
    - - - - -
    -
    -
    - ZONECONTROL = <GameMode.ZONECONTROL: 89> + +
    269@typing.final
    +270class GameMode(int, Enum):
    +271    """An Enum for all available gamemodes in Destiny 2."""
    +272
    +273    NONE = 0
    +274    STORY = 2
    +275    STRIKE = 3
    +276    RAID = 4
    +277    ALLPVP = 5
    +278    PATROL = 6
    +279    ALLPVE = 7
    +280    RESERVED9 = 9
    +281    CONTROL = 10
    +282    RESERVED11 = 11
    +283    CLASH = 12
    +284    RESERVED13 = 13
    +285    CRIMSONDOUBLES = 15
    +286    NIGHTFALL = 16
    +287    HEROICNIGHTFALL = 17
    +288    ALLSTRIKES = 18
    +289    IRONBANNER = 19
    +290    RESERVED20 = 20
    +291    RESERVED21 = 21
    +292    RESERVED22 = 22
    +293    RESERVED24 = 24
    +294    ALLMAYHEM = 25
    +295    RESERVED26 = 26
    +296    RESERVED27 = 27
    +297    RESERVED28 = 28
    +298    RESERVED29 = 29
    +299    RESERVED30 = 30
    +300    SUPREMACY = 31
    +301    PRIVATEMATCHESALL = 32
    +302    SURVIVAL = 37
    +303    COUNTDOWN = 38
    +304    TRIALSOFTHENINE = 39
    +305    SOCIAL = 40
    +306    TRIALSCOUNTDOWN = 41
    +307    TRIALSSURVIVAL = 42
    +308    IRONBANNERCONTROL = 43
    +309    IRONBANNERCLASH = 44
    +310    IRONBANNERSUPREMACY = 45
    +311    SCOREDNIGHTFALL = 46
    +312    SCOREDHEROICNIGHTFALL = 47
    +313    RUMBLE = 48
    +314    ALLDOUBLES = 49
    +315    DOUBLES = 50
    +316    PRIVATEMATCHESCLASH = 51
    +317    PRIVATEMATCHESCONTROL = 52
    +318    PRIVATEMATCHESSUPREMACY = 53
    +319    PRIVATEMATCHESCOUNTDOWN = 54
    +320    PRIVATEMATCHESSURVIVAL = 55
    +321    PRIVATEMATCHESMAYHEM = 56
    +322    PRIVATEMATCHESRUMBLE = 57
    +323    HEROICADVENTURE = 58
    +324    SHOWDOWN = 59
    +325    LOCKDOWN = 60
    +326    SCORCHED = 61
    +327    SCORCHEDTEAM = 62
    +328    GAMBIT = 63
    +329    ALLPVECOMPETITIVE = 64
    +330    BREAKTHROUGH = 65
    +331    BLACKARMORYRUN = 66
    +332    SALVAGE = 67
    +333    IRONBANNERSALVAGE = 68
    +334    PVPCOMPETITIVE = 69
    +335    PVPQUICKPLAY = 70
    +336    CLASHQUICKPLAY = 71
    +337    CLASHCOMPETITIVE = 72
    +338    CONTROLQUICKPLAY = 73
    +339    CONTROLCOMPETITIVE = 74
    +340    GAMBITPRIME = 75
    +341    RECKONING = 76
    +342    MENAGERIE = 77
    +343    VEXOFFENSIVE = 78
    +344    NIGHTMAREHUNT = 79
    +345    ELIMINATION = 80
    +346    MOMENTUM = 81
    +347    DUNGEON = 82
    +348    SUNDIAL = 83
    +349    TRIALS_OF_OSIRIS = 84
    +350    DARES = 85
    +351    OFFENSIVE = 86
    +352    LOSTSECTOR = 87
    +353    RIFT = 88
    +354    ZONECONTROL = 89
    +355    IRONBANNERRIFT = 90
    +
    - -
    - - - -
    -
    -
    - IRONBANNERRIFT = <GameMode.IRONBANNERRIFT: 90> +

    An Enum for all available gamemodes in Destiny 2.

    +
    - -
    - - - -
    Inherited Members
    @@ -19503,83 +14060,6 @@
    Inherited Members
    -
    -
    - NONE = <GatingScope.NONE: 0> - - -
    - - - - -
    -
    -
    - GLOBAL = <GatingScope.GLOBAL: 1> - - -
    - - - - -
    -
    -
    - CLAN = <GatingScope.CLAN: 2> - - -
    - - - - -
    -
    -
    - PROFILE = <GatingScope.PROFILE: 3> - - -
    - - - - -
    -
    -
    - CHARACTER = <GatingScope.CHARACTER: 4> - - -
    - - - - -
    -
    -
    - ITEM = <GatingScope.ITEM: 5> - - -
    - - - - -
    -
    -
    - ASSUMED_WORST_CASE = <GatingScope.ASSUMED_WORST_CASE: 6> - - -
    - - - - -
    Inherited Members
    @@ -19616,13 +14096,13 @@
    Inherited Members
    -
    487@typing.final
    -488class Gender(int, Enum):
    -489    """An Enum for Destiny Genders."""
    -490
    -491    MALE = 0
    -492    FEMALE = 1
    -493    UNKNOWN = 2
    +            
    484@typing.final
    +485class Gender(int, Enum):
    +486    """An Enum for Destiny Genders."""
    +487
    +488    MALE = 0
    +489    FEMALE = 1
    +490    UNKNOWN = 2
     
    @@ -19630,39 +14110,6 @@
    Inherited Members
    -
    -
    - MALE = <Gender.MALE: 0> - - -
    - - - - -
    -
    -
    - FEMALE = <Gender.FEMALE: 1> - - -
    - - - - -
    -
    -
    - UNKNOWN = <Gender.UNKNOWN: 2> - - -
    - - - - -
    Inherited Members
    @@ -19699,12 +14146,12 @@
    Inherited Members
    -
    656@typing.final
    -657class GroupType(int, Enum):
    -658    """An enums for the known bungie group types."""
    -659
    -660    GENERAL = 0
    -661    CLAN = 1
    +            
    653@typing.final
    +654class GroupType(int, Enum):
    +655    """An enums for the known bungie group types."""
    +656
    +657    GENERAL = 0
    +658    CLAN = 1
     
    @@ -19712,28 +14159,6 @@
    Inherited Members
    -
    -
    - GENERAL = <GroupType.GENERAL: 0> - - -
    - - - - -
    -
    -
    - CLAN = <GroupType.CLAN: 1> - - -
    - - - - -
    Inherited Members
    @@ -19839,7 +14264,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -20061,7 +14485,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -20252,7 +14675,8 @@
    Inherited Members
    Example
    -
    from aiobungie import Image
    +
    +
    from aiobungie import Image
     img = Image("img/destiny_content/pgcr/raid_eclipse.jpg")
     print(img)
     # https://www.bungie.net/img/destiny_content/pgcr/raid_eclipse.jpg
    @@ -20264,7 +14688,8 @@ 
    Example
    # Save the image to a file. await img.save("file_name", "/my/path/to/save/to", "jpeg") -
    +
    +
    Parameters
    @@ -20292,17 +14717,6 @@
    Parameters
    -
    -
    -
    - is_missing: bool - - -
    - - - -
    @@ -20640,7 +15054,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -20658,14 +15071,14 @@
    Inherited Members
    -
    722@typing.final
    -723class ItemBindStatus(int, Enum):
    -724    """An enum for Destiny 2 items bind status."""
    -725
    -726    NOT_BOUND = 0
    -727    BOUND_TO_CHARACTER = 1
    -728    BOUND_TO_ACCOUNT = 2
    -729    BOUNT_TO_GUILD = 3
    +            
    719@typing.final
    +720class ItemBindStatus(int, Enum):
    +721    """An enum for Destiny 2 items bind status."""
    +722
    +723    NOT_BOUND = 0
    +724    BOUND_TO_CHARACTER = 1
    +725    BOUND_TO_ACCOUNT = 2
    +726    BOUNT_TO_GUILD = 3
     
    @@ -20673,50 +15086,6 @@
    Inherited Members
    -
    -
    - NOT_BOUND = <ItemBindStatus.NOT_BOUND: 0> - - -
    - - - - -
    -
    -
    - BOUND_TO_CHARACTER = <ItemBindStatus.BOUND_TO_CHARACTER: 1> - - -
    - - - - -
    -
    -
    - BOUND_TO_ACCOUNT = <ItemBindStatus.BOUND_TO_ACCOUNT: 2> - - -
    - - - - -
    -
    -
    - BOUNT_TO_GUILD = <ItemBindStatus.BOUNT_TO_GUILD: 3> - - -
    - - - - -
    Inherited Members
    @@ -20753,15 +15122,15 @@
    Inherited Members
    -
    732@typing.final
    -733class ItemLocation(int, Enum):
    -734    """An enum for Destiny 2 items location."""
    -735
    -736    UNKNOWN = 0
    -737    INVENTORY = 1
    -738    VAULT = 2
    -739    VENDOR = 3
    -740    POSTMASTER = 4
    +            
    729@typing.final
    +730class ItemLocation(int, Enum):
    +731    """An enum for Destiny 2 items location."""
    +732
    +733    UNKNOWN = 0
    +734    INVENTORY = 1
    +735    VAULT = 2
    +736    VENDOR = 3
    +737    POSTMASTER = 4
     
    @@ -20769,61 +15138,6 @@
    Inherited Members
    -
    -
    - UNKNOWN = <ItemLocation.UNKNOWN: 0> - - -
    - - - - -
    -
    -
    - INVENTORY = <ItemLocation.INVENTORY: 1> - - -
    - - - - -
    -
    -
    - VAULT = <ItemLocation.VAULT: 2> - - -
    - - - - -
    -
    -
    - VENDOR = <ItemLocation.VENDOR: 3> - - -
    - - - - -
    -
    -
    - POSTMASTER = <ItemLocation.POSTMASTER: 4> - - -
    - - - - -
    Inherited Members
    @@ -20860,18 +15174,18 @@
    Inherited Members
    -
    757@typing.final
    -758class ItemState(Flag):
    -759    """An enum for Destiny 2 item states."""
    -760
    -761    NONE = 0
    -762    LOCKED = 1
    -763    TRACKED = 2
    -764    MASTERWORKED = 4
    -765    CRAFTED = 8
    -766    """If this bit is set, the item has been 'crafted' by the player."""
    -767    HIGHLITED_OBJECTIVE = 16
    -768    """If this bit is set, the item is a 'highlighted' objective."""
    +            
    754@typing.final
    +755class ItemState(Flag):
    +756    """An enum for Destiny 2 item states."""
    +757
    +758    NONE = 0
    +759    LOCKED = 1 << 0
    +760    TRACKED = 1 << 1
    +761    MASTERWORKED = 1 << 2
    +762    CRAFTED = 1 << 3
    +763    """If this bit is set, the item has been 'crafted' by the player."""
    +764    HIGHLITED_OBJECTIVE = 1 << 4
    +765    """If this bit is set, the item is a 'highlighted' objective."""
     
    @@ -20879,50 +15193,6 @@
    Inherited Members
    -
    -
    - NONE = <ItemState.NONE: 0> - - -
    - - - - -
    -
    -
    - LOCKED = <ItemState.LOCKED: 1> - - -
    - - - - -
    -
    -
    - TRACKED = <ItemState.TRACKED: 2> - - -
    - - - - -
    -
    -
    - MASTERWORKED = <ItemState.MASTERWORKED: 4> - - -
    - - - - -
    CRAFTED = <ItemState.CRAFTED: 8> @@ -20972,36 +15242,36 @@
    Inherited Members
    -
    589@typing.final
    -590class ItemSubType(int, Enum):
    -591    """An enum for Destiny 2 inventory items subtype."""
    -592
    -593    NONE = 0
    -594    AUTORIFLE = 6
    -595    SHOTGUN = 7
    -596    MACHINEGUN = 8
    -597    HANDCANNON = 9
    -598    ROCKETLAUNCHER = 10
    -599    FUSIONRIFLE = 11
    -600    SNIPERRIFLE = 12
    -601    PULSERIFLE = 13
    -602    SCOUTRIFLE = 14
    -603    SIDEARM = 17
    -604    SWORD = 18
    -605    MASK = 19
    -606    SHADER = 20
    -607    ORNAMENT = 21
    -608    FUSIONRIFLELINE = 22
    -609    GRENADELAUNCHER = 23
    -610    SUBMACHINEGUN = 24
    -611    TRACERIFLE = 25
    -612    HELMETARMOR = 26
    -613    GAUNTLETSARMOR = 27
    -614    CHESTARMOR = 28
    -615    LEGARMOR = 29
    -616    CLASSARMOR = 30
    -617    BOW = 31
    -618    DUMMYREPEATABLEBOUNTY = 32
    +            
    586@typing.final
    +587class ItemSubType(int, Enum):
    +588    """An enum for Destiny 2 inventory items subtype."""
    +589
    +590    NONE = 0
    +591    AUTORIFLE = 6
    +592    SHOTGUN = 7
    +593    MACHINEGUN = 8
    +594    HANDCANNON = 9
    +595    ROCKETLAUNCHER = 10
    +596    FUSIONRIFLE = 11
    +597    SNIPERRIFLE = 12
    +598    PULSERIFLE = 13
    +599    SCOUTRIFLE = 14
    +600    SIDEARM = 17
    +601    SWORD = 18
    +602    MASK = 19
    +603    SHADER = 20
    +604    ORNAMENT = 21
    +605    FUSIONRIFLELINE = 22
    +606    GRENADELAUNCHER = 23
    +607    SUBMACHINEGUN = 24
    +608    TRACERIFLE = 25
    +609    HELMETARMOR = 26
    +610    GAUNTLETSARMOR = 27
    +611    CHESTARMOR = 28
    +612    LEGARMOR = 29
    +613    CLASSARMOR = 30
    +614    BOW = 31
    +615    DUMMYREPEATABLEBOUNTY = 32
     
    @@ -21009,1008 +15279,1961 @@
    Inherited Members
    -
    -
    - NONE = <ItemSubType.NONE: 0> +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    - -
    - - - +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    +
    -
    -
    - AUTORIFLE = <ItemSubType.AUTORIFLE: 6> +
    +
    + +
    +
    @typing.final
    - -
    - - - + class + ItemTier(builtins.int, aiobungie.Enum): - -
    -
    - SHOTGUN = <ItemSubType.SHOTGUN: 7> + -
    - - - + +
    618@typing.final
    +619class ItemTier(int, Enum):
    +620    """An enum for a Destiny 2 item tier."""
    +621
    +622    NONE = 0
    +623    BASIC = 3340296461
    +624    COMMON = 2395677314
    +625    RARE = 2127292149
    +626    LEGENDERY = 4008398120
    +627    EXOTIC = 2759499571
    +
    + + +

    An enum for a Destiny 2 item tier.

    +
    + + +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    + +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    +
    -
    -
    - MACHINEGUN = <ItemSubType.MACHINEGUN: 8> +
    +
    + +
    +
    @typing.final
    + + class + ItemType(builtins.int, aiobungie.Enum): + + -
    - - - + +
    553@typing.final
    +554class ItemType(int, Enum):
    +555    """Enums for Destiny2's item types."""
    +556
    +557    NONE = 0
    +558    CURRENCY = 1
    +559    ARMOR = 2
    +560    WEAPON = 3
    +561    MESSAGE = 7
    +562    ENGRAM = 8
    +563    CONSUMABLE = 9
    +564    EXCHANGEMATERIAL = 10
    +565    MISSIONREWARD = 11
    +566    QUESTSTEP = 12
    +567    QUESTSTEPCOMPLETE = 13
    +568    EMBLEM = 14
    +569    QUEST = 15
    +570    SUBCLASS = 16
    +571    CLANBANNER = 17
    +572    AURA = 18
    +573    MOD = 19
    +574    DUMMY = 20
    +575    SHIP = 21
    +576    VEHICLE = 22
    +577    EMOTE = 23
    +578    GHOST = 24
    +579    PACKAGE = 25
    +580    BOUNTY = 26
    +581    WRAPPER = 27
    +582    SEASONALARTIFACT = 28
    +583    FINISHER = 29
    +
    + + +

    Enums for Destiny2's item types.

    +
    + + +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    + +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    +
    -
    -
    - HANDCANNON = <ItemSubType.HANDCANNON: 9> +
    +
    + +
    + + class + Iterator(typing.Generic[~Item]): + + + +
    + +
     45class Iterator(typing.Generic[Item]):
    + 46    """A Flat, In-Memory iterator for sequenced based data.
    + 47
    + 48    Example
    + 49    -------
    + 50    ```py
    + 51    iterator = Iterator([1, 2, 3])
    + 52
    + 53    # Map the results.
    + 54    for item in iterator.map(lambda item: item * 2):
    + 55        print(item)
    + 56    # 2
    + 57    # 4
    + 58
    + 59    # Indexing is also supported.
    + 60    print(iterator[0])
    + 61    # 1
    + 62
    + 63    # Normal iteration.
    + 64    for item in iterator:
    + 65        print(item)
    + 66    # 1
    + 67    # 2
    + 68    # 3
    + 69
    + 70    # Union two iterators.
    + 71    iterator2 = Iterator([4, 5, 6])
    + 72    final = iterator | iterator2
    + 73    # <Iterator([1, 2, 3, 4, 5, 6])>
    + 74    ```
    + 75
    + 76    Parameters
    + 77    ----------
    + 78    items: `collections.Iterable[Item]`
    + 79        The items to iterate over.
    + 80    """
    + 81
    + 82    __slots__ = ("_items",)
    + 83
    + 84    def __init__(self, items: collections.Iterable[Item]) -> None:
    + 85        self._items = iter(items)
    + 86
    + 87    @typing.overload
    + 88    def collect(self) -> list[Item]:
    + 89        ...
    + 90
    + 91    @typing.overload
    + 92    def collect(self, casting: _B) -> list[_B]:
    + 93        ...
    + 94
    + 95    def collect(
    + 96        self, casting: typing.Optional[_B] = None
    + 97    ) -> typing.Union[list[Item], list[_B]]:
    + 98        """Collects all items in the iterator into a list and cast them into an object if provided.
    + 99
    +100        Example
    +101        -------
    +102        >>> iterator = Iterator([1, 2, 3])
    +103        >>> iterator.collect(casting=str)
    +104        ["1", "2", "3"]
    +105
    +106        Parameters
    +107        ----------
    +108        casting: `T | None`
    +109            The type to cast the items to. If `None` is provided, the items will be returned as is.
    +110
    +111        Raises
    +112        ------
    +113        `StopIteration`
    +114            If no elements are left in the iterator.
    +115        """
    +116        if casting is not None:
    +117            return typing.cast(list[_B], list(map(casting, self._items)))
    +118
    +119        return list(self._items)
    +120
    +121    def next(self) -> Item:
    +122        """Returns the next item in the iterator.
    +123
    +124        Example
    +125        -------
    +126        ```py
    +127        iterator = Iterator(["1", "2", "3"])
    +128        item = iterator.next()
    +129        assert item == "1"
    +130        item = iterator.next()
    +131        assert item == "2"
    +132        ```
    +133
    +134        Raises
    +135        ------
    +136        `StopIteration`
    +137            If no elements are left in the iterator.
    +138        """
    +139        try:
    +140            return self.__next__()
    +141        except StopIteration:
    +142            self._ok()
    +143
    +144    def map(
    +145        self, predicate: collections.Callable[[Item], OtherItem]
    +146    ) -> Iterator[OtherItem]:
    +147        """Maps each item in the iterator to its predicated value.
    +148
    +149        Example
    +150        -------
    +151        ```py
    +152        iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value))
    +153        print(iterator)
    +154        # <Iterator([1, 2, 3])>
    +155        ```
    +156
    +157        Parameters
    +158        ----------
    +159        predicate: `collections.Callable[[Item], OtherItem]`
    +160            The function to map each item in the iterator to its predicated value.
    +161
    +162        Returns
    +163        -------
    +164        `Iterator[OtherItem]`
    +165            The mapped iterator.
    +166
    +167        Raises
    +168        ------
    +169        `StopIteration`
    +170            If no elements are left in the iterator.
    +171        """
    +172        return Iterator(map(predicate, self._items))
    +173
    +174    def take(self, n: int) -> Iterator[Item]:
    +175        """Take the first number of items until the number of items are yielded or
    +176        the end of the iterator is reached.
    +177
    +178        Example
    +179        -------
    +180        ```py
    +181        iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
    +182        print(iterator.take(2))
    +183        # <Iterator([GameMode.RAID, GameMode.STRIKE])>
    +184        ```
    +185
    +186        Parameters
    +187        ----------
    +188        n: `int`
    +189            The number of items to take.
    +190
    +191        Raises
    +192        ------
    +193        `StopIteration`
    +194            If no elements are left in the iterator.
    +195        """
    +196        return Iterator(itertools.islice(self._items, n))
    +197
    +198    def take_while(
    +199        self, predicate: collections.Callable[[Item], bool]
    +200    ) -> Iterator[Item]:
    +201        """Yields items from the iterator while predicate returns `True`.
    +202
    +203        Example
    +204        -------
    +205        ```py
    +206        iterator = Iterator([STEAM, XBOX, STADIA])
    +207        print(iterator.take_while(lambda platform: platform is not XBOX))
    +208        # <Iterator([STEAM])>
    +209        ```
    +210
    +211        Parameters
    +212        ----------
    +213        predicate: `collections.Callable[[Item], bool]`
    +214            The function to predicate each item in the iterator.
    +215
    +216        Raises
    +217        ------
    +218        `StopIteration`
    +219            If no elements are left in the iterator.
    +220        """
    +221        return Iterator(itertools.takewhile(predicate, self._items))
    +222
    +223    def drop_while(
    +224        self, predicate: collections.Callable[[Item], bool]
    +225    ) -> Iterator[Item]:
    +226        """Yields items from the iterator while predicate returns `False`.
    +227
    +228        Example
    +229        -------
    +230        ```py
    +231        iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
    +232        print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
    +233        # <Iterator([DestinyMembership(name="Bob")])>
    +234        ```
    +235
    +236        Parameters
    +237        ----------
    +238        predicate: `collections.Callable[[Item], bool]`
    +239            The function to predicate each item in the iterator.
    +240
    +241        Raises
    +242        ------
    +243        `StopIteration`
    +244            If no elements are left in the iterator.
    +245        """
    +246        return Iterator(itertools.dropwhile(predicate, self._items))
    +247
    +248    def filter(self, predicate: collections.Callable[[Item], bool]) -> Iterator[Item]:
    +249        """Filters the iterator to only yield items that match the predicate.
    +250
    +251        Example
    +252        -------
    +253        ```py
    +254        names = Iterator(["Jim", "Bob", "Mike", "Jess"])
    +255        print(names.filter(lambda n: n != "Jim"))
    +256        # <Iterator(["Bob", "Mike", "Jess"])>
    +257        ```
    +258        """
    +259        return Iterator(filter(predicate, self._items))
    +260
    +261    def skip(self, n: int) -> Iterator[Item]:
    +262        """Skips the first number of items in the iterator.
    +263
    +264        Example
    +265        -------
    +266        ```py
    +267        iterator = Iterator([STEAM, XBOX, STADIA])
    +268        print(iterator.skip(1))
    +269        # <Iterator([XBOX, STADIA])>
    +270        ```
    +271        """
    +272        return Iterator(itertools.islice(self._items, n, None))
    +273
    +274    def zip(self, other: Iterator[OtherItem]) -> Iterator[tuple[Item, OtherItem]]:
    +275        """Zips the iterator with another iterable.
    +276
    +277        Example
    +278        -------
    +279        ```py
    +280        iterator = Iterator([1, 3, 5])
    +281        other = Iterator([2, 4, 6])
    +282        for item, other_item in iterator.zip(other):
    +283            print(item, other_item)
    +284        # <Iterator([(1, 2), (3, 4), (5, 6)])>
    +285        ```
    +286
    +287        Parameters
    +288        ----------
    +289        other: `Iterator[OtherItem]`
    +290            The iterable to zip with.
    +291
    +292        Raises
    +293        ------
    +294        `StopIteration`
    +295            If no elements are left in the iterator.
    +296        """
    +297        return Iterator(zip(self._items, other))
    +298
    +299    def all(self, predicate: collections.Callable[[Item], bool]) -> bool:
    +300        """`True` if all items in the iterator match the predicate.
    +301
    +302        Example
    +303        -------
    +304        ```py
    +305        iterator = Iterator([1, 2, 3])
    +306        while iterator.all(lambda item: isinstance(item, int)):
    +307            print("Still all integers")
    +308            continue
    +309        # Still all integers
    +310        ```
    +311
    +312        Parameters
    +313        ----------
    +314        predicate: `collections.Callable[[Item], bool]`
    +315            The function to test each item in the iterator.
    +316
    +317        Raises
    +318        ------
    +319        `StopIteration`
    +320            If no elements are left in the iterator.
    +321        """
    +322        return all(predicate(item) for item in self)
    +323
    +324    def any(self, predicate: collections.Callable[[Item], bool]) -> bool:
    +325        """`True` if any items in the iterator match the predicate.
    +326
    +327        Example
    +328        -------
    +329        ```py
    +330        iterator = Iterator([1, 2, 3])
    +331        if iterator.any(lambda item: isinstance(item, int)):
    +332            print("At least one item is an int.")
    +333        # At least one item is an int.
    +334        ```
    +335
    +336        Parameters
    +337        ----------
    +338        predicate: `collections.Callable[[Item], bool]`
    +339            The function to test each item in the iterator.
    +340
    +341        Raises
    +342        ------
    +343        `StopIteration`
    +344            If no elements are left in the iterator.
    +345        """
    +346        return any(predicate(item) for item in self)
    +347
    +348    def sort(
    +349        self,
    +350        *,
    +351        key: collections.Callable[[Item], typeshed.SupportsRichComparison],
    +352        reverse: bool = False,
    +353    ) -> Iterator[Item]:
    +354        """Sorts the iterator.
    +355
    +356        Example
    +357        -------
    +358        ```py
    +359        iterator = Iterator([3, 1, 6, 7])
    +360        print(iterator.sort(key=lambda item: item))
    +361        # <Iterator([1, 3, 6, 7])>
    +362        ```
    +363
    +364        Parameters
    +365        ----------
    +366        key: `collections.Callable[[Item], Any]`
    +367            The function to sort by.
    +368        reverse: `bool`
    +369            Whether to reverse the sort.
    +370
    +371        Raises
    +372        ------
    +373        `StopIteration`
    +374            If no elements are left in the iterator.
    +375        """
    +376        return Iterator(sorted(self._items, key=key, reverse=reverse))
    +377
    +378    def first(self) -> Item:
    +379        """Returns the first item in the iterator.
    +380
    +381        Example
    +382        -------
    +383        ```py
    +384        iterator = Iterator([3, 1, 6, 7])
    +385        print(iterator.first())
    +386        3
    +387        ```
    +388
    +389        Raises
    +390        ------
    +391        `StopIteration`
    +392            If no elements are left in the iterator.
    +393        """
    +394        return self.take(1).next()
    +395
    +396    def reversed(self) -> Iterator[Item]:
    +397        """Returns a new iterator that yields the items in the iterator in reverse order.
    +398
    +399        Example
    +400        -------
    +401        ```py
    +402        iterator = Iterator([3, 1, 6, 7])
    +403        print(iterator.reversed())
    +404        # <Iterator([7, 6, 1, 3])>
    +405        ```
    +406
    +407        Raises
    +408        ------
    +409        `StopIteration`
    +410            If no elements are left in the iterator.
    +411        """
    +412        return Iterator(reversed(self.collect()))
    +413
    +414    def count(self) -> int:
    +415        """Returns the number of items in the iterator.
    +416
    +417        Example
    +418        -------
    +419        ```py
    +420        iterator = Iterator([3, 1, 6, 7])
    +421        print(iterator.count())
    +422        4
    +423        ```
    +424        """
    +425        count = 0
    +426        for _ in self:
    +427            count += 1
    +428
    +429        return count
    +430
    +431    def union(self, other: Iterator[Item]) -> Iterator[Item]:
    +432        """Returns a new iterator that yields all items from both iterators.
    +433
    +434        Example
    +435        -------
    +436        ```py
    +437        iterator = Iterator([1, 2, 3])
    +438        other = Iterator([4, 5, 6])
    +439        print(iterator.union(other))
    +440        # <Iterator([1, 2, 3, 4, 5, 6])>
    +441        ```
    +442
    +443        Parameters
    +444        ----------
    +445        other: `Iterator[Item]`
    +446            The iterable to union with.
    +447
    +448        Raises
    +449        ------
    +450        `StopIteration`
    +451            If no elements are left in the iterator.
    +452        """
    +453        return Iterator(itertools.chain(self._items, other))
    +454
    +455    def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None:
    +456        """Calls the function on each item in the iterator.
    +457
    +458        Example
    +459        -------
    +460        ```py
    +461        iterator = Iterator([1, 2, 3])
    +462        iterator.for_each(lambda item: print(item))
    +463        # 1
    +464        # 2
    +465        # 3
    +466        ```
    +467
    +468        Parameters
    +469        ----------
    +470        func: `typeshed.Callable[[Item], None]`
    +471            The function to call on each item in the iterator.
    +472        """
    +473        for item in self:
    +474            func(item)
    +475
    +476    async def async_for_each(
    +477        self,
    +478        func: collections.Callable[[Item], collections.Coroutine[None, None, None]],
    +479    ) -> None:
    +480        """Calls the async function on each item in the iterator concurrently.
    +481
    +482        Example
    +483        -------
    +484        ```py
    +485        async def signup(username: str) -> None:
    +486            async with aiohttp.request('POST', '...') as r:
    +487                # Actual logic.
    +488                ...
    +489
    +490        async def main():
    +491            users = aiobungie.into_iter(["user_danny", "user_jojo"])
    +492            await users.async_for_each(lambda username: signup(username))
    +493        ```
    +494
    +495        Parameters
    +496        ----------
    +497        func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]`
    +498            The async function to call on each item in the iterator.
    +499        """
    +500        await _helpers.awaits(*(func(item) for item in self))
    +501
    +502    def enumerate(self, *, start: int = 0) -> Iterator[tuple[int, Item]]:
    +503        """Returns a new iterator that yields tuples of the index and item.
    +504
    +505        Example
    +506        -------
    +507        ```py
    +508        iterator = Iterator([1, 2, 3])
    +509        for index, item in iterator.enumerate():
    +510            print(index, item)
    +511        # 0 1
    +512        # 1 2
    +513        # 2 3
    +514        ```
    +515
    +516        Raises
    +517        ------
    +518        `StopIteration`
    +519            If no elements are left in the iterator.
    +520        """
    +521        return Iterator(enumerate(self._items, start=start))
    +522
    +523    def _ok(self) -> typing.NoReturn:
    +524        raise StopIteration("No more items in the iterator.") from None
    +525
    +526    def __getitem__(self, index: int) -> Item:
    +527        try:
    +528            return self.skip(index).first()
    +529        except IndexError:
    +530            self._ok()
    +531
    +532    def __or__(self, other: Iterator[Item]) -> Iterator[Item]:
    +533        return self.union(other)
    +534
    +535    # This is a never.
    +536    def __setitem__(self) -> typing.NoReturn:
    +537        raise TypeError(
    +538            f"{type(self).__name__} doesn't support item assignment."
    +539        ) from None
    +540
    +541    def __repr__(self) -> str:
    +542        return f'<{self.__class__.__name__}({", ".join([str(item) for item in self])})>'
    +543
    +544    def __len__(self) -> int:
    +545        return self.count()
    +546
    +547    def __iter__(self) -> Iterator[Item]:
    +548        return self
    +549
    +550    def __next__(self) -> Item:
    +551        try:
    +552            item = next(self._items)
    +553        except StopIteration:
    +554            self._ok()
    +555
    +556        return item
    +
    + + +

    A Flat, In-Memory iterator for sequenced based data.

    + +
    Example
    + +
    +
    iterator = Iterator([1, 2, 3])
    +
    +# Map the results.
    +for item in iterator.map(lambda item: item * 2):
    +    print(item)
    +# 2
    +# 4
    +
    +# Indexing is also supported.
    +print(iterator[0])
    +# 1
    +
    +# Normal iteration.
    +for item in iterator:
    +    print(item)
    +# 1
    +# 2
    +# 3
    +
    +# Union two iterators.
    +iterator2 = Iterator([4, 5, 6])
    +final = iterator | iterator2
    +# <Iterator([1, 2, 3, 4, 5, 6])>
    +
    +
    + +
    Parameters
    + +
      +
    • items (collections.Iterable[Item]): +The items to iterate over.
    • +
    +
    + + +
    + +
    + + Iterator(items: collections.abc.Iterable[~Item]) + + -
    - - + +
    84    def __init__(self, items: collections.Iterable[Item]) -> None:
    +85        self._items = iter(items)
    +
    + +
    -
    -
    - ROCKETLAUNCHER = <ItemSubType.ROCKETLAUNCHER: 10> +
    + +
    + + def + collect( self, casting: 'typing.Optional[_B]' = None) -> 'typing.Union[list[Item], list[_B]]': + + + +
    + +
     95    def collect(
    + 96        self, casting: typing.Optional[_B] = None
    + 97    ) -> typing.Union[list[Item], list[_B]]:
    + 98        """Collects all items in the iterator into a list and cast them into an object if provided.
    + 99
    +100        Example
    +101        -------
    +102        >>> iterator = Iterator([1, 2, 3])
    +103        >>> iterator.collect(casting=str)
    +104        ["1", "2", "3"]
    +105
    +106        Parameters
    +107        ----------
    +108        casting: `T | None`
    +109            The type to cast the items to. If `None` is provided, the items will be returned as is.
    +110
    +111        Raises
    +112        ------
    +113        `StopIteration`
    +114            If no elements are left in the iterator.
    +115        """
    +116        if casting is not None:
    +117            return typing.cast(list[_B], list(map(casting, self._items)))
    +118
    +119        return list(self._items)
    +
    + + +

    Collects all items in the iterator into a list and cast them into an object if provided.

    + +
    Example
    + +
    +
    >>> iterator = Iterator([1, 2, 3])
    +>>> iterator.collect(casting=str)
    +["1", "2", "3"]
    +
    +
    + +
    Parameters
    + +
      +
    • casting (T | None): +The type to cast the items to. If None is provided, the items will be returned as is.
    • +
    + +
    Raises
    + +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - FUSIONRIFLE = <ItemSubType.FUSIONRIFLE: 11> +
    + +
    + + def + next(self) -> ~Item: + + + +
    + +
    121    def next(self) -> Item:
    +122        """Returns the next item in the iterator.
    +123
    +124        Example
    +125        -------
    +126        ```py
    +127        iterator = Iterator(["1", "2", "3"])
    +128        item = iterator.next()
    +129        assert item == "1"
    +130        item = iterator.next()
    +131        assert item == "2"
    +132        ```
    +133
    +134        Raises
    +135        ------
    +136        `StopIteration`
    +137            If no elements are left in the iterator.
    +138        """
    +139        try:
    +140            return self.__next__()
    +141        except StopIteration:
    +142            self._ok()
    +
    + + +

    Returns the next item in the iterator.

    + +
    Example
    + +
    +
    iterator = Iterator(["1", "2", "3"])
    +item = iterator.next()
    +assert item == "1"
    +item = iterator.next()
    +assert item == "2"
    +
    +
    + +
    Raises
    + +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - SNIPERRIFLE = <ItemSubType.SNIPERRIFLE: 12> +
    + +
    + + def + map( self, predicate: 'collections.Callable[[Item], OtherItem]') -> 'Iterator[OtherItem]': + + + +
    + +
    144    def map(
    +145        self, predicate: collections.Callable[[Item], OtherItem]
    +146    ) -> Iterator[OtherItem]:
    +147        """Maps each item in the iterator to its predicated value.
    +148
    +149        Example
    +150        -------
    +151        ```py
    +152        iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value))
    +153        print(iterator)
    +154        # <Iterator([1, 2, 3])>
    +155        ```
    +156
    +157        Parameters
    +158        ----------
    +159        predicate: `collections.Callable[[Item], OtherItem]`
    +160            The function to map each item in the iterator to its predicated value.
    +161
    +162        Returns
    +163        -------
    +164        `Iterator[OtherItem]`
    +165            The mapped iterator.
    +166
    +167        Raises
    +168        ------
    +169        `StopIteration`
    +170            If no elements are left in the iterator.
    +171        """
    +172        return Iterator(map(predicate, self._items))
    +
    + + +

    Maps each item in the iterator to its predicated value.

    + +
    Example
    + +
    +
    iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value))
    +print(iterator)
    +# <Iterator([1, 2, 3])>
    +
    +
    + +
    Parameters
    + +
      +
    • predicate (collections.Callable[[Item], OtherItem]): +The function to map each item in the iterator to its predicated value.
    • +
    + +
    Returns
    - -
    - - - +
      +
    • Iterator[OtherItem]: The mapped iterator.
    • +
    -
    -
    -
    - PULSERIFLE = <ItemSubType.PULSERIFLE: 13> +
    Raises
    + +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - SCOUTRIFLE = <ItemSubType.SCOUTRIFLE: 14> +
    + +
    + + def + take(self, n: int) -> aiobungie.Iterator[~Item]: + + + +
    + +
    174    def take(self, n: int) -> Iterator[Item]:
    +175        """Take the first number of items until the number of items are yielded or
    +176        the end of the iterator is reached.
    +177
    +178        Example
    +179        -------
    +180        ```py
    +181        iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
    +182        print(iterator.take(2))
    +183        # <Iterator([GameMode.RAID, GameMode.STRIKE])>
    +184        ```
    +185
    +186        Parameters
    +187        ----------
    +188        n: `int`
    +189            The number of items to take.
    +190
    +191        Raises
    +192        ------
    +193        `StopIteration`
    +194            If no elements are left in the iterator.
    +195        """
    +196        return Iterator(itertools.islice(self._items, n))
    +
    - -
    - - - -
    -
    -
    - SIDEARM = <ItemSubType.SIDEARM: 17> +

    Take the first number of items until the number of items are yielded or +the end of the iterator is reached.

    - -
    - - - +
    Example
    -
    -
    -
    - SWORD = <ItemSubType.SWORD: 18> +
    +
    iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
    +print(iterator.take(2))
    +# <Iterator([GameMode.RAID, GameMode.STRIKE])>
    +
    +
    - -
    - - - +
    Parameters
    -
    -
    -
    - MASK = <ItemSubType.MASK: 19> +
      +
    • n (int): +The number of items to take.
    • +
    - -
    - - - +
    Raises
    -
    -
    -
    - SHADER = <ItemSubType.SHADER: 20> +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - ORNAMENT = <ItemSubType.ORNAMENT: 21> +
    + +
    + + def + take_while( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.Iterator[~Item]: + + + +
    + +
    198    def take_while(
    +199        self, predicate: collections.Callable[[Item], bool]
    +200    ) -> Iterator[Item]:
    +201        """Yields items from the iterator while predicate returns `True`.
    +202
    +203        Example
    +204        -------
    +205        ```py
    +206        iterator = Iterator([STEAM, XBOX, STADIA])
    +207        print(iterator.take_while(lambda platform: platform is not XBOX))
    +208        # <Iterator([STEAM])>
    +209        ```
    +210
    +211        Parameters
    +212        ----------
    +213        predicate: `collections.Callable[[Item], bool]`
    +214            The function to predicate each item in the iterator.
    +215
    +216        Raises
    +217        ------
    +218        `StopIteration`
    +219            If no elements are left in the iterator.
    +220        """
    +221        return Iterator(itertools.takewhile(predicate, self._items))
    +
    - -
    - - - -
    -
    -
    - FUSIONRIFLELINE = <ItemSubType.FUSIONRIFLELINE: 22> +

    Yields items from the iterator while predicate returns True.

    - -
    - - - +
    Example
    -
    -
    -
    - GRENADELAUNCHER = <ItemSubType.GRENADELAUNCHER: 23> +
    +
    iterator = Iterator([STEAM, XBOX, STADIA])
    +print(iterator.take_while(lambda platform: platform is not XBOX))
    +# <Iterator([STEAM])>
    +
    +
    - -
    - - - +
    Parameters
    -
    -
    -
    - SUBMACHINEGUN = <ItemSubType.SUBMACHINEGUN: 24> +
      +
    • predicate (collections.Callable[[Item], bool]): +The function to predicate each item in the iterator.
    • +
    - -
    - - - +
    Raises
    -
    -
    -
    - TRACERIFLE = <ItemSubType.TRACERIFLE: 25> +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - HELMETARMOR = <ItemSubType.HELMETARMOR: 26> +
    + +
    + + def + drop_while( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.Iterator[~Item]: + + + +
    + +
    223    def drop_while(
    +224        self, predicate: collections.Callable[[Item], bool]
    +225    ) -> Iterator[Item]:
    +226        """Yields items from the iterator while predicate returns `False`.
    +227
    +228        Example
    +229        -------
    +230        ```py
    +231        iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
    +232        print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
    +233        # <Iterator([DestinyMembership(name="Bob")])>
    +234        ```
    +235
    +236        Parameters
    +237        ----------
    +238        predicate: `collections.Callable[[Item], bool]`
    +239            The function to predicate each item in the iterator.
    +240
    +241        Raises
    +242        ------
    +243        `StopIteration`
    +244            If no elements are left in the iterator.
    +245        """
    +246        return Iterator(itertools.dropwhile(predicate, self._items))
    +
    - -
    - - - -
    -
    -
    - GAUNTLETSARMOR = <ItemSubType.GAUNTLETSARMOR: 27> +

    Yields items from the iterator while predicate returns False.

    - -
    - - - +
    Example
    -
    -
    -
    - CHESTARMOR = <ItemSubType.CHESTARMOR: 28> +
    +
    iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
    +print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
    +# <Iterator([DestinyMembership(name="Bob")])>
    +
    +
    - -
    - - - +
    Parameters
    -
    -
    -
    - LEGARMOR = <ItemSubType.LEGARMOR: 29> +
      +
    • predicate (collections.Callable[[Item], bool]): +The function to predicate each item in the iterator.
    • +
    - -
    - - - +
    Raises
    -
    -
    -
    - CLASSARMOR = <ItemSubType.CLASSARMOR: 30> +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - BOW = <ItemSubType.BOW: 31> +
    + +
    + + def + filter( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.Iterator[~Item]: + + -
    - - - + +
    248    def filter(self, predicate: collections.Callable[[Item], bool]) -> Iterator[Item]:
    +249        """Filters the iterator to only yield items that match the predicate.
    +250
    +251        Example
    +252        -------
    +253        ```py
    +254        names = Iterator(["Jim", "Bob", "Mike", "Jess"])
    +255        print(names.filter(lambda n: n != "Jim"))
    +256        # <Iterator(["Bob", "Mike", "Jess"])>
    +257        ```
    +258        """
    +259        return Iterator(filter(predicate, self._items))
    +
    -
    -
    -
    - DUMMYREPEATABLEBOUNTY = <ItemSubType.DUMMYREPEATABLEBOUNTY: 32> - -
    - - - +

    Filters the iterator to only yield items that match the predicate.

    -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    +
    Example
    -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    +
    +
    names = Iterator(["Jim", "Bob", "Mike", "Jess"])
    +print(names.filter(lambda n: n != "Jim"))
    +# <Iterator(["Bob", "Mike", "Jess"])>
    +
    +
    +
    -
    - -
    -
    -
    - -
    -
    @typing.final
    - class - ItemTier(builtins.int, aiobungie.Enum): +
    +
    + +
    + + def + skip(self, n: int) -> aiobungie.Iterator[~Item]: - +
    - -
    621@typing.final
    -622class ItemTier(int, Enum):
    -623    """An enum for a Destiny 2 item tier."""
    -624
    -625    NONE = 0
    -626    BASIC = 3340296461
    -627    COMMON = 2395677314
    -628    RARE = 2127292149
    -629    LEGENDERY = 4008398120
    -630    EXOTIC = 2759499571
    +    
    +            
    261    def skip(self, n: int) -> Iterator[Item]:
    +262        """Skips the first number of items in the iterator.
    +263
    +264        Example
    +265        -------
    +266        ```py
    +267        iterator = Iterator([STEAM, XBOX, STADIA])
    +268        print(iterator.skip(1))
    +269        # <Iterator([XBOX, STADIA])>
    +270        ```
    +271        """
    +272        return Iterator(itertools.islice(self._items, n, None))
     
    -

    An enum for a Destiny 2 item tier.

    -
    - - -
    -
    - NONE = <ItemTier.NONE: 0> +

    Skips the first number of items in the iterator.

    - -
    - - - +
    Example
    -
    -
    -
    - BASIC = <ItemTier.BASIC: 3340296461> +
    +
    iterator = Iterator([STEAM, XBOX, STADIA])
    +print(iterator.skip(1))
    +# <Iterator([XBOX, STADIA])>
    +
    +
    +
    - -
    - - -
    -
    -
    - COMMON = <ItemTier.COMMON: 2395677314> +
    + +
    + + def + zip(self, other: 'Iterator[OtherItem]') -> 'Iterator[tuple[Item, OtherItem]]': + + + +
    + +
    274    def zip(self, other: Iterator[OtherItem]) -> Iterator[tuple[Item, OtherItem]]:
    +275        """Zips the iterator with another iterable.
    +276
    +277        Example
    +278        -------
    +279        ```py
    +280        iterator = Iterator([1, 3, 5])
    +281        other = Iterator([2, 4, 6])
    +282        for item, other_item in iterator.zip(other):
    +283            print(item, other_item)
    +284        # <Iterator([(1, 2), (3, 4), (5, 6)])>
    +285        ```
    +286
    +287        Parameters
    +288        ----------
    +289        other: `Iterator[OtherItem]`
    +290            The iterable to zip with.
    +291
    +292        Raises
    +293        ------
    +294        `StopIteration`
    +295            If no elements are left in the iterator.
    +296        """
    +297        return Iterator(zip(self._items, other))
    +
    - -
    - - - -
    -
    -
    - RARE = <ItemTier.RARE: 2127292149> +

    Zips the iterator with another iterable.

    - -
    - - - +
    Example
    -
    -
    -
    - LEGENDERY = <ItemTier.LEGENDERY: 4008398120> +
    +
    iterator = Iterator([1, 3, 5])
    +other = Iterator([2, 4, 6])
    +for item, other_item in iterator.zip(other):
    +    print(item, other_item)
    +# <Iterator([(1, 2), (3, 4), (5, 6)])>
    +
    +
    - -
    - - - +
    Parameters
    -
    -
    -
    - EXOTIC = <ItemTier.EXOTIC: 2759499571> +
      +
    • other (Iterator[OtherItem]): +The iterable to zip with.
    • +
    - -
    - - - +
    Raises
    -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    -
    -
    -
    -
    - -
    -
    @typing.final
    +
    + +
    + + def + all(self, predicate: collections.abc.Callable[[~Item], bool]) -> bool: - class - ItemType(builtins.int, aiobungie.Enum): + + +
    + +
    299    def all(self, predicate: collections.Callable[[Item], bool]) -> bool:
    +300        """`True` if all items in the iterator match the predicate.
    +301
    +302        Example
    +303        -------
    +304        ```py
    +305        iterator = Iterator([1, 2, 3])
    +306        while iterator.all(lambda item: isinstance(item, int)):
    +307            print("Still all integers")
    +308            continue
    +309        # Still all integers
    +310        ```
    +311
    +312        Parameters
    +313        ----------
    +314        predicate: `collections.Callable[[Item], bool]`
    +315            The function to test each item in the iterator.
    +316
    +317        Raises
    +318        ------
    +319        `StopIteration`
    +320            If no elements are left in the iterator.
    +321        """
    +322        return all(predicate(item) for item in self)
    +
    - -
    - -
    556@typing.final
    -557class ItemType(int, Enum):
    -558    """Enums for Destiny2's item types."""
    -559
    -560    NONE = 0
    -561    CURRENCY = 1
    -562    ARMOR = 2
    -563    WEAPON = 3
    -564    MESSAGE = 7
    -565    ENGRAM = 8
    -566    CONSUMABLE = 9
    -567    EXCHANGEMATERIAL = 10
    -568    MISSIONREWARD = 11
    -569    QUESTSTEP = 12
    -570    QUESTSTEPCOMPLETE = 13
    -571    EMBLEM = 14
    -572    QUEST = 15
    -573    SUBCLASS = 16
    -574    CLANBANNER = 17
    -575    AURA = 18
    -576    MOD = 19
    -577    DUMMY = 20
    -578    SHIP = 21
    -579    VEHICLE = 22
    -580    EMOTE = 23
    -581    GHOST = 24
    -582    PACKAGE = 25
    -583    BOUNTY = 26
    -584    WRAPPER = 27
    -585    SEASONALARTIFACT = 28
    -586    FINISHER = 29
    -
    +

    True if all items in the iterator match the predicate.

    +
    Example
    -

    Enums for Destiny2's item types.

    +
    +
    iterator = Iterator([1, 2, 3])
    +while iterator.all(lambda item: isinstance(item, int)):
    +    print("Still all integers")
    +    continue
    +# Still all integers
    +
    +
    Parameters
    -
    -
    - NONE = <ItemType.NONE: 0> +
      +
    • predicate (collections.Callable[[Item], bool]): +The function to test each item in the iterator.
    • +
    - -
    - - - +
    Raises
    -
    -
    -
    - CURRENCY = <ItemType.CURRENCY: 1> +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - ARMOR = <ItemType.ARMOR: 2> +
    + +
    + + def + any(self, predicate: collections.abc.Callable[[~Item], bool]) -> bool: - -
    - - - + + +
    + +
    324    def any(self, predicate: collections.Callable[[Item], bool]) -> bool:
    +325        """`True` if any items in the iterator match the predicate.
    +326
    +327        Example
    +328        -------
    +329        ```py
    +330        iterator = Iterator([1, 2, 3])
    +331        if iterator.any(lambda item: isinstance(item, int)):
    +332            print("At least one item is an int.")
    +333        # At least one item is an int.
    +334        ```
    +335
    +336        Parameters
    +337        ----------
    +338        predicate: `collections.Callable[[Item], bool]`
    +339            The function to test each item in the iterator.
    +340
    +341        Raises
    +342        ------
    +343        `StopIteration`
    +344            If no elements are left in the iterator.
    +345        """
    +346        return any(predicate(item) for item in self)
    +
    -
    -
    -
    - WEAPON = <ItemType.WEAPON: 3> - -
    - - - +

    True if any items in the iterator match the predicate.

    -
    -
    -
    - MESSAGE = <ItemType.MESSAGE: 7> +
    Example
    - -
    - - - +
    +
    iterator = Iterator([1, 2, 3])
    +if iterator.any(lambda item: isinstance(item, int)):
    +    print("At least one item is an int.")
    +# At least one item is an int.
    +
    +
    -
    -
    -
    - ENGRAM = <ItemType.ENGRAM: 8> +
    Parameters
    - -
    - - - +
      +
    • predicate (collections.Callable[[Item], bool]): +The function to test each item in the iterator.
    • +
    -
    -
    -
    - CONSUMABLE = <ItemType.CONSUMABLE: 9> +
    Raises
    + +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - EXCHANGEMATERIAL = <ItemType.EXCHANGEMATERIAL: 10> +
    + +
    + + def + sort( self, *, key: 'collections.Callable[[Item], typeshed.SupportsRichComparison]', reverse: bool = False) -> aiobungie.Iterator[~Item]: + + + +
    + +
    348    def sort(
    +349        self,
    +350        *,
    +351        key: collections.Callable[[Item], typeshed.SupportsRichComparison],
    +352        reverse: bool = False,
    +353    ) -> Iterator[Item]:
    +354        """Sorts the iterator.
    +355
    +356        Example
    +357        -------
    +358        ```py
    +359        iterator = Iterator([3, 1, 6, 7])
    +360        print(iterator.sort(key=lambda item: item))
    +361        # <Iterator([1, 3, 6, 7])>
    +362        ```
    +363
    +364        Parameters
    +365        ----------
    +366        key: `collections.Callable[[Item], Any]`
    +367            The function to sort by.
    +368        reverse: `bool`
    +369            Whether to reverse the sort.
    +370
    +371        Raises
    +372        ------
    +373        `StopIteration`
    +374            If no elements are left in the iterator.
    +375        """
    +376        return Iterator(sorted(self._items, key=key, reverse=reverse))
    +
    - -
    - - - -
    -
    -
    - MISSIONREWARD = <ItemType.MISSIONREWARD: 11> +

    Sorts the iterator.

    - -
    - - - +
    Example
    -
    -
    -
    - QUESTSTEP = <ItemType.QUESTSTEP: 12> +
    +
    iterator = Iterator([3, 1, 6, 7])
    +print(iterator.sort(key=lambda item: item))
    +# <Iterator([1, 3, 6, 7])>
    +
    +
    - -
    - - - +
    Parameters
    -
    -
    -
    - QUESTSTEPCOMPLETE = <ItemType.QUESTSTEPCOMPLETE: 13> +
      +
    • key (collections.Callable[[Item], Any]): +The function to sort by.
    • +
    • reverse (bool): +Whether to reverse the sort.
    • +
    - -
    - - - +
    Raises
    -
    -
    -
    - EMBLEM = <ItemType.EMBLEM: 14> +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - QUEST = <ItemType.QUEST: 15> +
    + +
    + + def + first(self) -> ~Item: + + -
    - - - + +
    378    def first(self) -> Item:
    +379        """Returns the first item in the iterator.
    +380
    +381        Example
    +382        -------
    +383        ```py
    +384        iterator = Iterator([3, 1, 6, 7])
    +385        print(iterator.first())
    +386        3
    +387        ```
    +388
    +389        Raises
    +390        ------
    +391        `StopIteration`
    +392            If no elements are left in the iterator.
    +393        """
    +394        return self.take(1).next()
    +
    -
    -
    -
    - SUBCLASS = <ItemType.SUBCLASS: 16> - -
    - - - +

    Returns the first item in the iterator.

    -
    -
    -
    - CLANBANNER = <ItemType.CLANBANNER: 17> +
    Example
    - -
    - - - +
    +
    iterator = Iterator([3, 1, 6, 7])
    +print(iterator.first())
    +3
    +
    +
    -
    -
    -
    - AURA = <ItemType.AURA: 18> +
    Raises
    + +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - MOD = <ItemType.MOD: 19> +
    + +
    + + def + reversed(self) -> aiobungie.Iterator[~Item]: + + -
    - - - + +
    396    def reversed(self) -> Iterator[Item]:
    +397        """Returns a new iterator that yields the items in the iterator in reverse order.
    +398
    +399        Example
    +400        -------
    +401        ```py
    +402        iterator = Iterator([3, 1, 6, 7])
    +403        print(iterator.reversed())
    +404        # <Iterator([7, 6, 1, 3])>
    +405        ```
    +406
    +407        Raises
    +408        ------
    +409        `StopIteration`
    +410            If no elements are left in the iterator.
    +411        """
    +412        return Iterator(reversed(self.collect()))
    +
    -
    -
    -
    - DUMMY = <ItemType.DUMMY: 20> - -
    - - - +

    Returns a new iterator that yields the items in the iterator in reverse order.

    -
    -
    -
    - SHIP = <ItemType.SHIP: 21> +
    Example
    + +
    +
    iterator = Iterator([3, 1, 6, 7])
    +print(iterator.reversed())
    +# <Iterator([7, 6, 1, 3])>
    +
    +
    - -
    - - - +
    Raises
    -
    -
    -
    - VEHICLE = <ItemType.VEHICLE: 22> +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - EMOTE = <ItemType.EMOTE: 23> +
    + +
    + + def + count(self) -> int: + + -
    - - - + +
    414    def count(self) -> int:
    +415        """Returns the number of items in the iterator.
    +416
    +417        Example
    +418        -------
    +419        ```py
    +420        iterator = Iterator([3, 1, 6, 7])
    +421        print(iterator.count())
    +422        4
    +423        ```
    +424        """
    +425        count = 0
    +426        for _ in self:
    +427            count += 1
    +428
    +429        return count
    +
    -
    -
    -
    - GHOST = <ItemType.GHOST: 24> - -
    - - - +

    Returns the number of items in the iterator.

    -
    -
    -
    - PACKAGE = <ItemType.PACKAGE: 25> +
    Example
    + +
    +
    iterator = Iterator([3, 1, 6, 7])
    +print(iterator.count())
    +4
    +
    +
    +
    - -
    - - -
    -
    -
    - BOUNTY = <ItemType.BOUNTY: 26> +
    + +
    + + def + union( self, other: aiobungie.Iterator[~Item]) -> aiobungie.Iterator[~Item]: + + + +
    + +
    431    def union(self, other: Iterator[Item]) -> Iterator[Item]:
    +432        """Returns a new iterator that yields all items from both iterators.
    +433
    +434        Example
    +435        -------
    +436        ```py
    +437        iterator = Iterator([1, 2, 3])
    +438        other = Iterator([4, 5, 6])
    +439        print(iterator.union(other))
    +440        # <Iterator([1, 2, 3, 4, 5, 6])>
    +441        ```
    +442
    +443        Parameters
    +444        ----------
    +445        other: `Iterator[Item]`
    +446            The iterable to union with.
    +447
    +448        Raises
    +449        ------
    +450        `StopIteration`
    +451            If no elements are left in the iterator.
    +452        """
    +453        return Iterator(itertools.chain(self._items, other))
    +
    - -
    - - - -
    -
    -
    - WRAPPER = <ItemType.WRAPPER: 27> +

    Returns a new iterator that yields all items from both iterators.

    - -
    - - - +
    Example
    -
    -
    -
    - SEASONALARTIFACT = <ItemType.SEASONALARTIFACT: 28> +
    +
    iterator = Iterator([1, 2, 3])
    +other = Iterator([4, 5, 6])
    +print(iterator.union(other))
    +# <Iterator([1, 2, 3, 4, 5, 6])>
    +
    +
    - -
    - - - +
    Parameters
    -
    -
    -
    - FINISHER = <ItemType.FINISHER: 29> +
      +
    • other (Iterator[Item]): +The iterable to union with.
    • +
    - -
    - - - +
    Raises
    -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    -
    -
    -
    -
    - -
    -
    @typing.final
    +
    + +
    + + def + for_each(self, func: collections.abc.Callable[[~Item], typing.Any]) -> None: - class - MembershipOption(builtins.int, aiobungie.Enum): + + +
    + +
    455    def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None:
    +456        """Calls the function on each item in the iterator.
    +457
    +458        Example
    +459        -------
    +460        ```py
    +461        iterator = Iterator([1, 2, 3])
    +462        iterator.for_each(lambda item: print(item))
    +463        # 1
    +464        # 2
    +465        # 3
    +466        ```
    +467
    +468        Parameters
    +469        ----------
    +470        func: `typeshed.Callable[[Item], None]`
    +471            The function to call on each item in the iterator.
    +472        """
    +473        for item in self:
    +474            func(item)
    +
    - -
    - -
    713@typing.final
    -714class MembershipOption(int, Enum):
    -715    """A enum for GroupV2 membership options."""
    -716
    -717    REVIEWD = 0
    -718    OPEN = 1
    -719    CLOSED = 2
    -
    +

    Calls the function on each item in the iterator.

    +
    Example
    -

    A enum for GroupV2 membership options.

    +
    +
    iterator = Iterator([1, 2, 3])
    +iterator.for_each(lambda item: print(item))
    +# 1
    +# 2
    +# 3
    +
    +
    Parameters
    -
    -
    - REVIEWD = <MembershipOption.REVIEWD: 0> +
      +
    • func (typeshed.Callable[[Item], None]): +The function to call on each item in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - OPEN = <MembershipOption.OPEN: 1> +
    + +
    + + async def + async_for_each( self, func: collections.abc.Callable[[~Item], collections.abc.Coroutine[None, None, None]]) -> None: - -
    - - - + + +
    + +
    476    async def async_for_each(
    +477        self,
    +478        func: collections.Callable[[Item], collections.Coroutine[None, None, None]],
    +479    ) -> None:
    +480        """Calls the async function on each item in the iterator concurrently.
    +481
    +482        Example
    +483        -------
    +484        ```py
    +485        async def signup(username: str) -> None:
    +486            async with aiohttp.request('POST', '...') as r:
    +487                # Actual logic.
    +488                ...
    +489
    +490        async def main():
    +491            users = aiobungie.into_iter(["user_danny", "user_jojo"])
    +492            await users.async_for_each(lambda username: signup(username))
    +493        ```
    +494
    +495        Parameters
    +496        ----------
    +497        func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]`
    +498            The async function to call on each item in the iterator.
    +499        """
    +500        await _helpers.awaits(*(func(item) for item in self))
    +
    -
    -
    -
    - CLOSED = <MembershipOption.CLOSED: 2> - -
    - - - +

    Calls the async function on each item in the iterator concurrently.

    -
    -
    -
    Inherited Members
    -
    -
    Enum
    -
    name
    -
    value
    +
    Example
    -
    -
    builtins.int
    -
    conjugate
    -
    bit_length
    -
    bit_count
    -
    to_bytes
    -
    from_bytes
    -
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    +
    +
    async def signup(username: str) -> None:
    +    async with aiohttp.request('POST', '...') as r:
    +        # Actual logic.
    +        ...
     
    -            
    -
    -
    -
    -
    - -
    -
    @typing.final
    +async def main(): + users = aiobungie.into_iter(["user_danny", "user_jojo"]) + await users.async_for_each(lambda username: signup(username)) +
    +
    - class - MembershipType(builtins.int, aiobungie.Enum): +
    Parameters
    - +
      +
    • func (collections.Callable[[Item], collections.Coroutine[None, None, None]]): +The async function to call on each item in the iterator.
    • +
    + - - -
    463@typing.final
    -464class MembershipType(int, Enum):
    -465    """An Enum for Bungie membership types."""
    -466
    -467    NONE = 0
    -468    XBOX = 1
    -469    PSN = 2
    -470    STEAM = 3
    -471    BLIZZARD = 4
    -472    STADIA = 5
    -473    BUNGIE = 254
    -474    ALL = -1
    +
    +                            
    +
    + +
    + + def + enumerate( self, *, start: int = 0) -> aiobungie.Iterator[tuple[int, ~Item]]: + + + +
    + +
    502    def enumerate(self, *, start: int = 0) -> Iterator[tuple[int, Item]]:
    +503        """Returns a new iterator that yields tuples of the index and item.
    +504
    +505        Example
    +506        -------
    +507        ```py
    +508        iterator = Iterator([1, 2, 3])
    +509        for index, item in iterator.enumerate():
    +510            print(index, item)
    +511        # 0 1
    +512        # 1 2
    +513        # 2 3
    +514        ```
    +515
    +516        Raises
    +517        ------
    +518        `StopIteration`
    +519            If no elements are left in the iterator.
    +520        """
    +521        return Iterator(enumerate(self._items, start=start))
     
    -

    An Enum for Bungie membership types.

    +

    Returns a new iterator that yields tuples of the index and item.

    + +
    Example
    + +
    +
    iterator = Iterator([1, 2, 3])
    +for index, item in iterator.enumerate():
    +    print(index, item)
    +# 0 1
    +# 1 2
    +# 2 3
    +
    +
    Raises
    -
    -
    - NONE = <MembershipType.NONE: 0> +
      +
    • StopIteration: If no elements are left in the iterator.
    • +
    +
    - -
    - - -
    -
    -
    - XBOX = <MembershipType.XBOX: 1> +
    +
    + +
    +
    @typing.final
    - -
    - - - + class + MembershipOption(builtins.int, aiobungie.Enum): - -
    -
    - PSN = <MembershipType.PSN: 2> + -
    - - - + +
    710@typing.final
    +711class MembershipOption(int, Enum):
    +712    """A enum for GroupV2 membership options."""
    +713
    +714    REVIEWD = 0
    +715    OPEN = 1
    +716    CLOSED = 2
    +
    -
    -
    -
    - STEAM = <MembershipType.STEAM: 3> - -
    - - - +

    A enum for GroupV2 membership options.

    +
    + -
    -
    -
    - BLIZZARD = <MembershipType.BLIZZARD: 4> +
    +
    Inherited Members
    +
    +
    Enum
    +
    name
    +
    value
    - -
    - - - +
    +
    builtins.int
    +
    conjugate
    +
    bit_length
    +
    bit_count
    +
    to_bytes
    +
    from_bytes
    +
    as_integer_ratio
    +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    +
    -
    -
    - STADIA = <MembershipType.STADIA: 5> +
    +
    + +
    +
    @typing.final
    - -
    - - - + class + MembershipType(builtins.int, aiobungie.Enum): - -
    -
    - BUNGIE = <MembershipType.BUNGIE: 254> + -
    - - - + +
    458@typing.final
    +459class MembershipType(int, Enum):
    +460    """An Enum for Bungie membership types."""
    +461
    +462    NONE = 0
    +463    XBOX = 1
    +464    PSN = 2
    +465    STEAM = 3
    +466    BLIZZARD = 4
    +467    STADIA = 5
    +468    EPIC_GAMES_STORE = 6
    +469    DEMON = 10
    +470    BUNGIE = 254
    +471    ALL = -1
    +
    -
    -
    -
    - ALL = <MembershipType.ALL: -1> - -
    - - - +

    An Enum for Bungie membership types.

    +
    + -
    Inherited Members
    @@ -22165,7 +17388,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -22183,16 +17405,16 @@
    Inherited Members
    -
    506@typing.final
    -507class MilestoneType(int, Enum):
    -508    """An Enum for Destiny 2 milestone types."""
    -509
    -510    UNKNOWN = 0
    -511    TUTORIAL = 1
    -512    ONETIME = 2
    -513    WEEKLY = 3
    -514    DAILY = 4
    -515    SPECIAL = 5
    +            
    503@typing.final
    +504class MilestoneType(int, Enum):
    +505    """An Enum for Destiny 2 milestone types."""
    +506
    +507    UNKNOWN = 0
    +508    TUTORIAL = 1
    +509    ONETIME = 2
    +510    WEEKLY = 3
    +511    DAILY = 4
    +512    SPECIAL = 5
     
    @@ -22200,72 +17422,6 @@
    Inherited Members
    -
    -
    - UNKNOWN = <MilestoneType.UNKNOWN: 0> - - -
    - - - - -
    -
    -
    - TUTORIAL = <MilestoneType.TUTORIAL: 1> - - -
    - - - - -
    -
    -
    - ONETIME = <MilestoneType.ONETIME: 2> - - -
    - - - - -
    -
    -
    - WEEKLY = <MilestoneType.WEEKLY: 3> - - -
    - - - - -
    -
    -
    - DAILY = <MilestoneType.DAILY: 4> - - -
    - - - - -
    -
    -
    - SPECIAL = <MilestoneType.SPECIAL: 5> - - -
    - - - - -
    Inherited Members
    @@ -22374,7 +17530,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -22408,83 +17563,6 @@
    Inherited Members
    -
    -
    - NONE = <ObjectiveUIStyle.NONE: 0> - - -
    - - - - -
    -
    -
    - HIGHLIGHTED = <ObjectiveUIStyle.HIGHLIGHTED: 1> - - -
    - - - - -
    -
    -
    - CRAFTING_WEAPON_LEVEL = <ObjectiveUIStyle.CRAFTING_WEAPON_LEVEL: 2> - - -
    - - - - -
    -
    -
    - CRAFTING_WEAPON_LEVEL_PROGRESS = <ObjectiveUIStyle.CRAFTING_WEAPON_LEVEL_PROGRESS: 3> - - -
    - - - - -
    -
    -
    - CRAFTING_WEAPON_TIMESTAMP = <ObjectiveUIStyle.CRAFTING_WEAPON_TIMESTAMP: 4> - - -
    - - - - -
    -
    -
    - CRAFTING_MEMENTOS = <ObjectiveUIStyle.CRAFTING_MEMENTOS: 5> - - -
    - - - - -
    -
    -
    - CRAFTING_MEMENTO_TITLE = <ObjectiveUIStyle.CRAFTING_MEMENTO_TITLE: 6> - - -
    - - - - -
    Inherited Members
    @@ -22521,14 +17599,14 @@
    Inherited Members
    -
    235@typing.final
    -236class Place(int, Enum):
    -237    """An Enum for Destiny 2 Places and NOT Planets"""
    -238
    -239    ORBIT = 2961497387
    -240    SOCIAL = 4151112093
    -241    LIGHT_HOUSE = 4276116472
    -242    EXPLORE = 3497767639
    +            
    230@typing.final
    +231class Place(int, Enum):
    +232    """An Enum for Destiny 2 Places and NOT Planets"""
    +233
    +234    ORBIT = 2961497387
    +235    SOCIAL = 4151112093
    +236    LIGHT_HOUSE = 4276116472
    +237    EXPLORE = 3497767639
     
    @@ -22536,50 +17614,6 @@
    Inherited Members
    -
    -
    - ORBIT = <Place.ORBIT: 2961497387> - - -
    - - - - -
    -
    -
    - SOCIAL = <Place.SOCIAL: 4151112093> - - -
    - - - - -
    -
    -
    - LIGHT_HOUSE = <Place.LIGHT_HOUSE: 4276116472> - - -
    - - - - -
    -
    -
    - EXPLORE = <Place.EXPLORE: 3497767639> - - -
    - - - - -
    Inherited Members
    @@ -22616,39 +17650,39 @@
    Inherited Members
    -
    200@typing.final
    -201class Planet(int, Enum):
    -202    """An Enum for all available planets in Destiny 2."""
    -203
    -204    UNKNOWN = 0
    -205    """Unknown space"""
    -206
    -207    EARTH = 3747705955
    -208    """Earth"""
    -209
    -210    DREAMING_CITY = 2877881518
    -211    """The Dreaming city."""
    -212
    -213    NESSUS = 3526908984
    -214    """Nessus"""
    -215
    -216    MOON = 3325508439
    -217    """The Moon"""
    -218
    -219    COSMODROME = 3990611421
    -220    """The Cosmodrome"""
    -221
    -222    TANGLED_SHORE = 3821439926
    -223    """The Tangled Shore"""
    -224
    -225    VENUS = 3871070152
    -226    """Venus"""
    -227
    -228    EAZ = 541863059  # Exclusive event.
    -229    """European Aerial Zone"""
    -230
    -231    EUROPA = 1729879943
    -232    """Europa"""
    +            
    195@typing.final
    +196class Planet(int, Enum):
    +197    """An Enum for all available planets in Destiny 2."""
    +198
    +199    UNKNOWN = 0
    +200    """Unknown space"""
    +201
    +202    EARTH = 3747705955
    +203    """Earth"""
    +204
    +205    DREAMING_CITY = 2877881518
    +206    """The Dreaming city."""
    +207
    +208    NESSUS = 3526908984
    +209    """Nessus"""
    +210
    +211    MOON = 3325508439
    +212    """The Moon"""
    +213
    +214    COSMODROME = 3990611421
    +215    """The Cosmodrome"""
    +216
    +217    TANGLED_SHORE = 3821439926
    +218    """The Tangled Shore"""
    +219
    +220    VENUS = 3871070152
    +221    """Venus"""
    +222
    +223    EAZ = 541863059  # Exclusive event.
    +224    """European Aerial Zone"""
    +225
    +226    EUROPA = 1729879943
    +227    """Europa"""
     
    @@ -22822,12 +17856,12 @@
    Inherited Members
    -
    683@typing.final
    -684class Presence(int, Enum):
    -685    """An enum for a bungie friend status."""
    -686
    -687    OFFLINE_OR_UNKNOWN = 0
    -688    ONLINE = 1
    +            
    680@typing.final
    +681class Presence(int, Enum):
    +682    """An enum for a bungie friend status."""
    +683
    +684    OFFLINE_OR_UNKNOWN = 0
    +685    ONLINE = 1
     
    @@ -22835,28 +17869,6 @@
    Inherited Members
    -
    -
    - OFFLINE_OR_UNKNOWN = <Presence.OFFLINE_OR_UNKNOWN: 0> - - -
    - - - - -
    -
    -
    - ONLINE = <Presence.ONLINE: 1> - - -
    - - - - -
    Inherited Members
    @@ -22872,98 +17884,43 @@
    Inherited Members
    to_bytes
    from_bytes
    as_integer_ratio
    -
    real
    -
    imag
    -
    numerator
    -
    denominator
    - -
    - - -
    -
    - -
    -
    @typing.final
    - - class - PrivacySetting(builtins.int, aiobungie.Enum): - - - -
    - -
    771@typing.final
    -772class PrivacySetting(int, Enum):
    -773    """An enum for players's privacy settings."""
    -774
    -775    OPEN = 0
    -776    CLAN_AND_FRIENDS = 1
    -777    FRIENDS_ONLY = 2
    -778    INVITE_ONLY = 3
    -779    CLOSED = 4
    -
    - - -

    An enum for players's privacy settings.

    -
    - - -
    -
    - OPEN = <PrivacySetting.OPEN: 0> - - -
    - - - - -
    -
    -
    - CLAN_AND_FRIENDS = <PrivacySetting.CLAN_AND_FRIENDS: 1> - - -
    - - - +
    real
    +
    imag
    +
    numerator
    +
    denominator
    +
    + -
    -
    - FRIENDS_ONLY = <PrivacySetting.FRIENDS_ONLY: 2> +
    +
    + +
    +
    @typing.final
    - -
    - - - + class + PrivacySetting(builtins.int, aiobungie.Enum): - -
    -
    - INVITE_ONLY = <PrivacySetting.INVITE_ONLY: 3> + -
    - - - + +
    768@typing.final
    +769class PrivacySetting(int, Enum):
    +770    """An enum for players's privacy settings."""
    +771
    +772    OPEN = 0
    +773    CLAN_AND_FRIENDS = 1
    +774    FRIENDS_ONLY = 2
    +775    INVITE_ONLY = 3
    +776    CLOSED = 4
    +
    -
    -
    -
    - CLOSED = <PrivacySetting.CLOSED: 4> - -
    - - - +

    An enum for players's privacy settings.

    +
    + -
    Inherited Members
    @@ -22999,2007 +17956,1997 @@
    Inherited Members
    -
     364class RESTClient(interfaces.RESTInterface):
    - 365    """A RESTful client implementation for Bungie's API.
    - 366
    - 367    This client is designed to only make HTTP requests and return JSON objects
    - 368    to provide RESTful functionality.
    - 369
    - 370    This client is also used within `aiobungie.Client` which deserialize those returned JSON objects
    - 371    using the factory into Pythonic data classes objects which provide Python functionality.
    - 372
    - 373    Example
    - 374    -------
    - 375    ```py
    - 376    import aiobungie
    - 377
    - 378    async def main():
    - 379        async with aiobungie.RESTClient("TOKEN") as rest_client:
    - 380            req = await rest_client.fetch_clan_members(4389205)
    - 381            clan_members = req['results']
    - 382            for member in clan_members:
    - 383                for k, v in member['destinyUserInfo'].items():
    - 384                    print(k, v)
    - 385    ```
    - 386
    - 387    Parameters
    - 388    ----------
    - 389    token : `str`
    - 390        A valid application token from Bungie's developer portal.
    - 391
    - 392    Other Parameters
    - 393    ----------------
    - 394    max_retries : `int`
    - 395        The max retries number to retry if the request hit a `5xx` status code.
    - 396    max_ratelimit_retries : `int`
    - 397        The max retries number to retry if the request hit a `429` status code. Defaults to `3`.
    - 398    client_secret : `typing.Optional[str]`
    - 399        An optional application client secret,
    - 400        This is only needed if you're fetching OAuth2 tokens with this client.
    - 401    client_id : `typing.Optional[int]`
    - 402        An optional application client id,
    - 403        This is only needed if you're fetching OAuth2 tokens with this client.
    - 404    enable_debugging : `bool | str`
    - 405        Whether to enable logging responses or not.
    - 406
    - 407    Logging Levels
    - 408    --------------
    - 409    * `False`: This will disable logging.
    - 410    * `True`: This will set the level to `DEBUG` and enable logging minimal information.
    - 411    * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information.
    - 412    """
    - 413
    - 414    __slots__ = (
    - 415        "_token",
    - 416        "_session",
    - 417        "_lock",
    - 418        "_max_retries",
    - 419        "_client_secret",
    - 420        "_client_id",
    - 421        "_metadata",
    - 422        "_max_rate_limit_retries",
    - 423    )
    - 424
    - 425    def __init__(
    - 426        self,
    - 427        token: str,
    - 428        /,
    - 429        client_secret: typing.Optional[str] = None,
    - 430        client_id: typing.Optional[int] = None,
    - 431        *,
    - 432        max_retries: int = 4,
    - 433        max_ratelimit_retries: int = 3,
    - 434        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    - 435    ) -> None:
    - 436        self._session: typing.Optional[_Session] = None
    - 437        self._lock: typing.Optional[asyncio.Lock] = None
    - 438        self._client_secret = client_secret
    - 439        self._client_id = client_id
    - 440        self._token: str = token
    - 441        self._max_retries = max_retries
    - 442        self._max_rate_limit_retries = max_ratelimit_retries
    - 443        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    +            
     362class RESTClient(interfaces.RESTInterface):
    + 363    """A RESTful client implementation for Bungie's API.
    + 364
    + 365    This client is designed to only make HTTP requests and return JSON objects
    + 366    to provide RESTful functionality.
    + 367
    + 368    This client is also used within `aiobungie.Client` which deserialize those returned JSON objects
    + 369    using the factory into Pythonic data classes objects which provide Python functionality.
    + 370
    + 371    Example
    + 372    -------
    + 373    ```py
    + 374    import aiobungie
    + 375
    + 376    async def main():
    + 377        async with aiobungie.RESTClient("TOKEN") as rest_client:
    + 378            req = await rest_client.fetch_clan_members(4389205)
    + 379            clan_members = req['results']
    + 380            for member in clan_members:
    + 381                for k, v in member['destinyUserInfo'].items():
    + 382                    print(k, v)
    + 383    ```
    + 384
    + 385    Parameters
    + 386    ----------
    + 387    token : `str`
    + 388        A valid application token from Bungie's developer portal.
    + 389
    + 390    Other Parameters
    + 391    ----------------
    + 392    max_retries : `int`
    + 393        The max retries number to retry if the request hit a `5xx` status code.
    + 394    max_ratelimit_retries : `int`
    + 395        The max retries number to retry if the request hit a `429` status code. Defaults to `3`.
    + 396    client_secret : `typing.Optional[str]`
    + 397        An optional application client secret,
    + 398        This is only needed if you're fetching OAuth2 tokens with this client.
    + 399    client_id : `typing.Optional[int]`
    + 400        An optional application client id,
    + 401        This is only needed if you're fetching OAuth2 tokens with this client.
    + 402    enable_debugging : `bool | str`
    + 403        Whether to enable logging responses or not.
    + 404
    + 405    Logging Levels
    + 406    --------------
    + 407    * `False`: This will disable logging.
    + 408    * `True`: This will set the level to `DEBUG` and enable logging minimal information.
    + 409    * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information.
    + 410    """
    + 411
    + 412    __slots__ = (
    + 413        "_token",
    + 414        "_session",
    + 415        "_lock",
    + 416        "_max_retries",
    + 417        "_client_secret",
    + 418        "_client_id",
    + 419        "_metadata",
    + 420        "_max_rate_limit_retries",
    + 421    )
    + 422
    + 423    def __init__(
    + 424        self,
    + 425        token: str,
    + 426        /,
    + 427        client_secret: typing.Optional[str] = None,
    + 428        client_id: typing.Optional[int] = None,
    + 429        *,
    + 430        max_retries: int = 4,
    + 431        max_ratelimit_retries: int = 3,
    + 432        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    + 433    ) -> None:
    + 434        self._session: typing.Optional[_Session] = None
    + 435        self._lock: typing.Optional[asyncio.Lock] = None
    + 436        self._client_secret = client_secret
    + 437        self._client_id = client_id
    + 438        self._token: str = token
    + 439        self._max_retries = max_retries
    + 440        self._max_rate_limit_retries = max_ratelimit_retries
    + 441        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    + 442
    + 443        self._set_debug_level(enable_debugging)
      444
    - 445        self._set_debug_level(enable_debugging)
    - 446
    - 447    @property
    - 448    def client_id(self) -> typing.Optional[int]:
    - 449        return self._client_id
    - 450
    - 451    @property
    - 452    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    - 453        return self._metadata
    - 454
    - 455    @property
    - 456    def is_alive(self) -> bool:
    - 457        return self._session is not None
    - 458
    - 459    @typing.final
    - 460    async def close(self) -> None:
    - 461        session = self._get_session()
    - 462        await session.close()
    - 463        self._session = None
    - 464
    - 465    @typing.final
    - 466    def open(self) -> None:
    - 467        """Open a new client session. This is called internally with contextmanager usage."""
    - 468        if self.is_alive:
    - 469            raise RuntimeError("Cannot open a new session while it's already open.")
    + 445    @property
    + 446    def client_id(self) -> typing.Optional[int]:
    + 447        return self._client_id
    + 448
    + 449    @property
    + 450    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    + 451        return self._metadata
    + 452
    + 453    @property
    + 454    def is_alive(self) -> bool:
    + 455        return self._session is not None
    + 456
    + 457    @typing.final
    + 458    async def close(self) -> None:
    + 459        session = self._get_session()
    + 460        await session.close()
    + 461        self._session = None
    + 462
    + 463    @typing.final
    + 464    def open(self) -> None:
    + 465        """Open a new client session. This is called internally with contextmanager usage."""
    + 466        if self.is_alive:
    + 467            raise RuntimeError("Cannot open a new session while it's already open.")
    + 468
    + 469        self._session = _Session.create(owner=False, raise_status=False)
      470
    - 471        self._session = _Session.create(
    - 472            owner=False,
    - 473            raise_status=False,
    - 474            connect=None,
    - 475            socket_read=None,
    - 476            socket_connect=None,
    - 477        )
    - 478
    - 479    @typing.final
    - 480    def enable_debugging(
    - 481        self,
    - 482        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    - 483        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
    - 484        /,
    - 485    ) -> None:
    - 486        self._set_debug_level(level, file)
    - 487
    - 488    @typing.final
    - 489    async def static_request(
    - 490        self,
    - 491        method: typing.Union[RequestMethod, str],
    - 492        path: str,
    - 493        *,
    - 494        auth: typing.Optional[str] = None,
    - 495        json: typing.Optional[dict[str, typing.Any]] = None,
    - 496    ) -> ResponseSig:
    - 497        return await self._request(method, path, auth=auth, json=json)
    + 471    @typing.final
    + 472    def enable_debugging(
    + 473        self,
    + 474        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    + 475        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
    + 476        /,
    + 477    ) -> None:
    + 478        self._set_debug_level(level, file)
    + 479
    + 480    @typing.final
    + 481    async def static_request(
    + 482        self,
    + 483        method: typing.Union[RequestMethod, str],
    + 484        path: str,
    + 485        *,
    + 486        auth: typing.Optional[str] = None,
    + 487        json: typing.Optional[dict[str, typing.Any]] = None,
    + 488    ) -> ResponseSig:
    + 489        return await self._request(method, path, auth=auth, json=json)
    + 490
    + 491    @typing.final
    + 492    def build_oauth2_url(
    + 493        self, client_id: typing.Optional[int] = None
    + 494    ) -> typing.Optional[builders.OAuthURL]:
    + 495        client_id = client_id or self._client_id
    + 496        if client_id is None:
    + 497            return None
      498
    - 499    @typing.final
    - 500    def build_oauth2_url(
    - 501        self, client_id: typing.Optional[int] = None
    - 502    ) -> typing.Optional[str]:
    - 503        client_id = client_id or self._client_id
    - 504        if client_id is None:
    - 505            return None
    + 499        return builders.OAuthURL(client_id=client_id)
    + 500
    + 501    @staticmethod
    + 502    def _set_debug_level(
    + 503        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    + 504        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
    + 505    ) -> None:
      506
    - 507        return url.OAUTH2_EP_BUILDER.format(
    - 508            oauth_endpoint=url.OAUTH_EP,
    - 509            client_id=client_id,
    - 510            uuid=_uuid(),
    - 511        )
    + 507        file_handler = logging.FileHandler(file, mode="w") if file else None
    + 508        if level == "TRACE" or level == TRACE:
    + 509            logging.basicConfig(
    + 510                level=TRACE, handlers=[file_handler] if file_handler else None
    + 511            )
      512
    - 513    @staticmethod
    - 514    def _set_debug_level(
    - 515        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    - 516        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
    - 517    ) -> None:
    - 518
    - 519        file_handler = logging.FileHandler(file, mode="w") if file else None
    - 520        if level == "TRACE" or level == TRACE:
    - 521            logging.basicConfig(
    - 522                level=TRACE, handlers=[file_handler] if file_handler else None
    - 523            )
    - 524
    - 525        elif level:
    - 526            logging.basicConfig(
    - 527                level=logging.DEBUG, handlers=[file_handler] if file_handler else None
    - 528            )
    - 529
    - 530    def _get_session(self) -> _Session:
    - 531        if self._session:
    - 532            return self._session
    - 533
    - 534        raise RuntimeError(
    - 535            "Cannot return a session while its close. Make sure you use `async with` before making requests."
    - 536        )
    - 537
    - 538    async def _request(
    - 539        self,
    - 540        method: typing.Union[RequestMethod, str],
    - 541        route: str,
    - 542        *,
    - 543        base: bool = False,
    - 544        oauth2: bool = False,
    - 545        auth: typing.Optional[str] = None,
    - 546        unwrapping: typing.Literal["json", "read"] = "json",
    - 547        json: typing.Optional[dict[str, typing.Any]] = None,
    - 548        headers: typing.Optional[dict[str, typing.Any]] = None,
    - 549        data: typing.Optional[typing.Union[str, dict[str, typing.Any]]] = None,
    - 550    ) -> ResponseSig:
    - 551
    - 552        retries: int = 0
    - 553        session = self._get_session()
    - 554        headers = headers or {}
    + 513        elif level:
    + 514            logging.basicConfig(
    + 515                level=logging.DEBUG, handlers=[file_handler] if file_handler else None
    + 516            )
    + 517
    + 518    def _get_session(self) -> _Session:
    + 519        if self._session:
    + 520            return self._session
    + 521
    + 522        raise RuntimeError(
    + 523            "Cannot return a session while its close. Make sure you use `async with` before making requests."
    + 524        )
    + 525
    + 526    async def _request(
    + 527        self,
    + 528        method: typing.Union[RequestMethod, str],
    + 529        route: str,
    + 530        *,
    + 531        base: bool = False,
    + 532        oauth2: bool = False,
    + 533        auth: typing.Optional[str] = None,
    + 534        unwrapping: typing.Literal["json", "read"] = "json",
    + 535        json: typing.Optional[dict[str, typing.Any]] = None,
    + 536        headers: typing.Optional[dict[str, typing.Any]] = None,
    + 537        data: typing.Optional[typing.Union[str, dict[str, typing.Any]]] = None,
    + 538    ) -> ResponseSig:
    + 539
    + 540        retries: int = 0
    + 541        session = self._get_session()
    + 542        headers = headers or {}
    + 543
    + 544        headers.setdefault(_USER_AGENT_HEADERS, _USER_AGENT)
    + 545        headers["X-API-KEY"] = self._token
    + 546
    + 547        if auth is not None:
    + 548            headers[_AUTH_HEADER] = f"Bearer {auth}"
    + 549
    + 550        # Handling endpoints
    + 551        endpoint = url.BASE
    + 552
    + 553        if not base:
    + 554            endpoint = endpoint + url.REST_EP
      555
    - 556        headers.setdefault(_USER_AGENT_HEADERS, _USER_AGENT)
    - 557        headers["X-API-KEY"] = self._token
    - 558
    - 559        if auth is not None:
    - 560            headers[_AUTH_HEADER] = f"Bearer {auth}"
    - 561
    - 562        # Handling endpoints
    - 563        endpoint = url.BASE
    - 564
    - 565        if not base:
    - 566            endpoint = endpoint + url.REST_EP
    + 556        if oauth2:
    + 557            headers["Content-Type"] = "application/x-www-form-urlencoded"
    + 558            endpoint = endpoint + url.TOKEN_EP
    + 559
    + 560        if self._lock is None:
    + 561            self._lock = asyncio.Lock()
    + 562
    + 563        while True:
    + 564            try:
    + 565                async with (stack := contextlib.AsyncExitStack()):
    + 566                    await stack.enter_async_context(self._lock)
      567
    - 568        if oauth2:
    - 569            headers["Content-Type"] = "application/x-www-form-urlencoded"
    - 570            endpoint = endpoint + url.TOKEN_EP
    - 571
    - 572        if self._lock is None:
    - 573            self._lock = asyncio.Lock()
    - 574
    - 575        while True:
    - 576            try:
    - 577                async with (stack := contextlib.AsyncExitStack()):
    - 578                    await stack.enter_async_context(self._lock)
    - 579
    - 580                    # We make the request here.
    - 581                    taken_time = time.monotonic()
    - 582                    response = await stack.enter_async_context(
    - 583                        session.client_session.request(
    - 584                            method=method,
    - 585                            url=f"{endpoint}/{route}",
    - 586                            json=json,
    - 587                            headers=headers,
    - 588                            data=data,
    - 589                        )
    - 590                    )
    - 591                    response_time = (time.monotonic() - taken_time) * 1_000
    + 568                    # We make the request here.
    + 569                    taken_time = time.monotonic()
    + 570                    response = await stack.enter_async_context(
    + 571                        session.client_session.request(
    + 572                            method=method,
    + 573                            url=f"{endpoint}/{route}",
    + 574                            json=json,
    + 575                            headers=headers,
    + 576                            data=data,
    + 577                        )
    + 578                    )
    + 579                    response_time = (time.monotonic() - taken_time) * 1_000
    + 580
    + 581                    _LOG.debug(
    + 582                        "%s %s %s Time %.4fms",
    + 583                        method,
    + 584                        f"{endpoint}/{route}",
    + 585                        f"{response.status} {response.reason}",
    + 586                        response_time,
    + 587                    )
    + 588
    + 589                    await self._handle_ratelimit(
    + 590                        response, method, route, self._max_rate_limit_retries
    + 591                    )
      592
    - 593                    _LOG.debug(
    - 594                        "%s %s %s Time %.4fms",
    - 595                        method,
    - 596                        f"{endpoint}/{route}",
    - 597                        f"{response.status} {response.reason}",
    - 598                        response_time,
    - 599                    )
    + 593                    if response.status == http.HTTPStatus.NO_CONTENT:
    + 594                        return None
    + 595
    + 596                    if 300 > response.status >= 200:
    + 597                        if unwrapping == "read":
    + 598                            # We need to read the bytes for the manifest response.
    + 599                            return await response.read()
      600
    - 601                    await self._handle_ratelimit(
    - 602                        response, method, route, self._max_rate_limit_retries
    - 603                    )
    - 604
    - 605                    if response.status == http.HTTPStatus.NO_CONTENT:
    - 606                        return None
    - 607
    - 608                    if 300 > response.status >= 200:
    - 609                        if unwrapping == "read":
    - 610                            # We need to read the bytes for the manifest response.
    - 611                            return await response.read()
    - 612
    - 613                        if response.content_type == _APP_JSON:
    - 614                            json_data = await response.json()
    - 615
    - 616                            _LOG.debug(
    - 617                                "%s %s %s Time %.4fms",
    - 618                                method,
    - 619                                f"{endpoint}/{route}",
    - 620                                f"{response.status} {response.reason}",
    - 621                                response_time,
    - 622                            )
    - 623
    - 624                            if _LOG.isEnabledFor(TRACE):
    - 625                                headers.update(response.headers)  # type: ignore
    - 626
    - 627                                _LOG.log(
    - 628                                    TRACE,
    - 629                                    "%s",
    - 630                                    error.stringify_http_message(headers),
    - 631                                )
    - 632
    - 633                            # Return the response.
    - 634                            # oauth2 responses are not packed inside a Response object.
    - 635                            if oauth2:
    - 636                                return json_data  # type: ignore[no-any-return]
    - 637
    - 638                            return json_data["Response"]  # type: ignore[no-any-return]
    - 639
    - 640                    if (
    - 641                        response.status in _RETRY_5XX
    - 642                        and retries < self._max_retries  # noqa: W503
    - 643                    ):
    - 644                        backoff_ = backoff.ExponentialBackOff(maximum=6)
    - 645                        sleep_time = next(backoff_)
    - 646                        _LOG.warning(
    - 647                            "Got %i - %s. Sleeping for %.2f seconds. Remaining retries: %i",
    - 648                            response.status,
    - 649                            response.reason,
    - 650                            sleep_time,
    - 651                            self._max_retries - retries,
    - 652                        )
    - 653
    - 654                        retries += 1
    - 655                        await asyncio.sleep(sleep_time)
    - 656                        continue
    - 657
    - 658                    raise await error.raise_error(response)
    - 659            # eol
    - 660            except _Dyn:
    - 661                continue
    - 662
    - 663    if not typing.TYPE_CHECKING:
    - 664
    - 665        def __enter__(self) -> typing.NoReturn:
    - 666            cls = type(self)
    - 667            raise TypeError(
    - 668                f"{cls.__qualname__} is async only, use 'async with' instead."
    - 669            )
    + 601                        if response.content_type == _APP_JSON:
    + 602                            json_data = await response.json()
    + 603
    + 604                            _LOG.debug(
    + 605                                "%s %s %s Time %.4fms",
    + 606                                method,
    + 607                                f"{endpoint}/{route}",
    + 608                                f"{response.status} {response.reason}",
    + 609                                response_time,
    + 610                            )
    + 611
    + 612                            if _LOG.isEnabledFor(TRACE):
    + 613                                headers.update(response.headers)  # type: ignore
    + 614
    + 615                                _LOG.log(
    + 616                                    TRACE,
    + 617                                    "%s",
    + 618                                    error.stringify_http_message(headers),
    + 619                                )
    + 620
    + 621                            # Return the response.
    + 622                            # oauth2 responses are not packed inside a Response object.
    + 623                            if oauth2:
    + 624                                return json_data  # type: ignore[no-any-return]
    + 625
    + 626                            return json_data["Response"]  # type: ignore[no-any-return]
    + 627
    + 628                    if (
    + 629                        response.status in _RETRY_5XX
    + 630                        and retries < self._max_retries  # noqa: W503
    + 631                    ):
    + 632                        backoff_ = backoff.ExponentialBackOff(maximum=6)
    + 633                        sleep_time = next(backoff_)
    + 634                        _LOG.warning(
    + 635                            "Got %i - %s. Sleeping for %.2f seconds. Remaining retries: %i",
    + 636                            response.status,
    + 637                            response.reason,
    + 638                            sleep_time,
    + 639                            self._max_retries - retries,
    + 640                        )
    + 641
    + 642                        retries += 1
    + 643                        await asyncio.sleep(sleep_time)
    + 644                        continue
    + 645
    + 646                    raise await error.raise_error(response)
    + 647            # eol
    + 648            except _Dyn:
    + 649                continue
    + 650
    + 651    if not typing.TYPE_CHECKING:
    + 652
    + 653        def __enter__(self) -> typing.NoReturn:
    + 654            cls = type(self)
    + 655            raise TypeError(
    + 656                f"{cls.__qualname__} is async only, use 'async with' instead."
    + 657            )
    + 658
    + 659        def __exit__(
    + 660            self,
    + 661            exception_type: typing.Optional[type[BaseException]],
    + 662            exception: typing.Optional[BaseException],
    + 663            exception_traceback: typing.Optional[types.TracebackType],
    + 664        ) -> None:
    + 665            ...
    + 666
    + 667    async def __aenter__(self) -> RESTClient:
    + 668        self.open()
    + 669        return self
      670
    - 671        def __exit__(
    - 672            self,
    - 673            exception_type: typing.Optional[type[BaseException]],
    - 674            exception: typing.Optional[BaseException],
    - 675            exception_traceback: typing.Optional[types.TracebackType],
    - 676        ) -> None:
    - 677            ...
    + 671    async def __aexit__(
    + 672        self,
    + 673        exception_type: typing.Optional[type[BaseException]],
    + 674        exception: typing.Optional[BaseException],
    + 675        exception_traceback: typing.Optional[types.TracebackType],
    + 676    ) -> None:
    + 677        await self.close()
      678
    - 679    async def __aenter__(self) -> RESTClient:
    - 680        self.open()
    - 681        return self
    - 682
    - 683    async def __aexit__(
    - 684        self,
    - 685        exception_type: typing.Optional[type[BaseException]],
    - 686        exception: typing.Optional[BaseException],
    - 687        exception_traceback: typing.Optional[types.TracebackType],
    - 688    ) -> None:
    - 689        await self.close()
    - 690
    - 691    # We don't want this to be super complicated.
    - 692    @staticmethod
    - 693    @typing.final
    - 694    async def _handle_ratelimit(
    - 695        response: aiohttp.ClientResponse,
    - 696        method: str,
    - 697        route: str,
    - 698        max_ratelimit_retries: int = 3,
    - 699    ) -> None:
    - 700
    - 701        if response.status != http.HTTPStatus.TOO_MANY_REQUESTS:
    - 702            return
    - 703
    - 704        if response.content_type != _APP_JSON:
    - 705            raise error.HTTPError(
    - 706                f"Being ratelimited on non JSON request, {response.content_type}.",
    - 707                http.HTTPStatus.TOO_MANY_REQUESTS,
    - 708            )
    + 679    # We don't want this to be super complicated.
    + 680    @staticmethod
    + 681    @typing.final
    + 682    async def _handle_ratelimit(
    + 683        response: aiohttp.ClientResponse,
    + 684        method: str,
    + 685        route: str,
    + 686        max_ratelimit_retries: int = 3,
    + 687    ) -> None:
    + 688
    + 689        if response.status != http.HTTPStatus.TOO_MANY_REQUESTS:
    + 690            return
    + 691
    + 692        if response.content_type != _APP_JSON:
    + 693            raise error.HTTPError(
    + 694                f"Being ratelimited on non JSON request, {response.content_type}.",
    + 695                http.HTTPStatus.TOO_MANY_REQUESTS,
    + 696            )
    + 697
    + 698        count: int = 0
    + 699        json: typedefs.JSONObject = await response.json()
    + 700        retry_after = float(json["ThrottleSeconds"])
    + 701
    + 702        while True:
    + 703            if count == max_ratelimit_retries:
    + 704                raise _Dyn
    + 705
    + 706            if retry_after <= 0:
    + 707                # We sleep for a little bit to avoid funky behavior.
    + 708                sleep_time = float(random.random() + 0.93) / 2
      709
    - 710        count: int = 0
    - 711        json: typedefs.JSONObject = await response.json()
    - 712        retry_after = float(json["ThrottleSeconds"])
    - 713
    - 714        while True:
    - 715            if count == max_ratelimit_retries:
    - 716                raise _Dyn
    - 717
    - 718            if retry_after <= 0:
    - 719                # We sleep for a little bit to avoid funky behavior.
    - 720                sleep_time = float(random.random() + 0.93) / 2
    - 721
    - 722                _LOG.warning(
    - 723                    "We're being ratelimited with method %s route %s. Sleeping for %.2fs.",
    - 724                    method,
    - 725                    route,
    - 726                    sleep_time,
    - 727                )
    - 728                count += 1
    - 729                await asyncio.sleep(sleep_time)
    - 730                continue
    - 731
    - 732            raise error.RateLimitedError(
    - 733                body=json,
    - 734                url=str(response.real_url),
    - 735                retry_after=retry_after,
    + 710                _LOG.warning(
    + 711                    "We're being ratelimited with method %s route %s. Sleeping for %.2fs.",
    + 712                    method,
    + 713                    route,
    + 714                    sleep_time,
    + 715                )
    + 716                count += 1
    + 717                await asyncio.sleep(sleep_time)
    + 718                continue
    + 719
    + 720            raise error.RateLimitedError(
    + 721                body=json,
    + 722                url=str(response.real_url),
    + 723                retry_after=retry_after,
    + 724            )
    + 725
    + 726    async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response:
    + 727
    + 728        if not isinstance(self._client_id, int):
    + 729            raise TypeError(
    + 730                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
    + 731            )
    + 732
    + 733        if not isinstance(self._client_secret, str):
    + 734            raise TypeError(
    + 735                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
      736            )
      737
    - 738    async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response:
    - 739
    - 740        if not isinstance(self._client_id, int):
    - 741            raise TypeError(
    - 742                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
    - 743            )
    - 744
    - 745        if not isinstance(self._client_secret, str):
    - 746            raise TypeError(
    - 747                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
    - 748            )
    - 749
    - 750        headers = {
    - 751            "client_secret": self._client_secret,
    - 752        }
    - 753
    - 754        data = (
    - 755            f"grant_type=authorization_code&code={code}"
    - 756            f"&client_id={self._client_id}&client_secret={self._client_secret}"
    - 757        )
    - 758
    - 759        response = await self._request(
    - 760            RequestMethod.POST, "", headers=headers, data=data, oauth2=True
    - 761        )
    - 762        assert isinstance(response, dict)
    - 763        return builders.OAuth2Response.build_response(response)
    - 764
    - 765    async def refresh_access_token(
    - 766        self, refresh_token: str, /
    - 767    ) -> builders.OAuth2Response:
    - 768        if not isinstance(self._client_id, int):
    - 769            raise TypeError(
    - 770                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
    - 771            )
    - 772
    - 773        if not isinstance(self._client_secret, str):
    - 774            raise TypeError(
    - 775                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
    - 776            )
    + 738        headers = {
    + 739            "client_secret": self._client_secret,
    + 740        }
    + 741
    + 742        data = (
    + 743            f"grant_type=authorization_code&code={code}"
    + 744            f"&client_id={self._client_id}&client_secret={self._client_secret}"
    + 745        )
    + 746
    + 747        response = await self._request(
    + 748            RequestMethod.POST, "", headers=headers, data=data, oauth2=True
    + 749        )
    + 750        assert isinstance(response, dict)
    + 751        return builders.OAuth2Response.build_response(response)
    + 752
    + 753    async def refresh_access_token(
    + 754        self, refresh_token: str, /
    + 755    ) -> builders.OAuth2Response:
    + 756        if not isinstance(self._client_id, int):
    + 757            raise TypeError(
    + 758                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
    + 759            )
    + 760
    + 761        if not isinstance(self._client_secret, str):
    + 762            raise TypeError(
    + 763                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
    + 764            )
    + 765
    + 766        data = {
    + 767            "grant_type": "refresh_token",
    + 768            "refresh_token": refresh_token,
    + 769            "client_id": self._client_id,
    + 770            "client_secret": self._client_secret,
    + 771            "Content-Type": "application/x-www-form-urlencoded",
    + 772        }
    + 773
    + 774        response = await self._request(RequestMethod.POST, "", data=data, oauth2=True)
    + 775        assert isinstance(response, dict)
    + 776        return builders.OAuth2Response.build_response(response)
      777
    - 778        data = {
    - 779            "grant_type": "refresh_token",
    - 780            "refresh_token": refresh_token,
    - 781            "client_id": self._client_id,
    - 782            "client_secret": self._client_secret,
    - 783            "Content-Type": "application/x-www-form-urlencoded",
    - 784        }
    + 778    async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject:
    + 779        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 780        resp = await self._request(
    + 781            RequestMethod.GET, f"User/GetBungieNetUserById/{id}/"
    + 782        )
    + 783        assert isinstance(resp, dict)
    + 784        return resp
      785
    - 786        response = await self._request(RequestMethod.POST, "", data=data, oauth2=True)
    - 787        assert isinstance(response, dict)
    - 788        return builders.OAuth2Response.build_response(response)
    - 789
    - 790    async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject:
    - 791        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 792        resp = await self._request(
    - 793            RequestMethod.GET, f"User/GetBungieNetUserById/{id}/"
    - 794        )
    - 795        assert isinstance(resp, dict)
    - 796        return resp
    - 797
    - 798    async def fetch_user_themes(self) -> typedefs.JSONArray:
    - 799        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 800        resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/")
    - 801        assert isinstance(resp, list)
    - 802        return resp
    - 803
    - 804    async def fetch_membership_from_id(
    - 805        self,
    - 806        id: int,
    - 807        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    - 808        /,
    - 809    ) -> typedefs.JSONObject:
    - 810        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 811        resp = await self._request(
    - 812            RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}"
    - 813        )
    - 814        assert isinstance(resp, dict)
    - 815        return resp
    - 816
    - 817    async def fetch_player(
    - 818        self,
    - 819        name: str,
    - 820        code: int,
    - 821        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
    - 822        /,
    - 823    ) -> typedefs.JSONArray:
    - 824        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 825        resp = await self._request(
    - 826            RequestMethod.POST,
    - 827            f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}",
    - 828            json={"displayName": name, "displayNameCode": code},
    - 829        )
    - 830        assert isinstance(resp, list)
    - 831        return resp
    - 832
    - 833    async def search_users(self, name: str, /) -> typedefs.JSONObject:
    + 786    async def fetch_user_themes(self) -> typedefs.JSONArray:
    + 787        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 788        resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/")
    + 789        assert isinstance(resp, list)
    + 790        return resp
    + 791
    + 792    async def fetch_membership_from_id(
    + 793        self,
    + 794        id: int,
    + 795        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    + 796        /,
    + 797    ) -> typedefs.JSONObject:
    + 798        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 799        resp = await self._request(
    + 800            RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}"
    + 801        )
    + 802        assert isinstance(resp, dict)
    + 803        return resp
    + 804
    + 805    async def fetch_player(
    + 806        self,
    + 807        name: str,
    + 808        code: int,
    + 809        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
    + 810        /,
    + 811    ) -> typedefs.JSONArray:
    + 812        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 813        resp = await self._request(
    + 814            RequestMethod.POST,
    + 815            f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}",
    + 816            json={"displayName": name, "displayNameCode": code},
    + 817        )
    + 818        assert isinstance(resp, list)
    + 819        return resp
    + 820
    + 821    async def search_users(self, name: str, /) -> typedefs.JSONObject:
    + 822        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 823        resp = await self._request(
    + 824            RequestMethod.POST,
    + 825            "User/Search/GlobalName/0",
    + 826            json={"displayNamePrefix": name},
    + 827        )
    + 828        assert isinstance(resp, dict)
    + 829        return resp
    + 830
    + 831    async def fetch_clan_from_id(
    + 832        self, id: int, /, access_token: typing.Optional[str] = None
    + 833    ) -> typedefs.JSONObject:
      834        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      835        resp = await self._request(
    - 836            RequestMethod.POST,
    - 837            "User/Search/GlobalName/0",
    - 838            json={"displayNamePrefix": name},
    - 839        )
    - 840        assert isinstance(resp, dict)
    - 841        return resp
    - 842
    - 843    async def fetch_clan_from_id(
    - 844        self, id: int, /, access_token: typing.Optional[str] = None
    - 845    ) -> typedefs.JSONObject:
    - 846        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 847        resp = await self._request(
    - 848            RequestMethod.GET, f"GroupV2/{id}", auth=access_token
    - 849        )
    - 850        assert isinstance(resp, dict)
    - 851        return resp
    - 852
    - 853    async def fetch_clan(
    - 854        self,
    - 855        name: str,
    - 856        /,
    - 857        access_token: typing.Optional[str] = None,
    - 858        *,
    - 859        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    - 860    ) -> typedefs.JSONObject:
    - 861        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 862        resp = await self._request(
    - 863            RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token
    - 864        )
    - 865        assert isinstance(resp, dict)
    - 866        return resp
    - 867
    - 868    async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject:
    - 869        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 870        resp = await self._request(
    - 871            RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/"
    - 872        )
    - 873        assert isinstance(resp, dict)
    - 874        return resp
    - 875
    - 876    async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray:
    - 877        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 878        resp = await self._request(
    - 879            RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/"
    - 880        )
    - 881        assert isinstance(resp, list)
    - 882        return resp
    - 883
    - 884    async def fetch_application(self, appid: int, /) -> typedefs.JSONObject:
    - 885        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 886        resp = await self._request(RequestMethod.GET, f"App/Application/{appid}")
    - 887        assert isinstance(resp, dict)
    - 888        return resp
    - 889
    - 890    async def fetch_character(
    - 891        self,
    - 892        member_id: int,
    - 893        membership_type: typedefs.IntAnd[enums.MembershipType],
    - 894        character_id: int,
    - 895        components: list[enums.ComponentType],
    - 896        auth: typing.Optional[str] = None,
    - 897    ) -> typedefs.JSONObject:
    - 898        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 899        collector = _collect_components(components)
    - 900        response = await self._request(
    - 901            RequestMethod.GET,
    - 902            f"Destiny2/{int(membership_type)}/Profile/{member_id}/"
    - 903            f"Character/{character_id}/?components={collector}",
    - 904            auth=auth,
    - 905        )
    - 906        assert isinstance(response, dict)
    - 907        return response
    - 908
    - 909    async def fetch_activities(
    - 910        self,
    - 911        member_id: int,
    - 912        character_id: int,
    - 913        mode: typedefs.IntAnd[enums.GameMode],
    - 914        membership_type: typedefs.IntAnd[
    - 915            enums.MembershipType
    - 916        ] = enums.MembershipType.ALL,
    - 917        *,
    - 918        page: int = 0,
    - 919        limit: int = 1,
    - 920    ) -> typedefs.JSONObject:
    - 921        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 922        resp = await self._request(
    - 923            RequestMethod.GET,
    - 924            f"Destiny2/{int(membership_type)}/Account/"
    - 925            f"{member_id}/Character/{character_id}/Stats/Activities"
    - 926            f"/?mode={int(mode)}&count={limit}&page={page}",
    - 927        )
    - 928        assert isinstance(resp, dict)
    - 929        return resp
    - 930
    - 931    async def fetch_vendor_sales(self) -> typedefs.JSONObject:
    - 932        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 933        resp = await self._request(
    - 934            RequestMethod.GET,
    - 935            f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}",
    - 936        )
    - 937        assert isinstance(resp, dict)
    - 938        return resp
    - 939
    - 940    async def fetch_profile(
    - 941        self,
    - 942        membership_id: int,
    - 943        type: typedefs.IntAnd[enums.MembershipType],
    - 944        components: list[enums.ComponentType],
    - 945        auth: typing.Optional[str] = None,
    - 946    ) -> typedefs.JSONObject:
    - 947        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 948        collector = _collect_components(components)
    - 949        response = await self._request(
    - 950            RequestMethod.GET,
    - 951            f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}",
    - 952            auth=auth,
    - 953        )
    - 954        assert isinstance(response, dict)
    - 955        return response
    - 956
    - 957    async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject:
    - 958        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 959        response = await self._request(
    - 960            RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}"
    - 961        )
    - 962        assert isinstance(response, dict)
    - 963        return response
    + 836            RequestMethod.GET, f"GroupV2/{id}", auth=access_token
    + 837        )
    + 838        assert isinstance(resp, dict)
    + 839        return resp
    + 840
    + 841    async def fetch_clan(
    + 842        self,
    + 843        name: str,
    + 844        /,
    + 845        access_token: typing.Optional[str] = None,
    + 846        *,
    + 847        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    + 848    ) -> typedefs.JSONObject:
    + 849        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 850        resp = await self._request(
    + 851            RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token
    + 852        )
    + 853        assert isinstance(resp, dict)
    + 854        return resp
    + 855
    + 856    async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject:
    + 857        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 858        resp = await self._request(
    + 859            RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/"
    + 860        )
    + 861        assert isinstance(resp, dict)
    + 862        return resp
    + 863
    + 864    async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray:
    + 865        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 866        resp = await self._request(
    + 867            RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/"
    + 868        )
    + 869        assert isinstance(resp, list)
    + 870        return resp
    + 871
    + 872    async def fetch_application(self, appid: int, /) -> typedefs.JSONObject:
    + 873        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 874        resp = await self._request(RequestMethod.GET, f"App/Application/{appid}")
    + 875        assert isinstance(resp, dict)
    + 876        return resp
    + 877
    + 878    async def fetch_character(
    + 879        self,
    + 880        member_id: int,
    + 881        membership_type: typedefs.IntAnd[enums.MembershipType],
    + 882        character_id: int,
    + 883        components: list[enums.ComponentType],
    + 884        auth: typing.Optional[str] = None,
    + 885    ) -> typedefs.JSONObject:
    + 886        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 887        collector = _collect_components(components)
    + 888        response = await self._request(
    + 889            RequestMethod.GET,
    + 890            f"Destiny2/{int(membership_type)}/Profile/{member_id}/"
    + 891            f"Character/{character_id}/?components={collector}",
    + 892            auth=auth,
    + 893        )
    + 894        assert isinstance(response, dict)
    + 895        return response
    + 896
    + 897    async def fetch_activities(
    + 898        self,
    + 899        member_id: int,
    + 900        character_id: int,
    + 901        mode: typedefs.IntAnd[enums.GameMode],
    + 902        membership_type: typedefs.IntAnd[
    + 903            enums.MembershipType
    + 904        ] = enums.MembershipType.ALL,
    + 905        *,
    + 906        page: int = 0,
    + 907        limit: int = 1,
    + 908    ) -> typedefs.JSONObject:
    + 909        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 910        resp = await self._request(
    + 911            RequestMethod.GET,
    + 912            f"Destiny2/{int(membership_type)}/Account/"
    + 913            f"{member_id}/Character/{character_id}/Stats/Activities"
    + 914            f"/?mode={int(mode)}&count={limit}&page={page}",
    + 915        )
    + 916        assert isinstance(resp, dict)
    + 917        return resp
    + 918
    + 919    async def fetch_vendor_sales(self) -> typedefs.JSONObject:
    + 920        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 921        resp = await self._request(
    + 922            RequestMethod.GET,
    + 923            f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}",
    + 924        )
    + 925        assert isinstance(resp, dict)
    + 926        return resp
    + 927
    + 928    async def fetch_profile(
    + 929        self,
    + 930        membership_id: int,
    + 931        type: typedefs.IntAnd[enums.MembershipType],
    + 932        components: list[enums.ComponentType],
    + 933        auth: typing.Optional[str] = None,
    + 934    ) -> typedefs.JSONObject:
    + 935        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 936        collector = _collect_components(components)
    + 937        response = await self._request(
    + 938            RequestMethod.GET,
    + 939            f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}",
    + 940            auth=auth,
    + 941        )
    + 942        assert isinstance(response, dict)
    + 943        return response
    + 944
    + 945    async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject:
    + 946        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 947        response = await self._request(
    + 948            RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}"
    + 949        )
    + 950        assert isinstance(response, dict)
    + 951        return response
    + 952
    + 953    async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject:
    + 954        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 955        resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash)
    + 956        assert isinstance(resp, dict)
    + 957        return resp
    + 958
    + 959    async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject:
    + 960        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    + 961        resp = await self.fetch_entity("DestinyObjectiveDefinition", hash)
    + 962        assert isinstance(resp, dict)
    + 963        return resp
      964
    - 965    async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject:
    - 966        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 967        resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash)
    - 968        assert isinstance(resp, dict)
    - 969        return resp
    - 970
    - 971    async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject:
    - 972        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    - 973        resp = await self.fetch_entity("DestinyObjectiveDefinition", hash)
    - 974        assert isinstance(resp, dict)
    - 975        return resp
    - 976
    - 977    async def fetch_groups_for_member(
    - 978        self,
    - 979        member_id: int,
    - 980        member_type: typedefs.IntAnd[enums.MembershipType],
    - 981        /,
    - 982        *,
    - 983        filter: int = 0,
    - 984        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    - 985    ) -> typedefs.JSONObject:
    - 986        resp = await self._request(
    - 987            RequestMethod.GET,
    - 988            f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
    - 989        )
    - 990        assert isinstance(resp, dict)
    - 991        return resp
    - 992
    - 993    async def fetch_potential_groups_for_member(
    - 994        self,
    - 995        member_id: int,
    - 996        member_type: typedefs.IntAnd[enums.MembershipType],
    - 997        /,
    - 998        *,
    - 999        filter: int = 0,
    -1000        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    -1001    ) -> typedefs.JSONObject:
    -1002        resp = await self._request(
    -1003            RequestMethod.GET,
    -1004            f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
    -1005        )
    -1006        assert isinstance(resp, dict)
    -1007        return resp
    -1008
    -1009    async def fetch_clan_members(
    -1010        self,
    -1011        clan_id: int,
    -1012        /,
    -1013        *,
    -1014        name: typing.Optional[str] = None,
    -1015        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    -1016    ) -> typedefs.JSONObject:
    -1017        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1018        resp = await self._request(
    -1019            RequestMethod.GET,
    -1020            f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}&currentpage=1",
    -1021        )
    -1022        assert isinstance(resp, dict)
    -1023        return resp
    -1024
    -1025    async def fetch_hardlinked_credentials(
    -1026        self,
    -1027        credential: int,
    -1028        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
    -1029        /,
    -1030    ) -> typedefs.JSONObject:
    -1031        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1032        resp = await self._request(
    -1033            RequestMethod.GET,
    -1034            f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/",
    -1035        )
    -1036        assert isinstance(resp, dict)
    -1037        return resp
    -1038
    -1039    async def fetch_user_credentials(
    -1040        self, access_token: str, membership_id: int, /
    -1041    ) -> typedefs.JSONArray:
    -1042        resp = await self._request(
    -1043            RequestMethod.GET,
    -1044            f"User/GetCredentialTypesForTargetAccount/{membership_id}",
    -1045            auth=access_token,
    -1046        )
    -1047        assert isinstance(resp, list)
    -1048        return resp
    -1049
    -1050    async def insert_socket_plug(
    -1051        self,
    -1052        action_token: str,
    -1053        /,
    -1054        instance_id: int,
    -1055        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
    -1056        character_id: int,
    -1057        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1058    ) -> typedefs.JSONObject:
    -1059
    -1060        if isinstance(plug, builders.PlugSocketBuilder):
    -1061            plug = plug.collect()
    -1062
    -1063        body = {
    -1064            "actionToken": action_token,
    -1065            "itemInstanceId": instance_id,
    -1066            "plug": plug,
    -1067            "characterId": character_id,
    -1068            "membershipType": int(membership_type),
    -1069        }
    -1070        resp = await self._request(
    -1071            RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body
    -1072        )
    -1073        assert isinstance(resp, dict)
    -1074        return resp
    -1075
    -1076    async def insert_socket_plug_free(
    -1077        self,
    -1078        access_token: str,
    -1079        /,
    -1080        instance_id: int,
    -1081        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
    -1082        character_id: int,
    -1083        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1084    ) -> typedefs.JSONObject:
    -1085
    -1086        if isinstance(plug, builders.PlugSocketBuilder):
    -1087            plug = plug.collect()
    -1088
    -1089        body = {
    -1090            "itemInstanceId": instance_id,
    -1091            "plug": plug,
    -1092            "characterId": character_id,
    -1093            "membershipType": int(membership_type),
    -1094        }
    -1095        resp = await self._request(
    -1096            RequestMethod.POST,
    -1097            "Destiny2/Actions/Items/InsertSocketPlugFree",
    -1098            json=body,
    -1099            auth=access_token,
    -1100        )
    -1101        assert isinstance(resp, dict)
    -1102        return resp
    -1103
    -1104    async def set_item_lock_state(
    -1105        self,
    -1106        access_token: str,
    -1107        state: bool,
    -1108        /,
    -1109        item_id: int,
    -1110        character_id: int,
    -1111        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1112    ) -> int:
    -1113        body = {
    -1114            "state": state,
    -1115            "itemId": item_id,
    -1116            "characterId": character_id,
    -1117            "membership_type": int(membership_type),
    -1118        }
    -1119        response = await self._request(
    -1120            RequestMethod.POST,
    -1121            "Destiny2/Actions/Items/SetLockState",
    -1122            json=body,
    -1123            auth=access_token,
    -1124        )
    -1125        assert isinstance(response, int)
    -1126        return response
    -1127
    -1128    async def set_quest_track_state(
    -1129        self,
    -1130        access_token: str,
    -1131        state: bool,
    -1132        /,
    -1133        item_id: int,
    -1134        character_id: int,
    -1135        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1136    ) -> int:
    -1137        body = {
    -1138            "state": state,
    -1139            "itemId": item_id,
    -1140            "characterId": character_id,
    -1141            "membership_type": int(membership_type),
    -1142        }
    -1143        response = await self._request(
    -1144            RequestMethod.POST,
    -1145            "Destiny2/Actions/Items/SetTrackedState",
    -1146            json=body,
    -1147            auth=access_token,
    -1148        )
    -1149        assert isinstance(response, int)
    -1150        return response
    -1151
    -1152    async def fetch_manifest_path(self) -> typedefs.JSONObject:
    -1153        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1154        path = await self._request(RequestMethod.GET, "Destiny2/Manifest")
    -1155        assert isinstance(path, dict)
    -1156        return path
    -1157
    -1158    async def read_manifest_bytes(self, language: str = "en", /) -> bytes:
    -1159        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1160        _ensure_manifest_language(language)
    -1161
    -1162        content = await self.fetch_manifest_path()
    -1163        resp = await self._request(
    -1164            RequestMethod.GET,
    -1165            content["mobileWorldContentPaths"][language],
    -1166            unwrapping="read",
    -1167            base=True,
    -1168        )
    -1169        assert isinstance(resp, bytes)
    -1170        return resp
    -1171
    -1172    async def download_manifest(
    -1173        self,
    -1174        language: str = "en",
    -1175        name: str = "manifest",
    -1176        path: typing.Union[pathlib.Path, str] = ".",
    -1177        *,
    -1178        force: bool = False,
    -1179    ) -> None:
    -1180        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1181        complete_path = _get_path(name, path, sql=True)
    -1182
    -1183        if complete_path.exists() and force:
    -1184            if force:
    -1185                _LOG.info(
    -1186                    f"Found manifest in {complete_path!s}. Forcing to Re-Download."
    -1187                )
    -1188                complete_path.unlink(missing_ok=True)
    -1189
    -1190                return await self.download_manifest(language, name, path, force=force)
    + 965    async def fetch_groups_for_member(
    + 966        self,
    + 967        member_id: int,
    + 968        member_type: typedefs.IntAnd[enums.MembershipType],
    + 969        /,
    + 970        *,
    + 971        filter: int = 0,
    + 972        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    + 973    ) -> typedefs.JSONObject:
    + 974        resp = await self._request(
    + 975            RequestMethod.GET,
    + 976            f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
    + 977        )
    + 978        assert isinstance(resp, dict)
    + 979        return resp
    + 980
    + 981    async def fetch_potential_groups_for_member(
    + 982        self,
    + 983        member_id: int,
    + 984        member_type: typedefs.IntAnd[enums.MembershipType],
    + 985        /,
    + 986        *,
    + 987        filter: int = 0,
    + 988        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    + 989    ) -> typedefs.JSONObject:
    + 990        resp = await self._request(
    + 991            RequestMethod.GET,
    + 992            f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
    + 993        )
    + 994        assert isinstance(resp, dict)
    + 995        return resp
    + 996
    + 997    async def fetch_clan_members(
    + 998        self,
    + 999        clan_id: int,
    +1000        /,
    +1001        *,
    +1002        name: typing.Optional[str] = None,
    +1003        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    +1004    ) -> typedefs.JSONObject:
    +1005        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1006        resp = await self._request(
    +1007            RequestMethod.GET,
    +1008            f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}&currentpage=1",
    +1009        )
    +1010        assert isinstance(resp, dict)
    +1011        return resp
    +1012
    +1013    async def fetch_hardlinked_credentials(
    +1014        self,
    +1015        credential: int,
    +1016        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
    +1017        /,
    +1018    ) -> typedefs.JSONObject:
    +1019        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1020        resp = await self._request(
    +1021            RequestMethod.GET,
    +1022            f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/",
    +1023        )
    +1024        assert isinstance(resp, dict)
    +1025        return resp
    +1026
    +1027    async def fetch_user_credentials(
    +1028        self, access_token: str, membership_id: int, /
    +1029    ) -> typedefs.JSONArray:
    +1030        resp = await self._request(
    +1031            RequestMethod.GET,
    +1032            f"User/GetCredentialTypesForTargetAccount/{membership_id}",
    +1033            auth=access_token,
    +1034        )
    +1035        assert isinstance(resp, list)
    +1036        return resp
    +1037
    +1038    async def insert_socket_plug(
    +1039        self,
    +1040        action_token: str,
    +1041        /,
    +1042        instance_id: int,
    +1043        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
    +1044        character_id: int,
    +1045        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1046    ) -> typedefs.JSONObject:
    +1047
    +1048        if isinstance(plug, builders.PlugSocketBuilder):
    +1049            plug = plug.collect()
    +1050
    +1051        body = {
    +1052            "actionToken": action_token,
    +1053            "itemInstanceId": instance_id,
    +1054            "plug": plug,
    +1055            "characterId": character_id,
    +1056            "membershipType": int(membership_type),
    +1057        }
    +1058        resp = await self._request(
    +1059            RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body
    +1060        )
    +1061        assert isinstance(resp, dict)
    +1062        return resp
    +1063
    +1064    async def insert_socket_plug_free(
    +1065        self,
    +1066        access_token: str,
    +1067        /,
    +1068        instance_id: int,
    +1069        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
    +1070        character_id: int,
    +1071        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1072    ) -> typedefs.JSONObject:
    +1073
    +1074        if isinstance(plug, builders.PlugSocketBuilder):
    +1075            plug = plug.collect()
    +1076
    +1077        body = {
    +1078            "itemInstanceId": instance_id,
    +1079            "plug": plug,
    +1080            "characterId": character_id,
    +1081            "membershipType": int(membership_type),
    +1082        }
    +1083        resp = await self._request(
    +1084            RequestMethod.POST,
    +1085            "Destiny2/Actions/Items/InsertSocketPlugFree",
    +1086            json=body,
    +1087            auth=access_token,
    +1088        )
    +1089        assert isinstance(resp, dict)
    +1090        return resp
    +1091
    +1092    async def set_item_lock_state(
    +1093        self,
    +1094        access_token: str,
    +1095        state: bool,
    +1096        /,
    +1097        item_id: int,
    +1098        character_id: int,
    +1099        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1100    ) -> int:
    +1101        body = {
    +1102            "state": state,
    +1103            "itemId": item_id,
    +1104            "characterId": character_id,
    +1105            "membership_type": int(membership_type),
    +1106        }
    +1107        response = await self._request(
    +1108            RequestMethod.POST,
    +1109            "Destiny2/Actions/Items/SetLockState",
    +1110            json=body,
    +1111            auth=access_token,
    +1112        )
    +1113        assert isinstance(response, int)
    +1114        return response
    +1115
    +1116    async def set_quest_track_state(
    +1117        self,
    +1118        access_token: str,
    +1119        state: bool,
    +1120        /,
    +1121        item_id: int,
    +1122        character_id: int,
    +1123        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1124    ) -> int:
    +1125        body = {
    +1126            "state": state,
    +1127            "itemId": item_id,
    +1128            "characterId": character_id,
    +1129            "membership_type": int(membership_type),
    +1130        }
    +1131        response = await self._request(
    +1132            RequestMethod.POST,
    +1133            "Destiny2/Actions/Items/SetTrackedState",
    +1134            json=body,
    +1135            auth=access_token,
    +1136        )
    +1137        assert isinstance(response, int)
    +1138        return response
    +1139
    +1140    async def fetch_manifest_path(self) -> typedefs.JSONObject:
    +1141        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1142        path = await self._request(RequestMethod.GET, "Destiny2/Manifest")
    +1143        assert isinstance(path, dict)
    +1144        return path
    +1145
    +1146    async def read_manifest_bytes(self, language: str = "en", /) -> bytes:
    +1147        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1148        _ensure_manifest_language(language)
    +1149
    +1150        content = await self.fetch_manifest_path()
    +1151        resp = await self._request(
    +1152            RequestMethod.GET,
    +1153            content["mobileWorldContentPaths"][language],
    +1154            unwrapping="read",
    +1155            base=True,
    +1156        )
    +1157        assert isinstance(resp, bytes)
    +1158        return resp
    +1159
    +1160    async def download_manifest(
    +1161        self,
    +1162        language: str = "en",
    +1163        name: str = "manifest",
    +1164        path: typing.Union[pathlib.Path, str] = ".",
    +1165        *,
    +1166        force: bool = False,
    +1167    ) -> None:
    +1168        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1169        complete_path = _get_path(name, path, sql=True)
    +1170
    +1171        if complete_path.exists() and force:
    +1172            if force:
    +1173                _LOG.info(
    +1174                    f"Found manifest in {complete_path!s}. Forcing to Re-Download."
    +1175                )
    +1176                complete_path.unlink(missing_ok=True)
    +1177
    +1178                return await self.download_manifest(language, name, path, force=force)
    +1179
    +1180            else:
    +1181                raise FileExistsError(
    +1182                    "Manifest file already exists, "
    +1183                    "To force download, set the `force` parameter to `True`."
    +1184                )
    +1185
    +1186        _LOG.info(f"Downloading manifest. Location: {complete_path!s}")
    +1187        data_bytes = await self.read_manifest_bytes(language)
    +1188        await asyncio.get_running_loop().run_in_executor(
    +1189            None, _write_sqlite_bytes, data_bytes, path, name
    +1190        )
     1191
    -1192            else:
    -1193                raise FileExistsError(
    -1194                    "Manifest file already exists, "
    -1195                    "To force download, set the `force` parameter to `True`."
    -1196                )
    -1197
    -1198        _LOG.info(f"Downloading manifest. Location: {complete_path!s}")
    -1199        data_bytes = await self.read_manifest_bytes(language)
    -1200        await asyncio.get_running_loop().run_in_executor(
    -1201            None, _write_sqlite_bytes, data_bytes, path, name
    -1202        )
    -1203
    -1204    async def download_json_manifest(
    -1205        self,
    -1206        file_name: str = "manifest",
    -1207        path: typing.Union[str, pathlib.Path] = ".",
    -1208        language: str = "en",
    -1209    ) -> None:
    -1210        _ensure_manifest_language(language)
    -1211
    -1212        _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...")
    -1213
    -1214        content = await self.fetch_manifest_path()
    -1215        json_bytes = await self._request(
    -1216            RequestMethod.GET,
    -1217            content["jsonWorldContentPaths"][language],
    -1218            unwrapping="read",
    -1219            base=True,
    -1220        )
    -1221
    -1222        await asyncio.get_running_loop().run_in_executor(
    -1223            None, _write_json_bytes, json_bytes, file_name, path
    -1224        )
    -1225        _LOG.info("Finished downloading manifest JSON.")
    -1226
    -1227    async def fetch_manifest_version(self) -> str:
    -1228        return typing.cast(str, (await self.fetch_manifest_path())["version"])
    -1229
    -1230    async def fetch_linked_profiles(
    -1231        self,
    -1232        member_id: int,
    -1233        member_type: typedefs.IntAnd[enums.MembershipType],
    -1234        /,
    -1235        *,
    -1236        all: bool = False,
    -1237    ) -> typedefs.JSONObject:
    -1238        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1239        resp = await self._request(
    -1240            RequestMethod.GET,
    -1241            f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}",
    -1242        )
    -1243        assert isinstance(resp, dict)
    -1244        return resp
    -1245
    -1246    async def fetch_clan_banners(self) -> typedefs.JSONObject:
    -1247        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1248        resp = await self._request(
    -1249            RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/"
    -1250        )
    -1251        assert isinstance(resp, dict)
    -1252        return resp
    -1253
    -1254    async def fetch_public_milestones(self) -> typedefs.JSONObject:
    -1255        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1256        resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/")
    -1257        assert isinstance(resp, dict)
    -1258        return resp
    -1259
    -1260    async def fetch_public_milestone_content(
    -1261        self, milestone_hash: int, /
    -1262    ) -> typedefs.JSONObject:
    -1263        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1264        resp = await self._request(
    -1265            RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/"
    +1192    async def download_json_manifest(
    +1193        self,
    +1194        file_name: str = "manifest",
    +1195        path: typing.Union[str, pathlib.Path] = ".",
    +1196        language: str = "en",
    +1197    ) -> None:
    +1198        _ensure_manifest_language(language)
    +1199
    +1200        _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...")
    +1201
    +1202        content = await self.fetch_manifest_path()
    +1203        json_bytes = await self._request(
    +1204            RequestMethod.GET,
    +1205            content["jsonWorldContentPaths"][language],
    +1206            unwrapping="read",
    +1207            base=True,
    +1208        )
    +1209
    +1210        await asyncio.get_running_loop().run_in_executor(
    +1211            None, _write_json_bytes, json_bytes, file_name, path
    +1212        )
    +1213        _LOG.info("Finished downloading manifest JSON.")
    +1214
    +1215    async def fetch_manifest_version(self) -> str:
    +1216        return typing.cast(str, (await self.fetch_manifest_path())["version"])
    +1217
    +1218    async def fetch_linked_profiles(
    +1219        self,
    +1220        member_id: int,
    +1221        member_type: typedefs.IntAnd[enums.MembershipType],
    +1222        /,
    +1223        *,
    +1224        all: bool = False,
    +1225    ) -> typedefs.JSONObject:
    +1226        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1227        resp = await self._request(
    +1228            RequestMethod.GET,
    +1229            f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}",
    +1230        )
    +1231        assert isinstance(resp, dict)
    +1232        return resp
    +1233
    +1234    async def fetch_clan_banners(self) -> typedefs.JSONObject:
    +1235        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1236        resp = await self._request(
    +1237            RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/"
    +1238        )
    +1239        assert isinstance(resp, dict)
    +1240        return resp
    +1241
    +1242    async def fetch_public_milestones(self) -> typedefs.JSONObject:
    +1243        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1244        resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/")
    +1245        assert isinstance(resp, dict)
    +1246        return resp
    +1247
    +1248    async def fetch_public_milestone_content(
    +1249        self, milestone_hash: int, /
    +1250    ) -> typedefs.JSONObject:
    +1251        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1252        resp = await self._request(
    +1253            RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/"
    +1254        )
    +1255        assert isinstance(resp, dict)
    +1256        return resp
    +1257
    +1258    async def fetch_current_user_memberships(
    +1259        self, access_token: str, /
    +1260    ) -> typedefs.JSONObject:
    +1261        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1262        resp = await self._request(
    +1263            RequestMethod.GET,
    +1264            "User/GetMembershipsForCurrentUser/",
    +1265            auth=access_token,
     1266        )
     1267        assert isinstance(resp, dict)
     1268        return resp
     1269
    -1270    async def fetch_current_user_memberships(
    -1271        self, access_token: str, /
    -1272    ) -> typedefs.JSONObject:
    -1273        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1274        resp = await self._request(
    -1275            RequestMethod.GET,
    -1276            "User/GetMembershipsForCurrentUser/",
    -1277            auth=access_token,
    -1278        )
    -1279        assert isinstance(resp, dict)
    -1280        return resp
    -1281
    -1282    async def equip_item(
    -1283        self,
    -1284        access_token: str,
    -1285        /,
    -1286        item_id: int,
    -1287        character_id: int,
    -1288        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1289    ) -> None:
    -1290        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1291        payload = {
    -1292            "itemId": item_id,
    -1293            "characterId": character_id,
    -1294            "membershipType": int(membership_type),
    -1295        }
    -1296
    -1297        await self._request(
    -1298            RequestMethod.POST,
    -1299            "Destiny2/Actions/Items/EquipItem/",
    -1300            json=payload,
    -1301            auth=access_token,
    -1302        )
    -1303
    -1304    async def equip_items(
    -1305        self,
    -1306        access_token: str,
    -1307        /,
    -1308        item_ids: list[int],
    -1309        character_id: int,
    -1310        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1311    ) -> None:
    -1312        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1313        payload = {
    -1314            "itemIds": item_ids,
    -1315            "characterId": character_id,
    -1316            "membershipType": int(membership_type),
    -1317        }
    -1318        await self._request(
    -1319            RequestMethod.POST,
    -1320            "Destiny2/Actions/Items/EquipItems/",
    -1321            json=payload,
    -1322            auth=access_token,
    -1323        )
    -1324
    -1325    async def ban_clan_member(
    -1326        self,
    -1327        access_token: str,
    -1328        /,
    -1329        group_id: int,
    -1330        membership_id: int,
    -1331        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1332        *,
    -1333        length: int = 0,
    -1334        comment: undefined.UndefinedOr[str] = undefined.Undefined,
    -1335    ) -> None:
    -1336        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1337        payload = {"comment": str(comment), "length": length}
    -1338        await self._request(
    -1339            RequestMethod.POST,
    -1340            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/",
    -1341            json=payload,
    -1342            auth=access_token,
    -1343        )
    -1344
    -1345    async def unban_clan_member(
    -1346        self,
    -1347        access_token: str,
    -1348        /,
    -1349        group_id: int,
    -1350        membership_id: int,
    -1351        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1352    ) -> None:
    -1353        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1354        await self._request(
    -1355            RequestMethod.POST,
    -1356            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/",
    -1357            auth=access_token,
    -1358        )
    -1359
    -1360    async def kick_clan_member(
    -1361        self,
    -1362        access_token: str,
    -1363        /,
    -1364        group_id: int,
    -1365        membership_id: int,
    -1366        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1367    ) -> typedefs.JSONObject:
    -1368        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1369        resp = await self._request(
    -1370            RequestMethod.POST,
    -1371            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/",
    -1372            auth=access_token,
    -1373        )
    -1374        assert isinstance(resp, dict)
    -1375        return resp
    -1376
    -1377    async def edit_clan(
    -1378        self,
    -1379        access_token: str,
    -1380        /,
    -1381        group_id: int,
    -1382        *,
    -1383        name: typedefs.NoneOr[str] = None,
    -1384        about: typedefs.NoneOr[str] = None,
    -1385        motto: typedefs.NoneOr[str] = None,
    -1386        theme: typedefs.NoneOr[str] = None,
    -1387        tags: typedefs.NoneOr[collections.Sequence[str]] = None,
    -1388        is_public: typedefs.NoneOr[bool] = None,
    -1389        locale: typedefs.NoneOr[str] = None,
    -1390        avatar_image_index: typedefs.NoneOr[int] = None,
    -1391        membership_option: typedefs.NoneOr[
    -1392            typedefs.IntAnd[enums.MembershipOption]
    -1393        ] = None,
    -1394        allow_chat: typedefs.NoneOr[bool] = None,
    -1395        chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None,
    -1396        call_sign: typedefs.NoneOr[str] = None,
    -1397        homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
    -1398        enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None,
    -1399        default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
    -1400        is_public_topic_admin: typedefs.NoneOr[bool] = None,
    -1401    ) -> None:
    -1402        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1403        payload = {
    -1404            "name": name,
    -1405            "about": about,
    -1406            "motto": motto,
    -1407            "theme": theme,
    -1408            "tags": tags,
    -1409            "isPublic": is_public,
    -1410            "avatarImageIndex": avatar_image_index,
    -1411            "isPublicTopicAdminOnly": is_public_topic_admin,
    -1412            "allowChat": allow_chat,
    -1413            "chatSecurity": chat_security,
    -1414            "callsign": call_sign,
    -1415            "homepage": homepage,
    -1416            "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins,
    -1417            "defaultPublicity": default_publicity,
    -1418            "locale": locale,
    -1419        }
    -1420        if membership_option is not None:
    -1421            payload["membershipOption"] = int(membership_option)
    -1422
    -1423        await self._request(
    -1424            RequestMethod.POST,
    -1425            f"GroupV2/{group_id}/Edit",
    -1426            json=payload,
    -1427            auth=access_token,
    -1428        )
    -1429
    -1430    async def edit_clan_options(
    -1431        self,
    -1432        access_token: str,
    -1433        /,
    -1434        group_id: int,
    -1435        *,
    -1436        invite_permissions_override: typedefs.NoneOr[bool] = None,
    -1437        update_culture_permissionOverride: typedefs.NoneOr[bool] = None,
    -1438        host_guided_game_permission_override: typedefs.NoneOr[
    -1439            typing.Literal[0, 1, 2]
    -1440        ] = None,
    -1441        update_banner_permission_override: typedefs.NoneOr[bool] = None,
    -1442        join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None,
    -1443    ) -> None:
    -1444
    -1445        payload = {
    -1446            "InvitePermissionOverride": invite_permissions_override,
    -1447            "UpdateCulturePermissionOverride": update_culture_permissionOverride,
    -1448            "HostGuidedGamePermissionOverride": host_guided_game_permission_override,
    -1449            "UpdateBannerPermissionOverride": update_banner_permission_override,
    -1450            "JoinLevel": int(join_level) if join_level else None,
    -1451        }
    -1452
    -1453        await self._request(
    -1454            RequestMethod.POST,
    -1455            f"GroupV2/{group_id}/EditFounderOptions",
    -1456            json=payload,
    -1457            auth=access_token,
    -1458        )
    -1459
    -1460    async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject:
    -1461        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1462        resp = await self._request(
    -1463            RequestMethod.GET,
    -1464            "Social/Friends/",
    -1465            auth=access_token,
    -1466        )
    -1467        assert isinstance(resp, dict)
    -1468        return resp
    -1469
    -1470    async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject:
    -1471        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1472        resp = await self._request(
    -1473            RequestMethod.GET,
    -1474            "Social/Friends/Requests",
    -1475            auth=access_token,
    -1476        )
    -1477        assert isinstance(resp, dict)
    -1478        return resp
    -1479
    -1480    async def accept_friend_request(self, access_token: str, /, member_id: int) -> None:
    -1481        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1482        await self._request(
    -1483            RequestMethod.POST,
    -1484            f"Social/Friends/Requests/Accept/{member_id}",
    -1485            auth=access_token,
    -1486        )
    -1487
    -1488    async def send_friend_request(self, access_token: str, /, member_id: int) -> None:
    -1489        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1490        await self._request(
    -1491            RequestMethod.POST,
    -1492            f"Social/Friends/Add/{member_id}",
    -1493            auth=access_token,
    -1494        )
    -1495
    -1496    async def decline_friend_request(
    -1497        self, access_token: str, /, member_id: int
    -1498    ) -> None:
    -1499        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1500        await self._request(
    -1501            RequestMethod.POST,
    -1502            f"Social/Friends/Requests/Decline/{member_id}",
    -1503            auth=access_token,
    -1504        )
    -1505
    -1506    async def remove_friend(self, access_token: str, /, member_id: int) -> None:
    -1507        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1508        await self._request(
    -1509            RequestMethod.POST,
    -1510            f"Social/Friends/Remove/{member_id}",
    -1511            auth=access_token,
    -1512        )
    -1513
    -1514    async def remove_friend_request(self, access_token: str, /, member_id: int) -> None:
    -1515        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1516        await self._request(
    -1517            RequestMethod.POST,
    -1518            f"Social/Friends/Requests/Remove/{member_id}",
    -1519            auth=access_token,
    -1520        )
    -1521
    -1522    async def approve_all_pending_group_users(
    -1523        self,
    -1524        access_token: str,
    -1525        /,
    -1526        group_id: int,
    -1527        message: undefined.UndefinedOr[str] = undefined.Undefined,
    -1528    ) -> None:
    -1529        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1530        await self._request(
    -1531            RequestMethod.POST,
    -1532            f"GroupV2/{group_id}/Members/ApproveAll",
    -1533            auth=access_token,
    -1534            json={"message": str(message)},
    -1535        )
    -1536
    -1537    async def deny_all_pending_group_users(
    -1538        self,
    -1539        access_token: str,
    -1540        /,
    -1541        group_id: int,
    -1542        *,
    -1543        message: undefined.UndefinedOr[str] = undefined.Undefined,
    -1544    ) -> None:
    -1545        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1546        await self._request(
    -1547            RequestMethod.POST,
    -1548            f"GroupV2/{group_id}/Members/DenyAll",
    -1549            auth=access_token,
    -1550            json={"message": str(message)},
    -1551        )
    -1552
    -1553    async def add_optional_conversation(
    -1554        self,
    -1555        access_token: str,
    -1556        /,
    -1557        group_id: int,
    -1558        *,
    -1559        name: undefined.UndefinedOr[str] = undefined.Undefined,
    -1560        security: typing.Literal[0, 1] = 0,
    -1561    ) -> None:
    -1562        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1563        payload = {"chatName": str(name), "chatSecurity": security}
    -1564        await self._request(
    -1565            RequestMethod.POST,
    -1566            f"GroupV2/{group_id}/OptionalConversations/Add",
    -1567            json=payload,
    -1568            auth=access_token,
    -1569        )
    -1570
    -1571    async def edit_optional_conversation(
    -1572        self,
    -1573        access_token: str,
    -1574        /,
    -1575        group_id: int,
    -1576        conversation_id: int,
    -1577        *,
    -1578        name: undefined.UndefinedOr[str] = undefined.Undefined,
    -1579        security: typing.Literal[0, 1] = 0,
    -1580        enable_chat: bool = False,
    -1581    ) -> None:
    -1582        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1583        payload = {
    -1584            "chatEnabled": enable_chat,
    -1585            "chatName": str(name),
    -1586            "chatSecurity": security,
    -1587        }
    -1588        await self._request(
    -1589            RequestMethod.POST,
    -1590            f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}",
    -1591            json=payload,
    -1592            auth=access_token,
    -1593        )
    -1594
    -1595    async def transfer_item(
    -1596        self,
    -1597        access_token: str,
    -1598        /,
    -1599        item_id: int,
    -1600        item_hash: int,
    -1601        character_id: int,
    -1602        member_type: typedefs.IntAnd[enums.MembershipType],
    -1603        *,
    -1604        stack_size: int = 1,
    -1605        vault: bool = False,
    -1606    ) -> None:
    -1607        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1608        payload = {
    -1609            "characterId": character_id,
    -1610            "membershipType": int(member_type),
    -1611            "itemId": item_id,
    -1612            "itemReferenceHash": item_hash,
    -1613            "stackSize": stack_size,
    -1614            "transferToVault": vault,
    -1615        }
    -1616        await self._request(
    -1617            RequestMethod.POST,
    -1618            "Destiny2/Actions/Items/TransferItem",
    -1619            json=payload,
    -1620            auth=access_token,
    -1621        )
    -1622
    -1623    async def pull_item(
    -1624        self,
    -1625        access_token: str,
    -1626        /,
    -1627        item_id: int,
    -1628        item_hash: int,
    -1629        character_id: int,
    -1630        member_type: typedefs.IntAnd[enums.MembershipType],
    -1631        *,
    -1632        stack_size: int = 1,
    -1633        vault: bool = False,
    -1634    ) -> None:
    -1635        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1636        payload = {
    -1637            "characterId": character_id,
    -1638            "membershipType": int(member_type),
    -1639            "itemId": item_id,
    -1640            "itemReferenceHash": item_hash,
    -1641            "stackSize": stack_size,
    -1642            "transferToVault": vault,
    -1643        }
    -1644        await self._request(
    -1645            RequestMethod.POST,
    -1646            "Destiny2/Actions/Items/PullFromPostmaster",
    -1647            json=payload,
    -1648            auth=access_token,
    -1649        )
    -1650
    -1651    async def fetch_fireteams(
    -1652        self,
    -1653        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    -1654        *,
    -1655        platform: typedefs.IntAnd[
    -1656            fireteams.FireteamPlatform
    -1657        ] = fireteams.FireteamPlatform.ANY,
    -1658        language: typing.Union[
    -1659            fireteams.FireteamLanguage, str
    -1660        ] = fireteams.FireteamLanguage.ALL,
    -1661        date_range: typedefs.IntAnd[
    -1662            fireteams.FireteamDate
    -1663        ] = fireteams.FireteamDate.ALL,
    -1664        page: int = 0,
    -1665        slots_filter: int = 0,
    -1666    ) -> typedefs.JSONObject:
    -1667        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1668        resp = await self._request(
    -1669            RequestMethod.GET,
    -1670            f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}",  # noqa: E501 Line too long
    -1671        )
    -1672        assert isinstance(resp, dict)
    -1673        return resp
    -1674
    -1675    async def fetch_avaliable_clan_fireteams(
    -1676        self,
    -1677        access_token: str,
    -1678        group_id: int,
    -1679        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    -1680        *,
    -1681        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    -1682        language: typing.Union[fireteams.FireteamLanguage, str],
    -1683        date_range: typedefs.IntAnd[
    -1684            fireteams.FireteamDate
    -1685        ] = fireteams.FireteamDate.ALL,
    -1686        page: int = 0,
    -1687        public_only: bool = False,
    -1688        slots_filter: int = 0,
    -1689    ) -> typedefs.JSONObject:
    -1690        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1691        resp = await self._request(
    -1692            RequestMethod.GET,
    -1693            f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}",  # noqa: E501
    -1694            json={"langFilter": str(language)},
    +1270    async def equip_item(
    +1271        self,
    +1272        access_token: str,
    +1273        /,
    +1274        item_id: int,
    +1275        character_id: int,
    +1276        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1277    ) -> None:
    +1278        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1279        payload = {
    +1280            "itemId": item_id,
    +1281            "characterId": character_id,
    +1282            "membershipType": int(membership_type),
    +1283        }
    +1284
    +1285        await self._request(
    +1286            RequestMethod.POST,
    +1287            "Destiny2/Actions/Items/EquipItem/",
    +1288            json=payload,
    +1289            auth=access_token,
    +1290        )
    +1291
    +1292    async def equip_items(
    +1293        self,
    +1294        access_token: str,
    +1295        /,
    +1296        item_ids: list[int],
    +1297        character_id: int,
    +1298        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1299    ) -> None:
    +1300        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1301        payload = {
    +1302            "itemIds": item_ids,
    +1303            "characterId": character_id,
    +1304            "membershipType": int(membership_type),
    +1305        }
    +1306        await self._request(
    +1307            RequestMethod.POST,
    +1308            "Destiny2/Actions/Items/EquipItems/",
    +1309            json=payload,
    +1310            auth=access_token,
    +1311        )
    +1312
    +1313    async def ban_clan_member(
    +1314        self,
    +1315        access_token: str,
    +1316        /,
    +1317        group_id: int,
    +1318        membership_id: int,
    +1319        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1320        *,
    +1321        length: int = 0,
    +1322        comment: undefined.UndefinedOr[str] = undefined.Undefined,
    +1323    ) -> None:
    +1324        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1325        payload = {"comment": str(comment), "length": length}
    +1326        await self._request(
    +1327            RequestMethod.POST,
    +1328            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/",
    +1329            json=payload,
    +1330            auth=access_token,
    +1331        )
    +1332
    +1333    async def unban_clan_member(
    +1334        self,
    +1335        access_token: str,
    +1336        /,
    +1337        group_id: int,
    +1338        membership_id: int,
    +1339        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1340    ) -> None:
    +1341        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1342        await self._request(
    +1343            RequestMethod.POST,
    +1344            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/",
    +1345            auth=access_token,
    +1346        )
    +1347
    +1348    async def kick_clan_member(
    +1349        self,
    +1350        access_token: str,
    +1351        /,
    +1352        group_id: int,
    +1353        membership_id: int,
    +1354        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1355    ) -> typedefs.JSONObject:
    +1356        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1357        resp = await self._request(
    +1358            RequestMethod.POST,
    +1359            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/",
    +1360            auth=access_token,
    +1361        )
    +1362        assert isinstance(resp, dict)
    +1363        return resp
    +1364
    +1365    async def edit_clan(
    +1366        self,
    +1367        access_token: str,
    +1368        /,
    +1369        group_id: int,
    +1370        *,
    +1371        name: typedefs.NoneOr[str] = None,
    +1372        about: typedefs.NoneOr[str] = None,
    +1373        motto: typedefs.NoneOr[str] = None,
    +1374        theme: typedefs.NoneOr[str] = None,
    +1375        tags: typedefs.NoneOr[collections.Sequence[str]] = None,
    +1376        is_public: typedefs.NoneOr[bool] = None,
    +1377        locale: typedefs.NoneOr[str] = None,
    +1378        avatar_image_index: typedefs.NoneOr[int] = None,
    +1379        membership_option: typedefs.NoneOr[
    +1380            typedefs.IntAnd[enums.MembershipOption]
    +1381        ] = None,
    +1382        allow_chat: typedefs.NoneOr[bool] = None,
    +1383        chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None,
    +1384        call_sign: typedefs.NoneOr[str] = None,
    +1385        homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
    +1386        enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None,
    +1387        default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
    +1388        is_public_topic_admin: typedefs.NoneOr[bool] = None,
    +1389    ) -> None:
    +1390        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1391        payload = {
    +1392            "name": name,
    +1393            "about": about,
    +1394            "motto": motto,
    +1395            "theme": theme,
    +1396            "tags": tags,
    +1397            "isPublic": is_public,
    +1398            "avatarImageIndex": avatar_image_index,
    +1399            "isPublicTopicAdminOnly": is_public_topic_admin,
    +1400            "allowChat": allow_chat,
    +1401            "chatSecurity": chat_security,
    +1402            "callsign": call_sign,
    +1403            "homepage": homepage,
    +1404            "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins,
    +1405            "defaultPublicity": default_publicity,
    +1406            "locale": locale,
    +1407        }
    +1408        if membership_option is not None:
    +1409            payload["membershipOption"] = int(membership_option)
    +1410
    +1411        await self._request(
    +1412            RequestMethod.POST,
    +1413            f"GroupV2/{group_id}/Edit",
    +1414            json=payload,
    +1415            auth=access_token,
    +1416        )
    +1417
    +1418    async def edit_clan_options(
    +1419        self,
    +1420        access_token: str,
    +1421        /,
    +1422        group_id: int,
    +1423        *,
    +1424        invite_permissions_override: typedefs.NoneOr[bool] = None,
    +1425        update_culture_permissionOverride: typedefs.NoneOr[bool] = None,
    +1426        host_guided_game_permission_override: typedefs.NoneOr[
    +1427            typing.Literal[0, 1, 2]
    +1428        ] = None,
    +1429        update_banner_permission_override: typedefs.NoneOr[bool] = None,
    +1430        join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None,
    +1431    ) -> None:
    +1432
    +1433        payload = {
    +1434            "InvitePermissionOverride": invite_permissions_override,
    +1435            "UpdateCulturePermissionOverride": update_culture_permissionOverride,
    +1436            "HostGuidedGamePermissionOverride": host_guided_game_permission_override,
    +1437            "UpdateBannerPermissionOverride": update_banner_permission_override,
    +1438            "JoinLevel": int(join_level) if join_level else None,
    +1439        }
    +1440
    +1441        await self._request(
    +1442            RequestMethod.POST,
    +1443            f"GroupV2/{group_id}/EditFounderOptions",
    +1444            json=payload,
    +1445            auth=access_token,
    +1446        )
    +1447
    +1448    async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject:
    +1449        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1450        resp = await self._request(
    +1451            RequestMethod.GET,
    +1452            "Social/Friends/",
    +1453            auth=access_token,
    +1454        )
    +1455        assert isinstance(resp, dict)
    +1456        return resp
    +1457
    +1458    async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject:
    +1459        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1460        resp = await self._request(
    +1461            RequestMethod.GET,
    +1462            "Social/Friends/Requests",
    +1463            auth=access_token,
    +1464        )
    +1465        assert isinstance(resp, dict)
    +1466        return resp
    +1467
    +1468    async def accept_friend_request(self, access_token: str, /, member_id: int) -> None:
    +1469        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1470        await self._request(
    +1471            RequestMethod.POST,
    +1472            f"Social/Friends/Requests/Accept/{member_id}",
    +1473            auth=access_token,
    +1474        )
    +1475
    +1476    async def send_friend_request(self, access_token: str, /, member_id: int) -> None:
    +1477        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1478        await self._request(
    +1479            RequestMethod.POST,
    +1480            f"Social/Friends/Add/{member_id}",
    +1481            auth=access_token,
    +1482        )
    +1483
    +1484    async def decline_friend_request(
    +1485        self, access_token: str, /, member_id: int
    +1486    ) -> None:
    +1487        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1488        await self._request(
    +1489            RequestMethod.POST,
    +1490            f"Social/Friends/Requests/Decline/{member_id}",
    +1491            auth=access_token,
    +1492        )
    +1493
    +1494    async def remove_friend(self, access_token: str, /, member_id: int) -> None:
    +1495        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1496        await self._request(
    +1497            RequestMethod.POST,
    +1498            f"Social/Friends/Remove/{member_id}",
    +1499            auth=access_token,
    +1500        )
    +1501
    +1502    async def remove_friend_request(self, access_token: str, /, member_id: int) -> None:
    +1503        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1504        await self._request(
    +1505            RequestMethod.POST,
    +1506            f"Social/Friends/Requests/Remove/{member_id}",
    +1507            auth=access_token,
    +1508        )
    +1509
    +1510    async def approve_all_pending_group_users(
    +1511        self,
    +1512        access_token: str,
    +1513        /,
    +1514        group_id: int,
    +1515        message: undefined.UndefinedOr[str] = undefined.Undefined,
    +1516    ) -> None:
    +1517        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1518        await self._request(
    +1519            RequestMethod.POST,
    +1520            f"GroupV2/{group_id}/Members/ApproveAll",
    +1521            auth=access_token,
    +1522            json={"message": str(message)},
    +1523        )
    +1524
    +1525    async def deny_all_pending_group_users(
    +1526        self,
    +1527        access_token: str,
    +1528        /,
    +1529        group_id: int,
    +1530        *,
    +1531        message: undefined.UndefinedOr[str] = undefined.Undefined,
    +1532    ) -> None:
    +1533        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1534        await self._request(
    +1535            RequestMethod.POST,
    +1536            f"GroupV2/{group_id}/Members/DenyAll",
    +1537            auth=access_token,
    +1538            json={"message": str(message)},
    +1539        )
    +1540
    +1541    async def add_optional_conversation(
    +1542        self,
    +1543        access_token: str,
    +1544        /,
    +1545        group_id: int,
    +1546        *,
    +1547        name: undefined.UndefinedOr[str] = undefined.Undefined,
    +1548        security: typing.Literal[0, 1] = 0,
    +1549    ) -> None:
    +1550        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1551        payload = {"chatName": str(name), "chatSecurity": security}
    +1552        await self._request(
    +1553            RequestMethod.POST,
    +1554            f"GroupV2/{group_id}/OptionalConversations/Add",
    +1555            json=payload,
    +1556            auth=access_token,
    +1557        )
    +1558
    +1559    async def edit_optional_conversation(
    +1560        self,
    +1561        access_token: str,
    +1562        /,
    +1563        group_id: int,
    +1564        conversation_id: int,
    +1565        *,
    +1566        name: undefined.UndefinedOr[str] = undefined.Undefined,
    +1567        security: typing.Literal[0, 1] = 0,
    +1568        enable_chat: bool = False,
    +1569    ) -> None:
    +1570        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1571        payload = {
    +1572            "chatEnabled": enable_chat,
    +1573            "chatName": str(name),
    +1574            "chatSecurity": security,
    +1575        }
    +1576        await self._request(
    +1577            RequestMethod.POST,
    +1578            f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}",
    +1579            json=payload,
    +1580            auth=access_token,
    +1581        )
    +1582
    +1583    async def transfer_item(
    +1584        self,
    +1585        access_token: str,
    +1586        /,
    +1587        item_id: int,
    +1588        item_hash: int,
    +1589        character_id: int,
    +1590        member_type: typedefs.IntAnd[enums.MembershipType],
    +1591        *,
    +1592        stack_size: int = 1,
    +1593        vault: bool = False,
    +1594    ) -> None:
    +1595        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1596        payload = {
    +1597            "characterId": character_id,
    +1598            "membershipType": int(member_type),
    +1599            "itemId": item_id,
    +1600            "itemReferenceHash": item_hash,
    +1601            "stackSize": stack_size,
    +1602            "transferToVault": vault,
    +1603        }
    +1604        await self._request(
    +1605            RequestMethod.POST,
    +1606            "Destiny2/Actions/Items/TransferItem",
    +1607            json=payload,
    +1608            auth=access_token,
    +1609        )
    +1610
    +1611    async def pull_item(
    +1612        self,
    +1613        access_token: str,
    +1614        /,
    +1615        item_id: int,
    +1616        item_hash: int,
    +1617        character_id: int,
    +1618        member_type: typedefs.IntAnd[enums.MembershipType],
    +1619        *,
    +1620        stack_size: int = 1,
    +1621        vault: bool = False,
    +1622    ) -> None:
    +1623        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1624        payload = {
    +1625            "characterId": character_id,
    +1626            "membershipType": int(member_type),
    +1627            "itemId": item_id,
    +1628            "itemReferenceHash": item_hash,
    +1629            "stackSize": stack_size,
    +1630            "transferToVault": vault,
    +1631        }
    +1632        await self._request(
    +1633            RequestMethod.POST,
    +1634            "Destiny2/Actions/Items/PullFromPostmaster",
    +1635            json=payload,
    +1636            auth=access_token,
    +1637        )
    +1638
    +1639    async def fetch_fireteams(
    +1640        self,
    +1641        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    +1642        *,
    +1643        platform: typedefs.IntAnd[
    +1644            fireteams.FireteamPlatform
    +1645        ] = fireteams.FireteamPlatform.ANY,
    +1646        language: typing.Union[
    +1647            fireteams.FireteamLanguage, str
    +1648        ] = fireteams.FireteamLanguage.ALL,
    +1649        date_range: typedefs.IntAnd[
    +1650            fireteams.FireteamDate
    +1651        ] = fireteams.FireteamDate.ALL,
    +1652        page: int = 0,
    +1653        slots_filter: int = 0,
    +1654    ) -> typedefs.JSONObject:
    +1655        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1656        resp = await self._request(
    +1657            RequestMethod.GET,
    +1658            f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}",  # noqa: E501 Line too long
    +1659        )
    +1660        assert isinstance(resp, dict)
    +1661        return resp
    +1662
    +1663    async def fetch_avaliable_clan_fireteams(
    +1664        self,
    +1665        access_token: str,
    +1666        group_id: int,
    +1667        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    +1668        *,
    +1669        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    +1670        language: typing.Union[fireteams.FireteamLanguage, str],
    +1671        date_range: typedefs.IntAnd[
    +1672            fireteams.FireteamDate
    +1673        ] = fireteams.FireteamDate.ALL,
    +1674        page: int = 0,
    +1675        public_only: bool = False,
    +1676        slots_filter: int = 0,
    +1677    ) -> typedefs.JSONObject:
    +1678        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1679        resp = await self._request(
    +1680            RequestMethod.GET,
    +1681            f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}",  # noqa: E501
    +1682            json={"langFilter": str(language)},
    +1683            auth=access_token,
    +1684        )
    +1685        assert isinstance(resp, dict)
    +1686        return resp
    +1687
    +1688    async def fetch_clan_fireteam(
    +1689        self, access_token: str, fireteam_id: int, group_id: int
    +1690    ) -> typedefs.JSONObject:
    +1691        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1692        resp = await self._request(
    +1693            RequestMethod.GET,
    +1694            f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}",
     1695            auth=access_token,
     1696        )
     1697        assert isinstance(resp, dict)
     1698        return resp
     1699
    -1700    async def fetch_clan_fireteam(
    -1701        self, access_token: str, fireteam_id: int, group_id: int
    -1702    ) -> typedefs.JSONObject:
    -1703        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1704        resp = await self._request(
    -1705            RequestMethod.GET,
    -1706            f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}",
    -1707            auth=access_token,
    -1708        )
    -1709        assert isinstance(resp, dict)
    -1710        return resp
    -1711
    -1712    async def fetch_my_clan_fireteams(
    -1713        self,
    -1714        access_token: str,
    -1715        group_id: int,
    -1716        *,
    -1717        include_closed: bool = True,
    -1718        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    -1719        language: typing.Union[fireteams.FireteamLanguage, str],
    -1720        filtered: bool = True,
    -1721        page: int = 0,
    -1722    ) -> typedefs.JSONObject:
    -1723        payload = {"groupFilter": filtered, "langFilter": str(language)}
    -1724        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1725        resp = await self._request(
    -1726            RequestMethod.GET,
    -1727            f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}",
    -1728            json=payload,
    +1700    async def fetch_my_clan_fireteams(
    +1701        self,
    +1702        access_token: str,
    +1703        group_id: int,
    +1704        *,
    +1705        include_closed: bool = True,
    +1706        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    +1707        language: typing.Union[fireteams.FireteamLanguage, str],
    +1708        filtered: bool = True,
    +1709        page: int = 0,
    +1710    ) -> typedefs.JSONObject:
    +1711        payload = {"groupFilter": filtered, "langFilter": str(language)}
    +1712        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1713        resp = await self._request(
    +1714            RequestMethod.GET,
    +1715            f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}",
    +1716            json=payload,
    +1717            auth=access_token,
    +1718        )
    +1719        assert isinstance(resp, dict)
    +1720        return resp
    +1721
    +1722    async def fetch_private_clan_fireteams(
    +1723        self, access_token: str, group_id: int, /
    +1724    ) -> int:
    +1725        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1726        resp = await self._request(
    +1727            RequestMethod.GET,
    +1728            f"Fireteam/Clan/{group_id}/ActiveCount",
     1729            auth=access_token,
     1730        )
    -1731        assert isinstance(resp, dict)
    +1731        assert isinstance(resp, int)
     1732        return resp
     1733
    -1734    async def fetch_private_clan_fireteams(
    -1735        self, access_token: str, group_id: int, /
    -1736    ) -> int:
    -1737        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1738        resp = await self._request(
    -1739            RequestMethod.GET,
    -1740            f"Fireteam/Clan/{group_id}/ActiveCount",
    -1741            auth=access_token,
    -1742        )
    -1743        assert isinstance(resp, int)
    -1744        return resp
    -1745
    -1746    async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject:
    -1747        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1748        resp = await self._request(
    -1749            RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}"
    +1734    async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject:
    +1735        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1736        resp = await self._request(
    +1737            RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}"
    +1738        )
    +1739        assert isinstance(resp, dict)
    +1740        return resp
    +1741
    +1742    async def search_entities(
    +1743        self, name: str, entity_type: str, *, page: int = 0
    +1744    ) -> typedefs.JSONObject:
    +1745        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1746        resp = await self._request(
    +1747            RequestMethod.GET,
    +1748            f"Destiny2/Armory/Search/{entity_type}/{name}/",
    +1749            json={"page": page},
     1750        )
     1751        assert isinstance(resp, dict)
     1752        return resp
     1753
    -1754    async def search_entities(
    -1755        self, name: str, entity_type: str, *, page: int = 0
    -1756    ) -> typedefs.JSONObject:
    -1757        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1758        resp = await self._request(
    -1759            RequestMethod.GET,
    -1760            f"Destiny2/Armory/Search/{entity_type}/{name}/",
    -1761            json={"page": page},
    -1762        )
    -1763        assert isinstance(resp, dict)
    -1764        return resp
    -1765
    -1766    async def fetch_unique_weapon_history(
    -1767        self,
    -1768        membership_id: int,
    -1769        character_id: int,
    -1770        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1771    ) -> typedefs.JSONObject:
    -1772        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1773        resp = await self._request(
    -1774            RequestMethod.GET,
    -1775            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/",
    -1776        )
    -1777        assert isinstance(resp, dict)
    -1778        return resp
    -1779
    -1780    async def fetch_item(
    -1781        self,
    -1782        member_id: int,
    -1783        item_id: int,
    -1784        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1785        components: list[enums.ComponentType],
    -1786    ) -> typedefs.JSONObject:
    -1787        collector = _collect_components(components)
    -1788        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1789        resp = await self._request(
    -1790            RequestMethod.GET,
    -1791            f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}",
    -1792        )
    -1793        assert isinstance(resp, dict)
    -1794        return resp
    -1795
    -1796    async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject:
    -1797        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1798        resp = await self._request(
    -1799            RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/"
    -1800        )
    -1801        assert isinstance(resp, dict)
    -1802        return resp
    -1803
    -1804    async def fetch_available_locales(self) -> typedefs.JSONObject:
    -1805        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1806        resp = await self._request(
    -1807            RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/"
    -1808        )
    +1754    async def fetch_unique_weapon_history(
    +1755        self,
    +1756        membership_id: int,
    +1757        character_id: int,
    +1758        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1759    ) -> typedefs.JSONObject:
    +1760        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1761        resp = await self._request(
    +1762            RequestMethod.GET,
    +1763            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/",
    +1764        )
    +1765        assert isinstance(resp, dict)
    +1766        return resp
    +1767
    +1768    async def fetch_item(
    +1769        self,
    +1770        member_id: int,
    +1771        item_id: int,
    +1772        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1773        components: list[enums.ComponentType],
    +1774    ) -> typedefs.JSONObject:
    +1775        collector = _collect_components(components)
    +1776        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1777        resp = await self._request(
    +1778            RequestMethod.GET,
    +1779            f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}",
    +1780        )
    +1781        assert isinstance(resp, dict)
    +1782        return resp
    +1783
    +1784    async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject:
    +1785        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1786        resp = await self._request(
    +1787            RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/"
    +1788        )
    +1789        assert isinstance(resp, dict)
    +1790        return resp
    +1791
    +1792    async def fetch_available_locales(self) -> typedefs.JSONObject:
    +1793        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1794        resp = await self._request(
    +1795            RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/"
    +1796        )
    +1797        assert isinstance(resp, dict)
    +1798        return resp
    +1799
    +1800    async def fetch_common_settings(self) -> typedefs.JSONObject:
    +1801        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1802        resp = await self._request(RequestMethod.GET, "Settings")
    +1803        assert isinstance(resp, dict)
    +1804        return resp
    +1805
    +1806    async def fetch_user_systems_overrides(self) -> typedefs.JSONObject:
    +1807        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1808        resp = await self._request(RequestMethod.GET, "UserSystemOverrides")
     1809        assert isinstance(resp, dict)
     1810        return resp
     1811
    -1812    async def fetch_common_settings(self) -> typedefs.JSONObject:
    -1813        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1814        resp = await self._request(RequestMethod.GET, "Settings")
    -1815        assert isinstance(resp, dict)
    -1816        return resp
    -1817
    -1818    async def fetch_user_systems_overrides(self) -> typedefs.JSONObject:
    -1819        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1820        resp = await self._request(RequestMethod.GET, "UserSystemOverrides")
    -1821        assert isinstance(resp, dict)
    -1822        return resp
    -1823
    -1824    async def fetch_global_alerts(
    -1825        self, *, include_streaming: bool = False
    -1826    ) -> typedefs.JSONArray:
    -1827        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1828        resp = await self._request(
    -1829            RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}"
    -1830        )
    -1831        assert isinstance(resp, list)
    -1832        return resp
    +1812    async def fetch_global_alerts(
    +1813        self, *, include_streaming: bool = False
    +1814    ) -> typedefs.JSONArray:
    +1815        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1816        resp = await self._request(
    +1817            RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}"
    +1818        )
    +1819        assert isinstance(resp, list)
    +1820        return resp
    +1821
    +1822    async def awainitialize_request(
    +1823        self,
    +1824        access_token: str,
    +1825        type: typing.Literal[0, 1],
    +1826        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1827        /,
    +1828        *,
    +1829        affected_item_id: typing.Optional[int] = None,
    +1830        character_id: typing.Optional[int] = None,
    +1831    ) -> typedefs.JSONObject:
    +1832        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
     1833
    -1834    async def awainitialize_request(
    -1835        self,
    -1836        access_token: str,
    -1837        type: typing.Literal[0, 1],
    -1838        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1839        /,
    -1840        *,
    -1841        affected_item_id: typing.Optional[int] = None,
    -1842        character_id: typing.Optional[int] = None,
    -1843    ) -> typedefs.JSONObject:
    -1844        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1845
    -1846        body = {"type": type, "membershipType": int(membership_type)}
    +1834        body = {"type": type, "membershipType": int(membership_type)}
    +1835
    +1836        if affected_item_id is not None:
    +1837            body["affectedItemId"] = affected_item_id
    +1838
    +1839        if character_id is not None:
    +1840            body["characterId"] = character_id
    +1841
    +1842        resp = await self._request(
    +1843            RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token
    +1844        )
    +1845        assert isinstance(resp, dict)
    +1846        return resp
     1847
    -1848        if affected_item_id is not None:
    -1849            body["affectedItemId"] = affected_item_id
    -1850
    -1851        if character_id is not None:
    -1852            body["characterId"] = character_id
    -1853
    -1854        resp = await self._request(
    -1855            RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token
    +1848    async def awaget_action_token(
    +1849        self, access_token: str, correlation_id: str, /
    +1850    ) -> typedefs.JSONObject:
    +1851        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1852        resp = await self._request(
    +1853            RequestMethod.POST,
    +1854            f"Destiny2/Awa/GetActionToken/{correlation_id}",
    +1855            auth=access_token,
     1856        )
     1857        assert isinstance(resp, dict)
     1858        return resp
     1859
    -1860    async def awaget_action_token(
    -1861        self, access_token: str, correlation_id: str, /
    -1862    ) -> typedefs.JSONObject:
    -1863        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1864        resp = await self._request(
    -1865            RequestMethod.POST,
    -1866            f"Destiny2/Awa/GetActionToken/{correlation_id}",
    -1867            auth=access_token,
    -1868        )
    -1869        assert isinstance(resp, dict)
    -1870        return resp
    -1871
    -1872    async def awa_provide_authorization_result(
    -1873        self,
    -1874        access_token: str,
    -1875        selection: int,
    -1876        correlation_id: str,
    -1877        nonce: collections.MutableSequence[typing.Union[str, bytes]],
    -1878    ) -> int:
    -1879        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1880
    -1881        body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce}
    -1882
    -1883        resp = await self._request(
    -1884            RequestMethod.POST,
    -1885            "Destiny2/Awa/AwaProvideAuthorizationResult",
    -1886            json=body,
    -1887            auth=access_token,
    -1888        )
    -1889        assert isinstance(resp, int)
    -1890        return resp
    -1891
    -1892    async def fetch_vendors(
    -1893        self,
    -1894        access_token: str,
    -1895        character_id: int,
    -1896        membership_id: int,
    -1897        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1898        /,
    -1899        components: list[enums.ComponentType],
    -1900        filter: typing.Optional[int] = None,
    -1901    ) -> typedefs.JSONObject:
    -1902        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1903        components_ = _collect_components(components)
    -1904        route = (
    -1905            f"Destiny2/{int(membership_type)}/Profile/{membership_id}"
    -1906            f"/Character/{character_id}/Vendors/?components={components_}"
    -1907        )
    -1908
    -1909        if filter is not None:
    -1910            route = route + f"&filter={filter}"
    -1911
    -1912        resp = await self._request(
    -1913            RequestMethod.GET,
    -1914            route,
    -1915            auth=access_token,
    -1916        )
    -1917        assert isinstance(resp, dict)
    -1918        return resp
    -1919
    -1920    async def fetch_vendor(
    -1921        self,
    -1922        access_token: str,
    -1923        character_id: int,
    -1924        membership_id: int,
    -1925        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1926        vendor_hash: int,
    -1927        /,
    -1928        components: list[enums.ComponentType],
    -1929    ) -> typedefs.JSONObject:
    -1930        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1931        components_ = _collect_components(components)
    -1932        resp = await self._request(
    -1933            RequestMethod.GET,
    -1934            (
    -1935                f"Platform/Destiny2/{int(membership_type)}/Profile/{membership_id}"
    -1936                f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}"
    -1937            ),
    -1938            auth=access_token,
    -1939        )
    -1940        assert isinstance(resp, dict)
    -1941        return resp
    -1942
    -1943    async def fetch_application_api_usage(
    -1944        self,
    -1945        access_token: str,
    -1946        application_id: int,
    -1947        /,
    -1948        *,
    -1949        start: typing.Optional[datetime.datetime] = None,
    -1950        end: typing.Optional[datetime.datetime] = None,
    -1951    ) -> typedefs.JSONObject:
    -1952
    -1953        end_date, start_date = time.parse_date_range(end, start)
    -1954        resp = await self._request(
    -1955            RequestMethod.GET,
    -1956            f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}",
    -1957            auth=access_token,
    -1958        )
    -1959        assert isinstance(resp, dict)
    -1960        return resp
    -1961
    -1962    async def fetch_bungie_applications(self) -> typedefs.JSONArray:
    -1963        resp = await self._request(RequestMethod.GET, "App/FirstParty")
    -1964        assert isinstance(resp, list)
    -1965        return resp
    -1966
    -1967    async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject:
    -1968        resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/")
    -1969        assert isinstance(resp, dict)
    -1970        return resp
    -1971
    -1972    async def fetch_content_by_id(
    -1973        self, id: int, locale: str, /, *, head: bool = False
    -1974    ) -> typedefs.JSONObject:
    -1975        resp = await self._request(
    -1976            RequestMethod.GET,
    -1977            f"Content/GetContentById/{id}/{locale}/",
    -1978            json={"head": head},
    -1979        )
    -1980        assert isinstance(resp, dict)
    -1981        return resp
    -1982
    -1983    async def fetch_content_by_tag_and_type(
    -1984        self, locale: str, tag: str, type: str, *, head: bool = False
    -1985    ) -> typedefs.JSONObject:
    -1986        resp = await self._request(
    -1987            RequestMethod.GET,
    -1988            f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/",
    -1989            json={"head": head},
    -1990        )
    -1991        assert isinstance(resp, dict)
    -1992        return resp
    +1860    async def awa_provide_authorization_result(
    +1861        self,
    +1862        access_token: str,
    +1863        selection: int,
    +1864        correlation_id: str,
    +1865        nonce: collections.MutableSequence[typing.Union[str, bytes]],
    +1866    ) -> int:
    +1867        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1868
    +1869        body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce}
    +1870
    +1871        resp = await self._request(
    +1872            RequestMethod.POST,
    +1873            "Destiny2/Awa/AwaProvideAuthorizationResult",
    +1874            json=body,
    +1875            auth=access_token,
    +1876        )
    +1877        assert isinstance(resp, int)
    +1878        return resp
    +1879
    +1880    async def fetch_vendors(
    +1881        self,
    +1882        access_token: str,
    +1883        character_id: int,
    +1884        membership_id: int,
    +1885        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1886        /,
    +1887        components: list[enums.ComponentType],
    +1888        filter: typing.Optional[int] = None,
    +1889    ) -> typedefs.JSONObject:
    +1890        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1891        components_ = _collect_components(components)
    +1892        route = (
    +1893            f"Destiny2/{int(membership_type)}/Profile/{membership_id}"
    +1894            f"/Character/{character_id}/Vendors/?components={components_}"
    +1895        )
    +1896
    +1897        if filter is not None:
    +1898            route = route + f"&filter={filter}"
    +1899
    +1900        resp = await self._request(
    +1901            RequestMethod.GET,
    +1902            route,
    +1903            auth=access_token,
    +1904        )
    +1905        assert isinstance(resp, dict)
    +1906        return resp
    +1907
    +1908    async def fetch_vendor(
    +1909        self,
    +1910        access_token: str,
    +1911        character_id: int,
    +1912        membership_id: int,
    +1913        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1914        vendor_hash: int,
    +1915        /,
    +1916        components: list[enums.ComponentType],
    +1917    ) -> typedefs.JSONObject:
    +1918        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1919        components_ = _collect_components(components)
    +1920        resp = await self._request(
    +1921            RequestMethod.GET,
    +1922            (
    +1923                f"Platform/Destiny2/{int(membership_type)}/Profile/{membership_id}"
    +1924                f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}"
    +1925            ),
    +1926            auth=access_token,
    +1927        )
    +1928        assert isinstance(resp, dict)
    +1929        return resp
    +1930
    +1931    async def fetch_application_api_usage(
    +1932        self,
    +1933        access_token: str,
    +1934        application_id: int,
    +1935        /,
    +1936        *,
    +1937        start: typing.Optional[datetime.datetime] = None,
    +1938        end: typing.Optional[datetime.datetime] = None,
    +1939    ) -> typedefs.JSONObject:
    +1940
    +1941        end_date, start_date = time.parse_date_range(end, start)
    +1942        resp = await self._request(
    +1943            RequestMethod.GET,
    +1944            f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}",
    +1945            auth=access_token,
    +1946        )
    +1947        assert isinstance(resp, dict)
    +1948        return resp
    +1949
    +1950    async def fetch_bungie_applications(self) -> typedefs.JSONArray:
    +1951        resp = await self._request(RequestMethod.GET, "App/FirstParty")
    +1952        assert isinstance(resp, list)
    +1953        return resp
    +1954
    +1955    async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject:
    +1956        resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/")
    +1957        assert isinstance(resp, dict)
    +1958        return resp
    +1959
    +1960    async def fetch_content_by_id(
    +1961        self, id: int, locale: str, /, *, head: bool = False
    +1962    ) -> typedefs.JSONObject:
    +1963        resp = await self._request(
    +1964            RequestMethod.GET,
    +1965            f"Content/GetContentById/{id}/{locale}/",
    +1966            json={"head": head},
    +1967        )
    +1968        assert isinstance(resp, dict)
    +1969        return resp
    +1970
    +1971    async def fetch_content_by_tag_and_type(
    +1972        self, locale: str, tag: str, type: str, *, head: bool = False
    +1973    ) -> typedefs.JSONObject:
    +1974        resp = await self._request(
    +1975            RequestMethod.GET,
    +1976            f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/",
    +1977            json={"head": head},
    +1978        )
    +1979        assert isinstance(resp, dict)
    +1980        return resp
    +1981
    +1982    async def search_content_with_text(
    +1983        self,
    +1984        locale: str,
    +1985        /,
    +1986        content_type: str,
    +1987        search_text: str,
    +1988        tag: str,
    +1989        *,
    +1990        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +1991        source: undefined.UndefinedOr[str] = undefined.Undefined,
    +1992    ) -> typedefs.JSONObject:
     1993
    -1994    async def search_content_with_text(
    -1995        self,
    -1996        locale: str,
    -1997        /,
    -1998        content_type: str,
    -1999        search_text: str,
    -2000        tag: str,
    -2001        *,
    -2002        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2003        source: undefined.UndefinedOr[str] = undefined.Undefined,
    -2004    ) -> typedefs.JSONObject:
    -2005
    -2006        body: typedefs.JSONObject = {}
    -2007
    -2008        body["ctype"] = content_type
    -2009        body["searchtext"] = search_text
    -2010        body["tag"] = tag
    -2011
    -2012        if page is not undefined.Undefined:
    -2013            body["currentpage"] = page
    -2014        else:
    -2015            body["currentpage"] = 1
    -2016
    -2017        if source is not undefined.Undefined:
    -2018            body["source"] = source
    -2019        else:
    -2020            source = ""
    -2021        resp = await self._request(
    -2022            RequestMethod.GET, f"Content/Search/{locale}/", json=body
    -2023        )
    -2024        assert isinstance(resp, dict)
    -2025        return resp
    -2026
    -2027    async def search_content_by_tag_and_type(
    -2028        self,
    -2029        locale: str,
    -2030        tag: str,
    -2031        type: str,
    -2032        *,
    -2033        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2034    ) -> typedefs.JSONObject:
    -2035        body: typedefs.JSONObject = {}
    -2036        body["currentpage"] = 1 if page is undefined.Undefined else page
    -2037        resp = await self._request(
    -2038            RequestMethod.GET,
    -2039            f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/",
    -2040            json=body,
    -2041        )
    -2042        assert isinstance(resp, dict)
    -2043        return resp
    -2044
    -2045    async def search_help_articles(
    -2046        self, text: str, size: str, /
    -2047    ) -> typedefs.JSONObject:
    -2048        resp = await self._request(
    -2049            RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/"
    -2050        )
    -2051        assert isinstance(resp, dict)
    -2052        return resp
    +1994        body: typedefs.JSONObject = {}
    +1995
    +1996        body["ctype"] = content_type
    +1997        body["searchtext"] = search_text
    +1998        body["tag"] = tag
    +1999
    +2000        if page is not undefined.Undefined:
    +2001            body["currentpage"] = page
    +2002        else:
    +2003            body["currentpage"] = 1
    +2004
    +2005        if source is not undefined.Undefined:
    +2006            body["source"] = source
    +2007        else:
    +2008            source = ""
    +2009        resp = await self._request(
    +2010            RequestMethod.GET, f"Content/Search/{locale}/", json=body
    +2011        )
    +2012        assert isinstance(resp, dict)
    +2013        return resp
    +2014
    +2015    async def search_content_by_tag_and_type(
    +2016        self,
    +2017        locale: str,
    +2018        tag: str,
    +2019        type: str,
    +2020        *,
    +2021        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +2022    ) -> typedefs.JSONObject:
    +2023        body: typedefs.JSONObject = {}
    +2024        body["currentpage"] = 1 if page is undefined.Undefined else page
    +2025        resp = await self._request(
    +2026            RequestMethod.GET,
    +2027            f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/",
    +2028            json=body,
    +2029        )
    +2030        assert isinstance(resp, dict)
    +2031        return resp
    +2032
    +2033    async def search_help_articles(
    +2034        self, text: str, size: str, /
    +2035    ) -> typedefs.JSONObject:
    +2036        resp = await self._request(
    +2037            RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/"
    +2038        )
    +2039        assert isinstance(resp, dict)
    +2040        return resp
    +2041
    +2042    async def fetch_topics_page(
    +2043        self,
    +2044        category_filter: int,
    +2045        group: int,
    +2046        date_filter: int,
    +2047        sort: typing.Union[str, bytes],
    +2048        *,
    +2049        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +2050        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    +2051        tag_filter: undefined.UndefinedOr[str] = undefined.Undefined,
    +2052    ) -> typedefs.JSONObject:
     2053
    -2054    async def fetch_topics_page(
    -2055        self,
    -2056        category_filter: int,
    -2057        group: int,
    -2058        date_filter: int,
    -2059        sort: typing.Union[str, bytes],
    -2060        *,
    -2061        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2062        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    -2063        tag_filter: undefined.UndefinedOr[str] = undefined.Undefined,
    -2064    ) -> typedefs.JSONObject:
    -2065
    -2066        body: typedefs.JSONObject = {}
    -2067        if locales is not undefined.Undefined:
    -2068            body["locales"] = ",".join(str(locales))
    -2069        else:
    -2070            body["locales"] = ",".join([])
    -2071
    -2072        if tag_filter is not undefined.Undefined:
    -2073            body["tagstring"] = tag_filter
    -2074        else:
    -2075            body["tagstring"] = ""
    -2076
    -2077        page = 0 if page is not undefined.Undefined else page
    -2078
    -2079        resp = await self._request(
    -2080            RequestMethod.GET,
    -2081            f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/",
    -2082            json=body,
    -2083        )
    -2084        assert isinstance(resp, dict)
    -2085        return resp
    -2086
    -2087    async def fetch_core_topics_page(
    -2088        self,
    -2089        category_filter: int,
    -2090        date_filter: int,
    -2091        sort: typing.Union[str, bytes],
    -2092        *,
    -2093        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2094        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    -2095    ) -> typedefs.JSONObject:
    -2096        body: typedefs.JSONObject = {}
    -2097
    -2098        if locales is not undefined.Undefined:
    -2099            body["locales"] = ",".join(str(locales))
    -2100        else:
    -2101            body["locales"] = ",".join([])
    -2102
    -2103        resp = await self._request(
    -2104            RequestMethod.GET,
    -2105            f"Forum/GetCoreTopicsPaged/{0 if page is undefined.Undefined else page}"
    -2106            f"/{sort!s}/{date_filter}/{category_filter}/",
    -2107            json=body,
    -2108        )
    -2109        assert isinstance(resp, dict)
    -2110        return resp
    -2111
    -2112    async def fetch_posts_threaded_page(
    -2113        self,
    -2114        parent_post: bool,
    -2115        page: int,
    -2116        page_size: int,
    -2117        parent_post_id: int,
    -2118        reply_size: int,
    -2119        root_thread_mode: bool,
    -2120        sort_mode: int,
    -2121        show_banned: typing.Optional[str] = None,
    -2122    ) -> typedefs.JSONObject:
    -2123        resp = await self._request(
    -2124            RequestMethod.GET,
    -2125            f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/"
    -2126            f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/",
    -2127            json={"showbanned": show_banned},
    -2128        )
    -2129        assert isinstance(resp, dict)
    -2130        return resp
    -2131
    -2132    async def fetch_posts_threaded_page_from_child(
    -2133        self,
    -2134        child_id: bool,
    -2135        page: int,
    -2136        page_size: int,
    -2137        reply_size: int,
    -2138        root_thread_mode: bool,
    -2139        sort_mode: int,
    -2140        show_banned: typing.Optional[str] = None,
    +2054        body: typedefs.JSONObject = {}
    +2055        if locales is not undefined.Undefined:
    +2056            body["locales"] = ",".join(str(locales))
    +2057        else:
    +2058            body["locales"] = ",".join([])
    +2059
    +2060        if tag_filter is not undefined.Undefined:
    +2061            body["tagstring"] = tag_filter
    +2062        else:
    +2063            body["tagstring"] = ""
    +2064
    +2065        page = 0 if page is not undefined.Undefined else page
    +2066
    +2067        resp = await self._request(
    +2068            RequestMethod.GET,
    +2069            f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/",
    +2070            json=body,
    +2071        )
    +2072        assert isinstance(resp, dict)
    +2073        return resp
    +2074
    +2075    async def fetch_core_topics_page(
    +2076        self,
    +2077        category_filter: int,
    +2078        date_filter: int,
    +2079        sort: typing.Union[str, bytes],
    +2080        *,
    +2081        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +2082        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    +2083    ) -> typedefs.JSONObject:
    +2084        body: typedefs.JSONObject = {}
    +2085
    +2086        if locales is not undefined.Undefined:
    +2087            body["locales"] = ",".join(str(locales))
    +2088        else:
    +2089            body["locales"] = ",".join([])
    +2090
    +2091        resp = await self._request(
    +2092            RequestMethod.GET,
    +2093            f"Forum/GetCoreTopicsPaged/{0 if page is undefined.Undefined else page}"
    +2094            f"/{sort!s}/{date_filter}/{category_filter}/",
    +2095            json=body,
    +2096        )
    +2097        assert isinstance(resp, dict)
    +2098        return resp
    +2099
    +2100    async def fetch_posts_threaded_page(
    +2101        self,
    +2102        parent_post: bool,
    +2103        page: int,
    +2104        page_size: int,
    +2105        parent_post_id: int,
    +2106        reply_size: int,
    +2107        root_thread_mode: bool,
    +2108        sort_mode: int,
    +2109        show_banned: typing.Optional[str] = None,
    +2110    ) -> typedefs.JSONObject:
    +2111        resp = await self._request(
    +2112            RequestMethod.GET,
    +2113            f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/"
    +2114            f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/",
    +2115            json={"showbanned": show_banned},
    +2116        )
    +2117        assert isinstance(resp, dict)
    +2118        return resp
    +2119
    +2120    async def fetch_posts_threaded_page_from_child(
    +2121        self,
    +2122        child_id: bool,
    +2123        page: int,
    +2124        page_size: int,
    +2125        reply_size: int,
    +2126        root_thread_mode: bool,
    +2127        sort_mode: int,
    +2128        show_banned: typing.Optional[str] = None,
    +2129    ) -> typedefs.JSONObject:
    +2130        resp = await self._request(
    +2131            RequestMethod.GET,
    +2132            f"Forum/GetPostsThreadedPagedFromChild/{child_id}/"
    +2133            f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/",
    +2134            json={"showbanned": show_banned},
    +2135        )
    +2136        assert isinstance(resp, dict)
    +2137        return resp
    +2138
    +2139    async def fetch_post_and_parent(
    +2140        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
     2141    ) -> typedefs.JSONObject:
     2142        resp = await self._request(
     2143            RequestMethod.GET,
    -2144            f"Forum/GetPostsThreadedPagedFromChild/{child_id}/"
    -2145            f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/",
    -2146            json={"showbanned": show_banned},
    -2147        )
    -2148        assert isinstance(resp, dict)
    -2149        return resp
    -2150
    -2151    async def fetch_post_and_parent(
    -2152        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
    -2153    ) -> typedefs.JSONObject:
    -2154        resp = await self._request(
    -2155            RequestMethod.GET,
    -2156            f"Forum/GetPostAndParent/{child_id}/",
    -2157            json={"showbanned": show_banned},
    -2158        )
    -2159        assert isinstance(resp, dict)
    -2160        return resp
    -2161
    -2162    async def fetch_posts_and_parent_awaiting(
    -2163        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
    -2164    ) -> typedefs.JSONObject:
    -2165        resp = await self._request(
    -2166            RequestMethod.GET,
    -2167            f"Forum/GetPostAndParentAwaitingApproval/{child_id}/",
    -2168            json={"showbanned": show_banned},
    -2169        )
    -2170        assert isinstance(resp, dict)
    -2171        return resp
    -2172
    -2173    async def fetch_topic_for_content(self, content_id: int, /) -> int:
    -2174        resp = await self._request(
    -2175            RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/"
    -2176        )
    -2177        assert isinstance(resp, int)
    -2178        return resp
    -2179
    -2180    async def fetch_forum_tag_suggestions(
    -2181        self, partial_tag: str, /
    -2182    ) -> typedefs.JSONObject:
    -2183        resp = await self._request(
    -2184            RequestMethod.GET,
    -2185            "Forum/GetForumTagSuggestions/",
    -2186            json={"partialtag": partial_tag},
    -2187        )
    -2188        assert isinstance(resp, dict)
    -2189        return resp
    -2190
    -2191    async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject:
    -2192        resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/")
    -2193        assert isinstance(resp, dict)
    -2194        return resp
    -2195
    -2196    async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray:
    -2197        resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/")
    -2198        assert isinstance(resp, list)
    -2199        return resp
    -2200
    -2201    async def fetch_recommended_groups(
    -2202        self,
    -2203        accecss_token: str,
    -2204        /,
    -2205        *,
    -2206        date_range: int = 0,
    -2207        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    -2208    ) -> typedefs.JSONArray:
    -2209        resp = await self._request(
    -2210            RequestMethod.POST,
    -2211            f"GroupV2/Recommended/{int(group_type)}/{date_range}/",
    -2212            auth=accecss_token,
    -2213        )
    -2214        assert isinstance(resp, list)
    -2215        return resp
    -2216
    -2217    async def fetch_available_avatars(self) -> collections.Mapping[str, int]:
    -2218        resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/")
    -2219        assert isinstance(resp, dict)
    -2220        return resp
    -2221
    -2222    async def fetch_user_clan_invite_setting(
    -2223        self,
    -2224        access_token: str,
    -2225        /,
    -2226        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2227    ) -> bool:
    -2228        resp = await self._request(
    -2229            RequestMethod.GET,
    -2230            f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/",
    -2231            auth=access_token,
    -2232        )
    -2233        assert isinstance(resp, bool)
    -2234        return resp
    -2235
    -2236    async def fetch_banned_group_members(
    -2237        self, access_token: str, group_id: int, /, *, page: int = 1
    -2238    ) -> typedefs.JSONObject:
    -2239        resp = await self._request(
    -2240            RequestMethod.GET,
    -2241            f"GroupV2/{group_id}/Banned/?currentpage={page}",
    -2242            auth=access_token,
    -2243        )
    -2244        assert isinstance(resp, dict)
    -2245        return resp
    -2246
    -2247    async def fetch_pending_group_memberships(
    -2248        self, access_token: str, group_id: int, /, *, current_page: int = 1
    -2249    ) -> typedefs.JSONObject:
    -2250        resp = await self._request(
    -2251            RequestMethod.GET,
    -2252            f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}",
    -2253            auth=access_token,
    -2254        )
    -2255        assert isinstance(resp, dict)
    -2256        return resp
    -2257
    -2258    async def fetch_invited_group_memberships(
    -2259        self, access_token: str, group_id: int, /, *, current_page: int = 1
    -2260    ) -> typedefs.JSONObject:
    -2261        resp = await self._request(
    -2262            RequestMethod.GET,
    -2263            f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}",
    -2264            auth=access_token,
    -2265        )
    -2266        assert isinstance(resp, dict)
    -2267        return resp
    -2268
    -2269    async def invite_member_to_group(
    -2270        self,
    -2271        access_token: str,
    -2272        /,
    -2273        group_id: int,
    -2274        membership_id: int,
    -2275        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2276        *,
    -2277        message: undefined.UndefinedOr[str] = undefined.Undefined,
    -2278    ) -> typedefs.JSONObject:
    -2279        resp = await self._request(
    -2280            RequestMethod.POST,
    -2281            f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/",
    -2282            auth=access_token,
    -2283            json={"message": str(message)},
    -2284        )
    -2285        assert isinstance(resp, dict)
    -2286        return resp
    -2287
    -2288    async def cancel_group_member_invite(
    -2289        self,
    -2290        access_token: str,
    -2291        /,
    -2292        group_id: int,
    -2293        membership_id: int,
    -2294        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2295    ) -> typedefs.JSONObject:
    -2296        resp = await self._request(
    -2297            RequestMethod.POST,
    -2298            f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/",
    -2299            auth=access_token,
    -2300        )
    -2301        assert isinstance(resp, dict)
    -2302        return resp
    -2303
    -2304    async def fetch_historical_definition(self) -> typedefs.JSONObject:
    -2305        resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/")
    -2306        assert isinstance(resp, dict)
    -2307        return resp
    -2308
    -2309    async def fetch_historical_stats(
    -2310        self,
    -2311        character_id: int,
    -2312        membership_id: int,
    -2313        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2314        day_start: datetime.datetime,
    -2315        day_end: datetime.datetime,
    -2316        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    -2317        modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]],
    -2318        *,
    -2319        period_type: enums.PeriodType = enums.PeriodType.ALL_TIME,
    -2320    ) -> typedefs.JSONObject:
    -2321
    -2322        end, start = time.parse_date_range(day_end, day_start)
    -2323        resp = await self._request(
    -2324            RequestMethod.GET,
    -2325            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/",
    -2326            json={
    -2327                "dayend": end,
    -2328                "daystart": start,
    -2329                "groups": [str(int(group)) for group in groups],
    -2330                "modes": [str(int(mode)) for mode in modes],
    -2331                "periodType": int(period_type),
    -2332            },
    -2333        )
    -2334        assert isinstance(resp, dict)
    -2335        return resp
    -2336
    -2337    async def fetch_historical_stats_for_account(
    -2338        self,
    -2339        membership_id: int,
    -2340        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2341        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    -2342    ) -> typedefs.JSONObject:
    -2343        resp = await self._request(
    -2344            RequestMethod.GET,
    -2345            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/",
    -2346            json={"groups": [str(int(group)) for group in groups]},
    -2347        )
    -2348        assert isinstance(resp, dict)
    -2349        return resp
    -2350
    -2351    async def fetch_aggregated_activity_stats(
    -2352        self,
    -2353        character_id: int,
    -2354        membership_id: int,
    -2355        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2356        /,
    -2357    ) -> typedefs.JSONObject:
    -2358        resp = await self._request(
    -2359            RequestMethod.GET,
    -2360            f"Destiny2/{int(membership_type)}/Account/{membership_id}/"
    -2361            f"Character/{character_id}/Stats/AggregateActivityStats/",
    -2362        )
    -2363        assert isinstance(resp, dict)
    -2364        return resp
    +2144            f"Forum/GetPostAndParent/{child_id}/",
    +2145            json={"showbanned": show_banned},
    +2146        )
    +2147        assert isinstance(resp, dict)
    +2148        return resp
    +2149
    +2150    async def fetch_posts_and_parent_awaiting(
    +2151        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
    +2152    ) -> typedefs.JSONObject:
    +2153        resp = await self._request(
    +2154            RequestMethod.GET,
    +2155            f"Forum/GetPostAndParentAwaitingApproval/{child_id}/",
    +2156            json={"showbanned": show_banned},
    +2157        )
    +2158        assert isinstance(resp, dict)
    +2159        return resp
    +2160
    +2161    async def fetch_topic_for_content(self, content_id: int, /) -> int:
    +2162        resp = await self._request(
    +2163            RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/"
    +2164        )
    +2165        assert isinstance(resp, int)
    +2166        return resp
    +2167
    +2168    async def fetch_forum_tag_suggestions(
    +2169        self, partial_tag: str, /
    +2170    ) -> typedefs.JSONObject:
    +2171        resp = await self._request(
    +2172            RequestMethod.GET,
    +2173            "Forum/GetForumTagSuggestions/",
    +2174            json={"partialtag": partial_tag},
    +2175        )
    +2176        assert isinstance(resp, dict)
    +2177        return resp
    +2178
    +2179    async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject:
    +2180        resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/")
    +2181        assert isinstance(resp, dict)
    +2182        return resp
    +2183
    +2184    async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray:
    +2185        resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/")
    +2186        assert isinstance(resp, list)
    +2187        return resp
    +2188
    +2189    async def fetch_recommended_groups(
    +2190        self,
    +2191        accecss_token: str,
    +2192        /,
    +2193        *,
    +2194        date_range: int = 0,
    +2195        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    +2196    ) -> typedefs.JSONArray:
    +2197        resp = await self._request(
    +2198            RequestMethod.POST,
    +2199            f"GroupV2/Recommended/{int(group_type)}/{date_range}/",
    +2200            auth=accecss_token,
    +2201        )
    +2202        assert isinstance(resp, list)
    +2203        return resp
    +2204
    +2205    async def fetch_available_avatars(self) -> collections.Mapping[str, int]:
    +2206        resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/")
    +2207        assert isinstance(resp, dict)
    +2208        return resp
    +2209
    +2210    async def fetch_user_clan_invite_setting(
    +2211        self,
    +2212        access_token: str,
    +2213        /,
    +2214        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2215    ) -> bool:
    +2216        resp = await self._request(
    +2217            RequestMethod.GET,
    +2218            f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/",
    +2219            auth=access_token,
    +2220        )
    +2221        assert isinstance(resp, bool)
    +2222        return resp
    +2223
    +2224    async def fetch_banned_group_members(
    +2225        self, access_token: str, group_id: int, /, *, page: int = 1
    +2226    ) -> typedefs.JSONObject:
    +2227        resp = await self._request(
    +2228            RequestMethod.GET,
    +2229            f"GroupV2/{group_id}/Banned/?currentpage={page}",
    +2230            auth=access_token,
    +2231        )
    +2232        assert isinstance(resp, dict)
    +2233        return resp
    +2234
    +2235    async def fetch_pending_group_memberships(
    +2236        self, access_token: str, group_id: int, /, *, current_page: int = 1
    +2237    ) -> typedefs.JSONObject:
    +2238        resp = await self._request(
    +2239            RequestMethod.GET,
    +2240            f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}",
    +2241            auth=access_token,
    +2242        )
    +2243        assert isinstance(resp, dict)
    +2244        return resp
    +2245
    +2246    async def fetch_invited_group_memberships(
    +2247        self, access_token: str, group_id: int, /, *, current_page: int = 1
    +2248    ) -> typedefs.JSONObject:
    +2249        resp = await self._request(
    +2250            RequestMethod.GET,
    +2251            f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}",
    +2252            auth=access_token,
    +2253        )
    +2254        assert isinstance(resp, dict)
    +2255        return resp
    +2256
    +2257    async def invite_member_to_group(
    +2258        self,
    +2259        access_token: str,
    +2260        /,
    +2261        group_id: int,
    +2262        membership_id: int,
    +2263        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2264        *,
    +2265        message: undefined.UndefinedOr[str] = undefined.Undefined,
    +2266    ) -> typedefs.JSONObject:
    +2267        resp = await self._request(
    +2268            RequestMethod.POST,
    +2269            f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/",
    +2270            auth=access_token,
    +2271            json={"message": str(message)},
    +2272        )
    +2273        assert isinstance(resp, dict)
    +2274        return resp
    +2275
    +2276    async def cancel_group_member_invite(
    +2277        self,
    +2278        access_token: str,
    +2279        /,
    +2280        group_id: int,
    +2281        membership_id: int,
    +2282        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2283    ) -> typedefs.JSONObject:
    +2284        resp = await self._request(
    +2285            RequestMethod.POST,
    +2286            f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/",
    +2287            auth=access_token,
    +2288        )
    +2289        assert isinstance(resp, dict)
    +2290        return resp
    +2291
    +2292    async def fetch_historical_definition(self) -> typedefs.JSONObject:
    +2293        resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/")
    +2294        assert isinstance(resp, dict)
    +2295        return resp
    +2296
    +2297    async def fetch_historical_stats(
    +2298        self,
    +2299        character_id: int,
    +2300        membership_id: int,
    +2301        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2302        day_start: datetime.datetime,
    +2303        day_end: datetime.datetime,
    +2304        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    +2305        modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]],
    +2306        *,
    +2307        period_type: enums.PeriodType = enums.PeriodType.ALL_TIME,
    +2308    ) -> typedefs.JSONObject:
    +2309
    +2310        end, start = time.parse_date_range(day_end, day_start)
    +2311        resp = await self._request(
    +2312            RequestMethod.GET,
    +2313            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/",
    +2314            json={
    +2315                "dayend": end,
    +2316                "daystart": start,
    +2317                "groups": [str(int(group)) for group in groups],
    +2318                "modes": [str(int(mode)) for mode in modes],
    +2319                "periodType": int(period_type),
    +2320            },
    +2321        )
    +2322        assert isinstance(resp, dict)
    +2323        return resp
    +2324
    +2325    async def fetch_historical_stats_for_account(
    +2326        self,
    +2327        membership_id: int,
    +2328        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2329        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    +2330    ) -> typedefs.JSONObject:
    +2331        resp = await self._request(
    +2332            RequestMethod.GET,
    +2333            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/",
    +2334            json={"groups": [str(int(group)) for group in groups]},
    +2335        )
    +2336        assert isinstance(resp, dict)
    +2337        return resp
    +2338
    +2339    async def fetch_aggregated_activity_stats(
    +2340        self,
    +2341        character_id: int,
    +2342        membership_id: int,
    +2343        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2344        /,
    +2345    ) -> typedefs.JSONObject:
    +2346        resp = await self._request(
    +2347            RequestMethod.GET,
    +2348            f"Destiny2/{int(membership_type)}/Account/{membership_id}/"
    +2349            f"Character/{character_id}/Stats/AggregateActivityStats/",
    +2350        )
    +2351        assert isinstance(resp, dict)
    +2352        return resp
     
    @@ -25013,7 +19960,8 @@
    Inherited Members
    Example
    -
    import aiobungie
    +
    +
    import aiobungie
     
     async def main():
         async with aiobungie.RESTClient("TOKEN") as rest_client:
    @@ -25022,7 +19970,8 @@ 
    Example
    for member in clan_members: for k, v in member['destinyUserInfo'].items(): print(k, v) -
    +
    +
    Parameters
    @@ -25068,27 +20017,27 @@
    Logging Levels
    -
    425    def __init__(
    -426        self,
    -427        token: str,
    -428        /,
    -429        client_secret: typing.Optional[str] = None,
    -430        client_id: typing.Optional[int] = None,
    -431        *,
    -432        max_retries: int = 4,
    -433        max_ratelimit_retries: int = 3,
    -434        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    -435    ) -> None:
    -436        self._session: typing.Optional[_Session] = None
    -437        self._lock: typing.Optional[asyncio.Lock] = None
    -438        self._client_secret = client_secret
    -439        self._client_id = client_id
    -440        self._token: str = token
    -441        self._max_retries = max_retries
    -442        self._max_rate_limit_retries = max_ratelimit_retries
    -443        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    -444
    -445        self._set_debug_level(enable_debugging)
    +            
    423    def __init__(
    +424        self,
    +425        token: str,
    +426        /,
    +427        client_secret: typing.Optional[str] = None,
    +428        client_id: typing.Optional[int] = None,
    +429        *,
    +430        max_retries: int = 4,
    +431        max_ratelimit_retries: int = 3,
    +432        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    +433    ) -> None:
    +434        self._session: typing.Optional[_Session] = None
    +435        self._lock: typing.Optional[asyncio.Lock] = None
    +436        self._client_secret = client_secret
    +437        self._client_id = client_id
    +438        self._token: str = token
    +439        self._max_retries = max_retries
    +440        self._max_rate_limit_retries = max_ratelimit_retries
    +441        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    +442
    +443        self._set_debug_level(enable_debugging)
     
    @@ -25122,7 +20071,8 @@
    Logging Levels
    Example
    -
    import aiobungie
    +
    +
    import aiobungie
     
     client = aiobungie.RESTClient(ā€¦)
     
    @@ -25137,7 +20087,8 @@ 
    Example
    # Use them to fetch your user. user = await client.fetch_current_user_memberships(tokens.access_token) -
    +
    +
    @@ -25167,11 +20118,11 @@
    Example
    -
    459    @typing.final
    -460    async def close(self) -> None:
    -461        session = self._get_session()
    -462        await session.close()
    -463        self._session = None
    +            
    457    @typing.final
    +458    async def close(self) -> None:
    +459        session = self._get_session()
    +460        await session.close()
    +461        self._session = None
     
    @@ -25200,19 +20151,13 @@
    Raises
    -
    465    @typing.final
    -466    def open(self) -> None:
    -467        """Open a new client session. This is called internally with contextmanager usage."""
    -468        if self.is_alive:
    -469            raise RuntimeError("Cannot open a new session while it's already open.")
    -470
    -471        self._session = _Session.create(
    -472            owner=False,
    -473            raise_status=False,
    -474            connect=None,
    -475            socket_read=None,
    -476            socket_connect=None,
    -477        )
    +            
    463    @typing.final
    +464    def open(self) -> None:
    +465        """Open a new client session. This is called internally with contextmanager usage."""
    +466        if self.is_alive:
    +467            raise RuntimeError("Cannot open a new session while it's already open.")
    +468
    +469        self._session = _Session.create(owner=False, raise_status=False)
     
    @@ -25233,14 +20178,14 @@
    Raises
    -
    479    @typing.final
    -480    def enable_debugging(
    -481        self,
    -482        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    -483        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
    -484        /,
    -485    ) -> None:
    -486        self._set_debug_level(level, file)
    +            
    471    @typing.final
    +472    def enable_debugging(
    +473        self,
    +474        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    +475        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
    +476        /,
    +477    ) -> None:
    +478        self._set_debug_level(level, file)
     
    @@ -25278,16 +20223,16 @@
    Parameters
    -
    488    @typing.final
    -489    async def static_request(
    -490        self,
    -491        method: typing.Union[RequestMethod, str],
    -492        path: str,
    -493        *,
    -494        auth: typing.Optional[str] = None,
    -495        json: typing.Optional[dict[str, typing.Any]] = None,
    -496    ) -> ResponseSig:
    -497        return await self._request(method, path, auth=auth, json=json)
    +            
    480    @typing.final
    +481    async def static_request(
    +482        self,
    +483        method: typing.Union[RequestMethod, str],
    +484        path: str,
    +485        *,
    +486        auth: typing.Optional[str] = None,
    +487        json: typing.Optional[dict[str, typing.Any]] = None,
    +488    ) -> ResponseSig:
    +489        return await self._request(method, path, auth=auth, json=json)
     
    @@ -25322,30 +20267,28 @@
    Returns
    @typing.final
    def - build_oauth2_url(self, client_id: Optional[int] = None) -> Optional[str]: + build_oauth2_url( self, client_id: Optional[int] = None) -> Optional[aiobungie.builders.OAuthURL]:
    -
    499    @typing.final
    -500    def build_oauth2_url(
    -501        self, client_id: typing.Optional[int] = None
    -502    ) -> typing.Optional[str]:
    -503        client_id = client_id or self._client_id
    -504        if client_id is None:
    -505            return None
    -506
    -507        return url.OAUTH2_EP_BUILDER.format(
    -508            oauth_endpoint=url.OAUTH_EP,
    -509            client_id=client_id,
    -510            uuid=_uuid(),
    -511        )
    +            
    491    @typing.final
    +492    def build_oauth2_url(
    +493        self, client_id: typing.Optional[int] = None
    +494    ) -> typing.Optional[builders.OAuthURL]:
    +495        client_id = client_id or self._client_id
    +496        if client_id is None:
    +497            return None
    +498
    +499        return builders.OAuthURL(client_id=client_id)
     

    Builds an OAuth2 URL using the provided user REST/Base client secret/id.

    +

    You can't get the complete string URL by using .compile() method.

    +
    Parameters
      @@ -25357,8 +20300,8 @@
      Parameters
      Returns
    @@ -25376,32 +20319,32 @@
    Returns
    -
    738    async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response:
    -739
    -740        if not isinstance(self._client_id, int):
    -741            raise TypeError(
    -742                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
    -743            )
    -744
    -745        if not isinstance(self._client_secret, str):
    -746            raise TypeError(
    -747                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
    -748            )
    -749
    -750        headers = {
    -751            "client_secret": self._client_secret,
    -752        }
    -753
    -754        data = (
    -755            f"grant_type=authorization_code&code={code}"
    -756            f"&client_id={self._client_id}&client_secret={self._client_secret}"
    -757        )
    -758
    -759        response = await self._request(
    -760            RequestMethod.POST, "", headers=headers, data=data, oauth2=True
    -761        )
    -762        assert isinstance(response, dict)
    -763        return builders.OAuth2Response.build_response(response)
    +            
    726    async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response:
    +727
    +728        if not isinstance(self._client_id, int):
    +729            raise TypeError(
    +730                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
    +731            )
    +732
    +733        if not isinstance(self._client_secret, str):
    +734            raise TypeError(
    +735                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
    +736            )
    +737
    +738        headers = {
    +739            "client_secret": self._client_secret,
    +740        }
    +741
    +742        data = (
    +743            f"grant_type=authorization_code&code={code}"
    +744            f"&client_id={self._client_id}&client_secret={self._client_secret}"
    +745        )
    +746
    +747        response = await self._request(
    +748            RequestMethod.POST, "", headers=headers, data=data, oauth2=True
    +749        )
    +750        assert isinstance(response, dict)
    +751        return builders.OAuth2Response.build_response(response)
     
    @@ -25440,30 +20383,30 @@
    Raises
    -
    765    async def refresh_access_token(
    -766        self, refresh_token: str, /
    -767    ) -> builders.OAuth2Response:
    -768        if not isinstance(self._client_id, int):
    -769            raise TypeError(
    -770                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
    -771            )
    -772
    -773        if not isinstance(self._client_secret, str):
    -774            raise TypeError(
    -775                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
    -776            )
    -777
    -778        data = {
    -779            "grant_type": "refresh_token",
    -780            "refresh_token": refresh_token,
    -781            "client_id": self._client_id,
    -782            "client_secret": self._client_secret,
    -783            "Content-Type": "application/x-www-form-urlencoded",
    -784        }
    -785
    -786        response = await self._request(RequestMethod.POST, "", data=data, oauth2=True)
    -787        assert isinstance(response, dict)
    -788        return builders.OAuth2Response.build_response(response)
    +            
    753    async def refresh_access_token(
    +754        self, refresh_token: str, /
    +755    ) -> builders.OAuth2Response:
    +756        if not isinstance(self._client_id, int):
    +757            raise TypeError(
    +758                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
    +759            )
    +760
    +761        if not isinstance(self._client_secret, str):
    +762            raise TypeError(
    +763                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
    +764            )
    +765
    +766        data = {
    +767            "grant_type": "refresh_token",
    +768            "refresh_token": refresh_token,
    +769            "client_id": self._client_id,
    +770            "client_secret": self._client_secret,
    +771            "Content-Type": "application/x-www-form-urlencoded",
    +772        }
    +773
    +774        response = await self._request(RequestMethod.POST, "", data=data, oauth2=True)
    +775        assert isinstance(response, dict)
    +776        return builders.OAuth2Response.build_response(response)
     
    @@ -25496,13 +20439,13 @@
    Returns
    -
    790    async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject:
    -791        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -792        resp = await self._request(
    -793            RequestMethod.GET, f"User/GetBungieNetUserById/{id}/"
    -794        )
    -795        assert isinstance(resp, dict)
    -796        return resp
    +            
    778    async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject:
    +779        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +780        resp = await self._request(
    +781            RequestMethod.GET, f"User/GetBungieNetUserById/{id}/"
    +782        )
    +783        assert isinstance(resp, dict)
    +784        return resp
     
    @@ -25541,11 +20484,11 @@
    Raises
    -
    798    async def fetch_user_themes(self) -> typedefs.JSONArray:
    -799        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -800        resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/")
    -801        assert isinstance(resp, list)
    -802        return resp
    +            
    786    async def fetch_user_themes(self) -> typedefs.JSONArray:
    +787        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +788        resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/")
    +789        assert isinstance(resp, list)
    +790        return resp
     
    @@ -25565,24 +20508,24 @@
    Returns
    async def - fetch_membership_from_id( self, id: int, type: Union[int, aiobungie.MembershipType] = <MembershipType.NONE: 0>, /) -> dict[str, typing.Any]: + fetch_membership_from_id( self, id: int, type: Union[int, aiobungie.MembershipType] = <MembershipType.NONE: 0>, /) -> dict[str, typing.Any]:
    -
    804    async def fetch_membership_from_id(
    -805        self,
    -806        id: int,
    -807        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    -808        /,
    -809    ) -> typedefs.JSONObject:
    -810        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -811        resp = await self._request(
    -812            RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}"
    -813        )
    -814        assert isinstance(resp, dict)
    -815        return resp
    +            
    792    async def fetch_membership_from_id(
    +793        self,
    +794        id: int,
    +795        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    +796        /,
    +797    ) -> typedefs.JSONObject:
    +798        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +799        resp = await self._request(
    +800            RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}"
    +801        )
    +802        assert isinstance(resp, dict)
    +803        return resp
     
    @@ -25617,27 +20560,27 @@
    Raises
    async def - fetch_player( self, name: str, code: int, type: Union[int, aiobungie.MembershipType] = <MembershipType.ALL: -1>, /) -> list[typing.Any]: + fetch_player( self, name: str, code: int, type: Union[int, aiobungie.MembershipType] = <MembershipType.ALL: -1>, /) -> list[typing.Any]:
    -
    817    async def fetch_player(
    -818        self,
    -819        name: str,
    -820        code: int,
    -821        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
    -822        /,
    -823    ) -> typedefs.JSONArray:
    -824        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -825        resp = await self._request(
    -826            RequestMethod.POST,
    -827            f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}",
    -828            json={"displayName": name, "displayNameCode": code},
    -829        )
    -830        assert isinstance(resp, list)
    -831        return resp
    +            
    805    async def fetch_player(
    +806        self,
    +807        name: str,
    +808        code: int,
    +809        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
    +810        /,
    +811    ) -> typedefs.JSONArray:
    +812        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +813        resp = await self._request(
    +814            RequestMethod.POST,
    +815            f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}",
    +816            json={"displayName": name, "displayNameCode": code},
    +817        )
    +818        assert isinstance(resp, list)
    +819        return resp
     
    @@ -25681,15 +20624,15 @@
    Raises
    -
    833    async def search_users(self, name: str, /) -> typedefs.JSONObject:
    -834        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -835        resp = await self._request(
    -836            RequestMethod.POST,
    -837            "User/Search/GlobalName/0",
    -838            json={"displayNamePrefix": name},
    -839        )
    -840        assert isinstance(resp, dict)
    -841        return resp
    +            
    821    async def search_users(self, name: str, /) -> typedefs.JSONObject:
    +822        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +823        resp = await self._request(
    +824            RequestMethod.POST,
    +825            "User/Search/GlobalName/0",
    +826            json={"displayNamePrefix": name},
    +827        )
    +828        assert isinstance(resp, dict)
    +829        return resp
     
    @@ -25728,15 +20671,15 @@
    Raises
    -
    843    async def fetch_clan_from_id(
    -844        self, id: int, /, access_token: typing.Optional[str] = None
    -845    ) -> typedefs.JSONObject:
    -846        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -847        resp = await self._request(
    -848            RequestMethod.GET, f"GroupV2/{id}", auth=access_token
    -849        )
    -850        assert isinstance(resp, dict)
    -851        return resp
    +            
    831    async def fetch_clan_from_id(
    +832        self, id: int, /, access_token: typing.Optional[str] = None
    +833    ) -> typedefs.JSONObject:
    +834        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +835        resp = await self._request(
    +836            RequestMethod.GET, f"GroupV2/{id}", auth=access_token
    +837        )
    +838        assert isinstance(resp, dict)
    +839        return resp
     
    @@ -25780,26 +20723,26 @@
    Raises
    async def - fetch_clan( self, name: str, /, access_token: Optional[str] = None, *, type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> dict[str, typing.Any]: + fetch_clan( self, name: str, /, access_token: Optional[str] = None, *, type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> dict[str, typing.Any]:
    -
    853    async def fetch_clan(
    -854        self,
    -855        name: str,
    -856        /,
    -857        access_token: typing.Optional[str] = None,
    -858        *,
    -859        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    -860    ) -> typedefs.JSONObject:
    -861        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -862        resp = await self._request(
    -863            RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token
    -864        )
    -865        assert isinstance(resp, dict)
    -866        return resp
    +            
    841    async def fetch_clan(
    +842        self,
    +843        name: str,
    +844        /,
    +845        access_token: typing.Optional[str] = None,
    +846        *,
    +847        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    +848    ) -> typedefs.JSONObject:
    +849        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +850        resp = await self._request(
    +851            RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token
    +852        )
    +853        assert isinstance(resp, dict)
    +854        return resp
     
    @@ -25852,13 +20795,13 @@
    Raises
    -
    868    async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject:
    -869        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -870        resp = await self._request(
    -871            RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/"
    -872        )
    -873        assert isinstance(resp, dict)
    -874        return resp
    +            
    856    async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject:
    +857        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +858        resp = await self._request(
    +859            RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/"
    +860        )
    +861        assert isinstance(resp, dict)
    +862        return resp
     
    @@ -25897,13 +20840,13 @@
    Raises
    -
    876    async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray:
    -877        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -878        resp = await self._request(
    -879            RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/"
    -880        )
    -881        assert isinstance(resp, list)
    -882        return resp
    +            
    864    async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray:
    +865        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +866        resp = await self._request(
    +867            RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/"
    +868        )
    +869        assert isinstance(resp, list)
    +870        return resp
     
    @@ -25936,11 +20879,11 @@
    Returns
    -
    884    async def fetch_application(self, appid: int, /) -> typedefs.JSONObject:
    -885        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -886        resp = await self._request(RequestMethod.GET, f"App/Application/{appid}")
    -887        assert isinstance(resp, dict)
    -888        return resp
    +            
    872    async def fetch_application(self, appid: int, /) -> typedefs.JSONObject:
    +873        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +874        resp = await self._request(RequestMethod.GET, f"App/Application/{appid}")
    +875        assert isinstance(resp, dict)
    +876        return resp
     
    @@ -25973,24 +20916,24 @@
    Returns
    -
    890    async def fetch_character(
    -891        self,
    -892        member_id: int,
    -893        membership_type: typedefs.IntAnd[enums.MembershipType],
    -894        character_id: int,
    -895        components: list[enums.ComponentType],
    -896        auth: typing.Optional[str] = None,
    -897    ) -> typedefs.JSONObject:
    -898        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -899        collector = _collect_components(components)
    -900        response = await self._request(
    -901            RequestMethod.GET,
    -902            f"Destiny2/{int(membership_type)}/Profile/{member_id}/"
    -903            f"Character/{character_id}/?components={collector}",
    -904            auth=auth,
    -905        )
    -906        assert isinstance(response, dict)
    -907        return response
    +            
    878    async def fetch_character(
    +879        self,
    +880        member_id: int,
    +881        membership_type: typedefs.IntAnd[enums.MembershipType],
    +882        character_id: int,
    +883        components: list[enums.ComponentType],
    +884        auth: typing.Optional[str] = None,
    +885    ) -> typedefs.JSONObject:
    +886        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +887        collector = _collect_components(components)
    +888        response = await self._request(
    +889            RequestMethod.GET,
    +890            f"Destiny2/{int(membership_type)}/Profile/{member_id}/"
    +891            f"Character/{character_id}/?components={collector}",
    +892            auth=auth,
    +893        )
    +894        assert isinstance(response, dict)
    +895        return response
     
    @@ -26037,33 +20980,33 @@
    Raises
    async def - fetch_activities( self, member_id: int, character_id: int, mode: Union[int, aiobungie.GameMode], membership_type: Union[int, aiobungie.MembershipType] = <MembershipType.ALL: -1>, *, page: int = 0, limit: int = 1) -> dict[str, typing.Any]: + fetch_activities( self, member_id: int, character_id: int, mode: Union[int, aiobungie.GameMode], membership_type: Union[int, aiobungie.MembershipType] = <MembershipType.ALL: -1>, *, page: int = 0, limit: int = 1) -> dict[str, typing.Any]:
    -
    909    async def fetch_activities(
    -910        self,
    -911        member_id: int,
    -912        character_id: int,
    -913        mode: typedefs.IntAnd[enums.GameMode],
    -914        membership_type: typedefs.IntAnd[
    -915            enums.MembershipType
    -916        ] = enums.MembershipType.ALL,
    -917        *,
    -918        page: int = 0,
    -919        limit: int = 1,
    -920    ) -> typedefs.JSONObject:
    -921        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -922        resp = await self._request(
    -923            RequestMethod.GET,
    -924            f"Destiny2/{int(membership_type)}/Account/"
    -925            f"{member_id}/Character/{character_id}/Stats/Activities"
    -926            f"/?mode={int(mode)}&count={limit}&page={page}",
    -927        )
    -928        assert isinstance(resp, dict)
    -929        return resp
    +            
    897    async def fetch_activities(
    +898        self,
    +899        member_id: int,
    +900        character_id: int,
    +901        mode: typedefs.IntAnd[enums.GameMode],
    +902        membership_type: typedefs.IntAnd[
    +903            enums.MembershipType
    +904        ] = enums.MembershipType.ALL,
    +905        *,
    +906        page: int = 0,
    +907        limit: int = 1,
    +908    ) -> typedefs.JSONObject:
    +909        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +910        resp = await self._request(
    +911            RequestMethod.GET,
    +912            f"Destiny2/{int(membership_type)}/Account/"
    +913            f"{member_id}/Character/{character_id}/Stats/Activities"
    +914            f"/?mode={int(mode)}&count={limit}&page={page}",
    +915        )
    +916        assert isinstance(resp, dict)
    +917        return resp
     
    @@ -26118,14 +21061,14 @@
    Raises
    -
    931    async def fetch_vendor_sales(self) -> typedefs.JSONObject:
    -932        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -933        resp = await self._request(
    -934            RequestMethod.GET,
    -935            f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}",
    -936        )
    -937        assert isinstance(resp, dict)
    -938        return resp
    +            
    919    async def fetch_vendor_sales(self) -> typedefs.JSONObject:
    +920        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +921        resp = await self._request(
    +922            RequestMethod.GET,
    +923            f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}",
    +924        )
    +925        assert isinstance(resp, dict)
    +926        return resp
     
    @@ -26143,22 +21086,22 @@
    Raises
    -
    940    async def fetch_profile(
    -941        self,
    -942        membership_id: int,
    -943        type: typedefs.IntAnd[enums.MembershipType],
    -944        components: list[enums.ComponentType],
    -945        auth: typing.Optional[str] = None,
    -946    ) -> typedefs.JSONObject:
    -947        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -948        collector = _collect_components(components)
    -949        response = await self._request(
    -950            RequestMethod.GET,
    -951            f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}",
    -952            auth=auth,
    -953        )
    -954        assert isinstance(response, dict)
    -955        return response
    +            
    928    async def fetch_profile(
    +929        self,
    +930        membership_id: int,
    +931        type: typedefs.IntAnd[enums.MembershipType],
    +932        components: list[enums.ComponentType],
    +933        auth: typing.Optional[str] = None,
    +934    ) -> typedefs.JSONObject:
    +935        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +936        collector = _collect_components(components)
    +937        response = await self._request(
    +938            RequestMethod.GET,
    +939            f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}",
    +940            auth=auth,
    +941        )
    +942        assert isinstance(response, dict)
    +943        return response
     
    @@ -26209,13 +21152,13 @@
    Raises
    -
    957    async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject:
    -958        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -959        response = await self._request(
    -960            RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}"
    -961        )
    -962        assert isinstance(response, dict)
    -963        return response
    +            
    945    async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject:
    +946        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +947        response = await self._request(
    +948            RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}"
    +949        )
    +950        assert isinstance(response, dict)
    +951        return response
     
    @@ -26250,11 +21193,11 @@
    Returns
    -
    965    async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject:
    -966        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -967        resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash)
    -968        assert isinstance(resp, dict)
    -969        return resp
    +            
    953    async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject:
    +954        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +955        resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash)
    +956        assert isinstance(resp, dict)
    +957        return resp
     
    @@ -26287,11 +21230,11 @@
    Returns
    -
    971    async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject:
    -972        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -973        resp = await self.fetch_entity("DestinyObjectiveDefinition", hash)
    -974        assert isinstance(resp, dict)
    -975        return resp
    +            
    959    async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject:
    +960        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +961        resp = await self.fetch_entity("DestinyObjectiveDefinition", hash)
    +962        assert isinstance(resp, dict)
    +963        return resp
     
    @@ -26318,27 +21261,27 @@
    Returns
    async def - fetch_groups_for_member( self, member_id: int, member_type: Union[int, aiobungie.MembershipType], /, *, filter: int = 0, group_type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> dict[str, typing.Any]: + fetch_groups_for_member( self, member_id: int, member_type: Union[int, aiobungie.MembershipType], /, *, filter: int = 0, group_type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> dict[str, typing.Any]:
    -
    977    async def fetch_groups_for_member(
    -978        self,
    -979        member_id: int,
    -980        member_type: typedefs.IntAnd[enums.MembershipType],
    -981        /,
    -982        *,
    -983        filter: int = 0,
    -984        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    -985    ) -> typedefs.JSONObject:
    -986        resp = await self._request(
    -987            RequestMethod.GET,
    -988            f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
    -989        )
    -990        assert isinstance(resp, dict)
    -991        return resp
    +            
    965    async def fetch_groups_for_member(
    +966        self,
    +967        member_id: int,
    +968        member_type: typedefs.IntAnd[enums.MembershipType],
    +969        /,
    +970        *,
    +971        filter: int = 0,
    +972        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    +973    ) -> typedefs.JSONObject:
    +974        resp = await self._request(
    +975            RequestMethod.GET,
    +976            f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
    +977        )
    +978        assert isinstance(resp, dict)
    +979        return resp
     
    @@ -26360,7 +21303,7 @@
    Other Parameters
    Filter apply to list of joined groups. This Default to 0
  • group_type (aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. -This is always set to aiobungie.GroupType.CLAN and should not be changed.
  • +This is always set to aiobungie.GroupType.CLAN and should not be changed.
    Returns
    @@ -26377,27 +21320,27 @@
    Returns
    async def - fetch_potential_groups_for_member( self, member_id: int, member_type: Union[int, aiobungie.MembershipType], /, *, filter: int = 0, group_type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> dict[str, typing.Any]: + fetch_potential_groups_for_member( self, member_id: int, member_type: Union[int, aiobungie.MembershipType], /, *, filter: int = 0, group_type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> dict[str, typing.Any]:
    -
     993    async def fetch_potential_groups_for_member(
    - 994        self,
    - 995        member_id: int,
    - 996        member_type: typedefs.IntAnd[enums.MembershipType],
    - 997        /,
    - 998        *,
    - 999        filter: int = 0,
    -1000        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    -1001    ) -> typedefs.JSONObject:
    -1002        resp = await self._request(
    -1003            RequestMethod.GET,
    -1004            f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
    -1005        )
    -1006        assert isinstance(resp, dict)
    -1007        return resp
    +            
    981    async def fetch_potential_groups_for_member(
    +982        self,
    +983        member_id: int,
    +984        member_type: typedefs.IntAnd[enums.MembershipType],
    +985        /,
    +986        *,
    +987        filter: int = 0,
    +988        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    +989    ) -> typedefs.JSONObject:
    +990        resp = await self._request(
    +991            RequestMethod.GET,
    +992            f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
    +993        )
    +994        assert isinstance(resp, dict)
    +995        return resp
     
    @@ -26419,7 +21362,7 @@
    Other Parameters
    Filter apply to list of joined groups. This Default to 0
  • group_type (aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. -This is always set to aiobungie.GroupType.CLAN and should not be changed.
  • +This is always set to aiobungie.GroupType.CLAN and should not be changed.
    Returns
    @@ -26436,27 +21379,27 @@
    Returns
    async def - fetch_clan_members( self, clan_id: int, /, *, name: Optional[str] = None, type: Union[int, aiobungie.MembershipType] = <MembershipType.NONE: 0>) -> dict[str, typing.Any]: + fetch_clan_members( self, clan_id: int, /, *, name: Optional[str] = None, type: Union[int, aiobungie.MembershipType] = <MembershipType.NONE: 0>) -> dict[str, typing.Any]:
    -
    1009    async def fetch_clan_members(
    -1010        self,
    -1011        clan_id: int,
    -1012        /,
    -1013        *,
    -1014        name: typing.Optional[str] = None,
    -1015        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    -1016    ) -> typedefs.JSONObject:
    -1017        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1018        resp = await self._request(
    -1019            RequestMethod.GET,
    -1020            f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}&currentpage=1",
    -1021        )
    -1022        assert isinstance(resp, dict)
    -1023        return resp
    +            
     997    async def fetch_clan_members(
    + 998        self,
    + 999        clan_id: int,
    +1000        /,
    +1001        *,
    +1002        name: typing.Optional[str] = None,
    +1003        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
    +1004    ) -> typedefs.JSONObject:
    +1005        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1006        resp = await self._request(
    +1007            RequestMethod.GET,
    +1008            f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}&currentpage=1",
    +1009        )
    +1010        assert isinstance(resp, dict)
    +1011        return resp
     
    @@ -26476,7 +21419,7 @@
    Other Parameters
    If provided, Only players matching this name will be returned.
  • type (aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): An optional clan member's membership type. -Default is set to aiobungie.MembershipType.NONE +Default is set to aiobungie.MembershipType.NONE Which returns the first matched clan member by their name.
  • @@ -26500,31 +21443,31 @@
    Raises
    async def - fetch_hardlinked_credentials( self, credential: int, type: Union[int, aiobungie.CredentialType] = <CredentialType.STEAMID: 12>, /) -> dict[str, typing.Any]: + fetch_hardlinked_credentials( self, credential: int, type: Union[int, aiobungie.CredentialType] = <CredentialType.STEAMID: 12>, /) -> dict[str, typing.Any]:
    -
    1025    async def fetch_hardlinked_credentials(
    -1026        self,
    -1027        credential: int,
    -1028        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
    -1029        /,
    -1030    ) -> typedefs.JSONObject:
    -1031        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1032        resp = await self._request(
    -1033            RequestMethod.GET,
    -1034            f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/",
    -1035        )
    -1036        assert isinstance(resp, dict)
    -1037        return resp
    +            
    1013    async def fetch_hardlinked_credentials(
    +1014        self,
    +1015        credential: int,
    +1016        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
    +1017        /,
    +1018    ) -> typedefs.JSONObject:
    +1019        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1020        resp = await self._request(
    +1021            RequestMethod.GET,
    +1022            f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/",
    +1023        )
    +1024        assert isinstance(resp, dict)
    +1025        return resp
     

    Gets any hard linked membership given a credential.

    -

    Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now. +

    Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now. Cross Save aware.

    Parameters
    @@ -26557,16 +21500,16 @@
    Returns
    -
    1039    async def fetch_user_credentials(
    -1040        self, access_token: str, membership_id: int, /
    -1041    ) -> typedefs.JSONArray:
    -1042        resp = await self._request(
    -1043            RequestMethod.GET,
    -1044            f"User/GetCredentialTypesForTargetAccount/{membership_id}",
    -1045            auth=access_token,
    -1046        )
    -1047        assert isinstance(resp, list)
    -1048        return resp
    +            
    1027    async def fetch_user_credentials(
    +1028        self, access_token: str, membership_id: int, /
    +1029    ) -> typedefs.JSONArray:
    +1030        resp = await self._request(
    +1031            RequestMethod.GET,
    +1032            f"User/GetCredentialTypesForTargetAccount/{membership_id}",
    +1033            auth=access_token,
    +1034        )
    +1035        assert isinstance(resp, list)
    +1036        return resp
     
    @@ -26613,31 +21556,31 @@
    Raises
    -
    1050    async def insert_socket_plug(
    -1051        self,
    -1052        action_token: str,
    -1053        /,
    -1054        instance_id: int,
    -1055        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
    -1056        character_id: int,
    -1057        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1058    ) -> typedefs.JSONObject:
    -1059
    -1060        if isinstance(plug, builders.PlugSocketBuilder):
    -1061            plug = plug.collect()
    -1062
    -1063        body = {
    -1064            "actionToken": action_token,
    -1065            "itemInstanceId": instance_id,
    -1066            "plug": plug,
    -1067            "characterId": character_id,
    -1068            "membershipType": int(membership_type),
    -1069        }
    -1070        resp = await self._request(
    -1071            RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body
    -1072        )
    -1073        assert isinstance(resp, dict)
    -1074        return resp
    +            
    1038    async def insert_socket_plug(
    +1039        self,
    +1040        action_token: str,
    +1041        /,
    +1042        instance_id: int,
    +1043        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
    +1044        character_id: int,
    +1045        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1046    ) -> typedefs.JSONObject:
    +1047
    +1048        if isinstance(plug, builders.PlugSocketBuilder):
    +1049            plug = plug.collect()
    +1050
    +1051        body = {
    +1052            "actionToken": action_token,
    +1053            "itemInstanceId": instance_id,
    +1054            "plug": plug,
    +1055            "characterId": character_id,
    +1056            "membershipType": int(membership_type),
    +1057        }
    +1058        resp = await self._request(
    +1059            RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body
    +1060        )
    +1061        assert isinstance(resp, dict)
    +1062        return resp
     
    @@ -26662,7 +21605,8 @@
    Parameters
    Example
    -
    plug = (
    +
    +
    plug = (
         aiobungie.PlugSocketBuilder()
         .set_socket_array(0)
         .set_socket_index(0)
    @@ -26670,7 +21614,8 @@ 
    Example
    .collect() ) await insert_socket_plug_free(..., plug=plug) -
    +
    +

    character_id : int The character's id. @@ -26703,33 +21648,33 @@

    Raises
    -
    1076    async def insert_socket_plug_free(
    -1077        self,
    -1078        access_token: str,
    -1079        /,
    -1080        instance_id: int,
    -1081        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
    -1082        character_id: int,
    -1083        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1084    ) -> typedefs.JSONObject:
    -1085
    -1086        if isinstance(plug, builders.PlugSocketBuilder):
    -1087            plug = plug.collect()
    -1088
    -1089        body = {
    -1090            "itemInstanceId": instance_id,
    -1091            "plug": plug,
    -1092            "characterId": character_id,
    -1093            "membershipType": int(membership_type),
    -1094        }
    -1095        resp = await self._request(
    -1096            RequestMethod.POST,
    -1097            "Destiny2/Actions/Items/InsertSocketPlugFree",
    -1098            json=body,
    -1099            auth=access_token,
    -1100        )
    -1101        assert isinstance(resp, dict)
    -1102        return resp
    +            
    1064    async def insert_socket_plug_free(
    +1065        self,
    +1066        access_token: str,
    +1067        /,
    +1068        instance_id: int,
    +1069        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
    +1070        character_id: int,
    +1071        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1072    ) -> typedefs.JSONObject:
    +1073
    +1074        if isinstance(plug, builders.PlugSocketBuilder):
    +1075            plug = plug.collect()
    +1076
    +1077        body = {
    +1078            "itemInstanceId": instance_id,
    +1079            "plug": plug,
    +1080            "characterId": character_id,
    +1081            "membershipType": int(membership_type),
    +1082        }
    +1083        resp = await self._request(
    +1084            RequestMethod.POST,
    +1085            "Destiny2/Actions/Items/InsertSocketPlugFree",
    +1086            json=body,
    +1087            auth=access_token,
    +1088        )
    +1089        assert isinstance(resp, dict)
    +1090        return resp
     
    @@ -26752,7 +21697,8 @@
    Parameters
    Example
    -
    plug = (
    +
    +
    plug = (
         aiobungie.PlugSocketBuilder()
         .set_socket_array(0)
         .set_socket_index(0)
    @@ -26760,7 +21706,8 @@ 
    Example
    .collect() ) await insert_socket_plug_free(..., plug=plug) -
    +
    +

    character_id : int The character's id. @@ -26793,29 +21740,29 @@

    Raises
    -
    1104    async def set_item_lock_state(
    -1105        self,
    -1106        access_token: str,
    -1107        state: bool,
    -1108        /,
    -1109        item_id: int,
    -1110        character_id: int,
    -1111        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1112    ) -> int:
    -1113        body = {
    -1114            "state": state,
    -1115            "itemId": item_id,
    -1116            "characterId": character_id,
    -1117            "membership_type": int(membership_type),
    -1118        }
    -1119        response = await self._request(
    -1120            RequestMethod.POST,
    -1121            "Destiny2/Actions/Items/SetLockState",
    -1122            json=body,
    -1123            auth=access_token,
    -1124        )
    -1125        assert isinstance(response, int)
    -1126        return response
    +            
    1092    async def set_item_lock_state(
    +1093        self,
    +1094        access_token: str,
    +1095        state: bool,
    +1096        /,
    +1097        item_id: int,
    +1098        character_id: int,
    +1099        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1100    ) -> int:
    +1101        body = {
    +1102            "state": state,
    +1103            "itemId": item_id,
    +1104            "characterId": character_id,
    +1105            "membership_type": int(membership_type),
    +1106        }
    +1107        response = await self._request(
    +1108            RequestMethod.POST,
    +1109            "Destiny2/Actions/Items/SetLockState",
    +1110            json=body,
    +1111            auth=access_token,
    +1112        )
    +1113        assert isinstance(response, int)
    +1114        return response
     
    @@ -26872,29 +21819,29 @@
    Raises
    -
    1128    async def set_quest_track_state(
    -1129        self,
    -1130        access_token: str,
    -1131        state: bool,
    -1132        /,
    -1133        item_id: int,
    -1134        character_id: int,
    -1135        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1136    ) -> int:
    -1137        body = {
    -1138            "state": state,
    -1139            "itemId": item_id,
    -1140            "characterId": character_id,
    -1141            "membership_type": int(membership_type),
    -1142        }
    -1143        response = await self._request(
    -1144            RequestMethod.POST,
    -1145            "Destiny2/Actions/Items/SetTrackedState",
    -1146            json=body,
    -1147            auth=access_token,
    -1148        )
    -1149        assert isinstance(response, int)
    -1150        return response
    +            
    1116    async def set_quest_track_state(
    +1117        self,
    +1118        access_token: str,
    +1119        state: bool,
    +1120        /,
    +1121        item_id: int,
    +1122        character_id: int,
    +1123        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1124    ) -> int:
    +1125        body = {
    +1126            "state": state,
    +1127            "itemId": item_id,
    +1128            "characterId": character_id,
    +1129            "membership_type": int(membership_type),
    +1130        }
    +1131        response = await self._request(
    +1132            RequestMethod.POST,
    +1133            "Destiny2/Actions/Items/SetTrackedState",
    +1134            json=body,
    +1135            auth=access_token,
    +1136        )
    +1137        assert isinstance(response, int)
    +1138        return response
     
    @@ -26951,11 +21898,11 @@
    Raises
    -
    1152    async def fetch_manifest_path(self) -> typedefs.JSONObject:
    -1153        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1154        path = await self._request(RequestMethod.GET, "Destiny2/Manifest")
    -1155        assert isinstance(path, dict)
    -1156        return path
    +            
    1140    async def fetch_manifest_path(self) -> typedefs.JSONObject:
    +1141        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1142        path = await self._request(RequestMethod.GET, "Destiny2/Manifest")
    +1143        assert isinstance(path, dict)
    +1144        return path
     
    @@ -26981,19 +21928,19 @@
    Returns
    -
    1158    async def read_manifest_bytes(self, language: str = "en", /) -> bytes:
    -1159        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1160        _ensure_manifest_language(language)
    -1161
    -1162        content = await self.fetch_manifest_path()
    -1163        resp = await self._request(
    -1164            RequestMethod.GET,
    -1165            content["mobileWorldContentPaths"][language],
    -1166            unwrapping="read",
    -1167            base=True,
    -1168        )
    -1169        assert isinstance(resp, bytes)
    -1170        return resp
    +            
    1146    async def read_manifest_bytes(self, language: str = "en", /) -> bytes:
    +1147        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1148        _ensure_manifest_language(language)
    +1149
    +1150        content = await self.fetch_manifest_path()
    +1151        resp = await self._request(
    +1152            RequestMethod.GET,
    +1153            content["mobileWorldContentPaths"][language],
    +1154            unwrapping="read",
    +1155            base=True,
    +1156        )
    +1157        assert isinstance(resp, bytes)
    +1158        return resp
     
    @@ -27029,37 +21976,37 @@
    Returns
    -
    1172    async def download_manifest(
    -1173        self,
    -1174        language: str = "en",
    -1175        name: str = "manifest",
    -1176        path: typing.Union[pathlib.Path, str] = ".",
    -1177        *,
    -1178        force: bool = False,
    -1179    ) -> None:
    -1180        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1181        complete_path = _get_path(name, path, sql=True)
    -1182
    -1183        if complete_path.exists() and force:
    -1184            if force:
    -1185                _LOG.info(
    -1186                    f"Found manifest in {complete_path!s}. Forcing to Re-Download."
    -1187                )
    -1188                complete_path.unlink(missing_ok=True)
    -1189
    -1190                return await self.download_manifest(language, name, path, force=force)
    -1191
    -1192            else:
    -1193                raise FileExistsError(
    -1194                    "Manifest file already exists, "
    -1195                    "To force download, set the `force` parameter to `True`."
    -1196                )
    -1197
    -1198        _LOG.info(f"Downloading manifest. Location: {complete_path!s}")
    -1199        data_bytes = await self.read_manifest_bytes(language)
    -1200        await asyncio.get_running_loop().run_in_executor(
    -1201            None, _write_sqlite_bytes, data_bytes, path, name
    -1202        )
    +            
    1160    async def download_manifest(
    +1161        self,
    +1162        language: str = "en",
    +1163        name: str = "manifest",
    +1164        path: typing.Union[pathlib.Path, str] = ".",
    +1165        *,
    +1166        force: bool = False,
    +1167    ) -> None:
    +1168        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1169        complete_path = _get_path(name, path, sql=True)
    +1170
    +1171        if complete_path.exists() and force:
    +1172            if force:
    +1173                _LOG.info(
    +1174                    f"Found manifest in {complete_path!s}. Forcing to Re-Download."
    +1175                )
    +1176                complete_path.unlink(missing_ok=True)
    +1177
    +1178                return await self.download_manifest(language, name, path, force=force)
    +1179
    +1180            else:
    +1181                raise FileExistsError(
    +1182                    "Manifest file already exists, "
    +1183                    "To force download, set the `force` parameter to `True`."
    +1184                )
    +1185
    +1186        _LOG.info(f"Downloading manifest. Location: {complete_path!s}")
    +1187        data_bytes = await self.read_manifest_bytes(language)
    +1188        await asyncio.get_running_loop().run_in_executor(
    +1189            None, _write_sqlite_bytes, data_bytes, path, name
    +1190        )
     
    @@ -27111,28 +22058,28 @@
    Raises
    -
    1204    async def download_json_manifest(
    -1205        self,
    -1206        file_name: str = "manifest",
    -1207        path: typing.Union[str, pathlib.Path] = ".",
    -1208        language: str = "en",
    -1209    ) -> None:
    -1210        _ensure_manifest_language(language)
    -1211
    -1212        _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...")
    -1213
    -1214        content = await self.fetch_manifest_path()
    -1215        json_bytes = await self._request(
    -1216            RequestMethod.GET,
    -1217            content["jsonWorldContentPaths"][language],
    -1218            unwrapping="read",
    -1219            base=True,
    -1220        )
    -1221
    -1222        await asyncio.get_running_loop().run_in_executor(
    -1223            None, _write_json_bytes, json_bytes, file_name, path
    -1224        )
    -1225        _LOG.info("Finished downloading manifest JSON.")
    +            
    1192    async def download_json_manifest(
    +1193        self,
    +1194        file_name: str = "manifest",
    +1195        path: typing.Union[str, pathlib.Path] = ".",
    +1196        language: str = "en",
    +1197    ) -> None:
    +1198        _ensure_manifest_language(language)
    +1199
    +1200        _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...")
    +1201
    +1202        content = await self.fetch_manifest_path()
    +1203        json_bytes = await self._request(
    +1204            RequestMethod.GET,
    +1205            content["jsonWorldContentPaths"][language],
    +1206            unwrapping="read",
    +1207            base=True,
    +1208        )
    +1209
    +1210        await asyncio.get_running_loop().run_in_executor(
    +1211            None, _write_json_bytes, json_bytes, file_name, path
    +1212        )
    +1213        _LOG.info("Finished downloading manifest JSON.")
     
    @@ -27163,8 +22110,8 @@
    Parameters
    -
    1227    async def fetch_manifest_version(self) -> str:
    -1228        return typing.cast(str, (await self.fetch_manifest_path())["version"])
    +            
    1215    async def fetch_manifest_version(self) -> str:
    +1216        return typing.cast(str, (await self.fetch_manifest_path())["version"])
     
    @@ -27190,21 +22137,21 @@
    Returns
    -
    1230    async def fetch_linked_profiles(
    -1231        self,
    -1232        member_id: int,
    -1233        member_type: typedefs.IntAnd[enums.MembershipType],
    -1234        /,
    -1235        *,
    -1236        all: bool = False,
    -1237    ) -> typedefs.JSONObject:
    -1238        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1239        resp = await self._request(
    -1240            RequestMethod.GET,
    -1241            f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}",
    -1242        )
    -1243        assert isinstance(resp, dict)
    -1244        return resp
    +            
    1218    async def fetch_linked_profiles(
    +1219        self,
    +1220        member_id: int,
    +1221        member_type: typedefs.IntAnd[enums.MembershipType],
    +1222        /,
    +1223        *,
    +1224        all: bool = False,
    +1225    ) -> typedefs.JSONObject:
    +1226        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1227        resp = await self._request(
    +1228            RequestMethod.GET,
    +1229            f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}",
    +1230        )
    +1231        assert isinstance(resp, dict)
    +1232        return resp
     
    @@ -27259,13 +22206,13 @@
    Returns
    -
    1246    async def fetch_clan_banners(self) -> typedefs.JSONObject:
    -1247        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1248        resp = await self._request(
    -1249            RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/"
    -1250        )
    -1251        assert isinstance(resp, dict)
    -1252        return resp
    +            
    1234    async def fetch_clan_banners(self) -> typedefs.JSONObject:
    +1235        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1236        resp = await self._request(
    +1237            RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/"
    +1238        )
    +1239        assert isinstance(resp, dict)
    +1240        return resp
     
    @@ -27291,11 +22238,11 @@
    Returns
    -
    1254    async def fetch_public_milestones(self) -> typedefs.JSONObject:
    -1255        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1256        resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/")
    -1257        assert isinstance(resp, dict)
    -1258        return resp
    +            
    1242    async def fetch_public_milestones(self) -> typedefs.JSONObject:
    +1243        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1244        resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/")
    +1245        assert isinstance(resp, dict)
    +1246        return resp
     
    @@ -27321,15 +22268,15 @@
    Returns
    -
    1260    async def fetch_public_milestone_content(
    -1261        self, milestone_hash: int, /
    -1262    ) -> typedefs.JSONObject:
    -1263        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1264        resp = await self._request(
    -1265            RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/"
    -1266        )
    -1267        assert isinstance(resp, dict)
    -1268        return resp
    +            
    1248    async def fetch_public_milestone_content(
    +1249        self, milestone_hash: int, /
    +1250    ) -> typedefs.JSONObject:
    +1251        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1252        resp = await self._request(
    +1253            RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/"
    +1254        )
    +1255        assert isinstance(resp, dict)
    +1256        return resp
     
    @@ -27362,17 +22309,17 @@
    Returns
    -
    1270    async def fetch_current_user_memberships(
    -1271        self, access_token: str, /
    -1272    ) -> typedefs.JSONObject:
    -1273        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1274        resp = await self._request(
    -1275            RequestMethod.GET,
    -1276            "User/GetMembershipsForCurrentUser/",
    -1277            auth=access_token,
    -1278        )
    -1279        assert isinstance(resp, dict)
    -1280        return resp
    +            
    1258    async def fetch_current_user_memberships(
    +1259        self, access_token: str, /
    +1260    ) -> typedefs.JSONObject:
    +1261        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1262        resp = await self._request(
    +1263            RequestMethod.GET,
    +1264            "User/GetMembershipsForCurrentUser/",
    +1265            auth=access_token,
    +1266        )
    +1267        assert isinstance(resp, dict)
    +1268        return resp
     
    @@ -27412,27 +22359,27 @@
    Returns
    -
    1282    async def equip_item(
    -1283        self,
    -1284        access_token: str,
    -1285        /,
    -1286        item_id: int,
    -1287        character_id: int,
    -1288        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1289    ) -> None:
    -1290        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1291        payload = {
    -1292            "itemId": item_id,
    -1293            "characterId": character_id,
    -1294            "membershipType": int(membership_type),
    -1295        }
    -1296
    -1297        await self._request(
    -1298            RequestMethod.POST,
    -1299            "Destiny2/Actions/Items/EquipItem/",
    -1300            json=payload,
    -1301            auth=access_token,
    -1302        )
    +            
    1270    async def equip_item(
    +1271        self,
    +1272        access_token: str,
    +1273        /,
    +1274        item_id: int,
    +1275        character_id: int,
    +1276        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1277    ) -> None:
    +1278        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1279        payload = {
    +1280            "itemId": item_id,
    +1281            "characterId": character_id,
    +1282            "membershipType": int(membership_type),
    +1283        }
    +1284
    +1285        await self._request(
    +1286            RequestMethod.POST,
    +1287            "Destiny2/Actions/Items/EquipItem/",
    +1288            json=payload,
    +1289            auth=access_token,
    +1290        )
     
    @@ -27473,26 +22420,26 @@
    Parameters
    -
    1304    async def equip_items(
    -1305        self,
    -1306        access_token: str,
    -1307        /,
    -1308        item_ids: list[int],
    -1309        character_id: int,
    -1310        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1311    ) -> None:
    -1312        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1313        payload = {
    -1314            "itemIds": item_ids,
    -1315            "characterId": character_id,
    -1316            "membershipType": int(membership_type),
    -1317        }
    -1318        await self._request(
    -1319            RequestMethod.POST,
    -1320            "Destiny2/Actions/Items/EquipItems/",
    -1321            json=payload,
    -1322            auth=access_token,
    -1323        )
    +            
    1292    async def equip_items(
    +1293        self,
    +1294        access_token: str,
    +1295        /,
    +1296        item_ids: list[int],
    +1297        character_id: int,
    +1298        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1299    ) -> None:
    +1300        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1301        payload = {
    +1302            "itemIds": item_ids,
    +1303            "characterId": character_id,
    +1304            "membershipType": int(membership_type),
    +1305        }
    +1306        await self._request(
    +1307            RequestMethod.POST,
    +1308            "Destiny2/Actions/Items/EquipItems/",
    +1309            json=payload,
    +1310            auth=access_token,
    +1311        )
     
    @@ -27533,25 +22480,25 @@
    Parameters
    -
    1325    async def ban_clan_member(
    -1326        self,
    -1327        access_token: str,
    -1328        /,
    -1329        group_id: int,
    -1330        membership_id: int,
    -1331        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1332        *,
    -1333        length: int = 0,
    -1334        comment: undefined.UndefinedOr[str] = undefined.Undefined,
    -1335    ) -> None:
    -1336        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1337        payload = {"comment": str(comment), "length": length}
    -1338        await self._request(
    -1339            RequestMethod.POST,
    -1340            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/",
    -1341            json=payload,
    -1342            auth=access_token,
    -1343        )
    +            
    1313    async def ban_clan_member(
    +1314        self,
    +1315        access_token: str,
    +1316        /,
    +1317        group_id: int,
    +1318        membership_id: int,
    +1319        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1320        *,
    +1321        length: int = 0,
    +1322        comment: undefined.UndefinedOr[str] = undefined.Undefined,
    +1323    ) -> None:
    +1324        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1325        payload = {"comment": str(comment), "length": length}
    +1326        await self._request(
    +1327            RequestMethod.POST,
    +1328            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/",
    +1329            json=payload,
    +1330            auth=access_token,
    +1331        )
     
    @@ -27599,20 +22546,20 @@
    Other Parameters
    -
    1345    async def unban_clan_member(
    -1346        self,
    -1347        access_token: str,
    -1348        /,
    -1349        group_id: int,
    -1350        membership_id: int,
    -1351        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1352    ) -> None:
    -1353        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1354        await self._request(
    -1355            RequestMethod.POST,
    -1356            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/",
    -1357            auth=access_token,
    -1358        )
    +            
    1333    async def unban_clan_member(
    +1334        self,
    +1335        access_token: str,
    +1336        /,
    +1337        group_id: int,
    +1338        membership_id: int,
    +1339        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1340    ) -> None:
    +1341        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1342        await self._request(
    +1343            RequestMethod.POST,
    +1344            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/",
    +1345            auth=access_token,
    +1346        )
     
    @@ -27651,22 +22598,22 @@
    Parameters
    -
    1360    async def kick_clan_member(
    -1361        self,
    -1362        access_token: str,
    -1363        /,
    -1364        group_id: int,
    -1365        membership_id: int,
    -1366        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1367    ) -> typedefs.JSONObject:
    -1368        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1369        resp = await self._request(
    -1370            RequestMethod.POST,
    -1371            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/",
    -1372            auth=access_token,
    -1373        )
    -1374        assert isinstance(resp, dict)
    -1375        return resp
    +            
    1348    async def kick_clan_member(
    +1349        self,
    +1350        access_token: str,
    +1351        /,
    +1352        group_id: int,
    +1353        membership_id: int,
    +1354        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1355    ) -> typedefs.JSONObject:
    +1356        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1357        resp = await self._request(
    +1358            RequestMethod.POST,
    +1359            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/",
    +1360            auth=access_token,
    +1361        )
    +1362        assert isinstance(resp, dict)
    +1363        return resp
     
    @@ -27711,58 +22658,58 @@
    Returns
    -
    1377    async def edit_clan(
    -1378        self,
    -1379        access_token: str,
    -1380        /,
    -1381        group_id: int,
    -1382        *,
    -1383        name: typedefs.NoneOr[str] = None,
    -1384        about: typedefs.NoneOr[str] = None,
    -1385        motto: typedefs.NoneOr[str] = None,
    -1386        theme: typedefs.NoneOr[str] = None,
    -1387        tags: typedefs.NoneOr[collections.Sequence[str]] = None,
    -1388        is_public: typedefs.NoneOr[bool] = None,
    -1389        locale: typedefs.NoneOr[str] = None,
    -1390        avatar_image_index: typedefs.NoneOr[int] = None,
    -1391        membership_option: typedefs.NoneOr[
    -1392            typedefs.IntAnd[enums.MembershipOption]
    -1393        ] = None,
    -1394        allow_chat: typedefs.NoneOr[bool] = None,
    -1395        chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None,
    -1396        call_sign: typedefs.NoneOr[str] = None,
    -1397        homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
    -1398        enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None,
    -1399        default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
    -1400        is_public_topic_admin: typedefs.NoneOr[bool] = None,
    -1401    ) -> None:
    -1402        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1403        payload = {
    -1404            "name": name,
    -1405            "about": about,
    -1406            "motto": motto,
    -1407            "theme": theme,
    -1408            "tags": tags,
    -1409            "isPublic": is_public,
    -1410            "avatarImageIndex": avatar_image_index,
    -1411            "isPublicTopicAdminOnly": is_public_topic_admin,
    -1412            "allowChat": allow_chat,
    -1413            "chatSecurity": chat_security,
    -1414            "callsign": call_sign,
    -1415            "homepage": homepage,
    -1416            "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins,
    -1417            "defaultPublicity": default_publicity,
    -1418            "locale": locale,
    -1419        }
    -1420        if membership_option is not None:
    -1421            payload["membershipOption"] = int(membership_option)
    -1422
    -1423        await self._request(
    -1424            RequestMethod.POST,
    -1425            f"GroupV2/{group_id}/Edit",
    -1426            json=payload,
    -1427            auth=access_token,
    -1428        )
    +            
    1365    async def edit_clan(
    +1366        self,
    +1367        access_token: str,
    +1368        /,
    +1369        group_id: int,
    +1370        *,
    +1371        name: typedefs.NoneOr[str] = None,
    +1372        about: typedefs.NoneOr[str] = None,
    +1373        motto: typedefs.NoneOr[str] = None,
    +1374        theme: typedefs.NoneOr[str] = None,
    +1375        tags: typedefs.NoneOr[collections.Sequence[str]] = None,
    +1376        is_public: typedefs.NoneOr[bool] = None,
    +1377        locale: typedefs.NoneOr[str] = None,
    +1378        avatar_image_index: typedefs.NoneOr[int] = None,
    +1379        membership_option: typedefs.NoneOr[
    +1380            typedefs.IntAnd[enums.MembershipOption]
    +1381        ] = None,
    +1382        allow_chat: typedefs.NoneOr[bool] = None,
    +1383        chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None,
    +1384        call_sign: typedefs.NoneOr[str] = None,
    +1385        homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
    +1386        enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None,
    +1387        default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
    +1388        is_public_topic_admin: typedefs.NoneOr[bool] = None,
    +1389    ) -> None:
    +1390        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1391        payload = {
    +1392            "name": name,
    +1393            "about": about,
    +1394            "motto": motto,
    +1395            "theme": theme,
    +1396            "tags": tags,
    +1397            "isPublic": is_public,
    +1398            "avatarImageIndex": avatar_image_index,
    +1399            "isPublicTopicAdminOnly": is_public_topic_admin,
    +1400            "allowChat": allow_chat,
    +1401            "chatSecurity": chat_security,
    +1402            "callsign": call_sign,
    +1403            "homepage": homepage,
    +1404            "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins,
    +1405            "defaultPublicity": default_publicity,
    +1406            "locale": locale,
    +1407        }
    +1408        if membership_option is not None:
    +1409            payload["membershipOption"] = int(membership_option)
    +1410
    +1411        await self._request(
    +1412            RequestMethod.POST,
    +1413            f"GroupV2/{group_id}/Edit",
    +1414            json=payload,
    +1415            auth=access_token,
    +1416        )
     
    @@ -27842,35 +22789,35 @@
    Other Parameters
    -
    1430    async def edit_clan_options(
    -1431        self,
    -1432        access_token: str,
    -1433        /,
    -1434        group_id: int,
    -1435        *,
    -1436        invite_permissions_override: typedefs.NoneOr[bool] = None,
    -1437        update_culture_permissionOverride: typedefs.NoneOr[bool] = None,
    -1438        host_guided_game_permission_override: typedefs.NoneOr[
    -1439            typing.Literal[0, 1, 2]
    -1440        ] = None,
    -1441        update_banner_permission_override: typedefs.NoneOr[bool] = None,
    -1442        join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None,
    -1443    ) -> None:
    -1444
    -1445        payload = {
    -1446            "InvitePermissionOverride": invite_permissions_override,
    -1447            "UpdateCulturePermissionOverride": update_culture_permissionOverride,
    -1448            "HostGuidedGamePermissionOverride": host_guided_game_permission_override,
    -1449            "UpdateBannerPermissionOverride": update_banner_permission_override,
    -1450            "JoinLevel": int(join_level) if join_level else None,
    -1451        }
    -1452
    -1453        await self._request(
    -1454            RequestMethod.POST,
    -1455            f"GroupV2/{group_id}/EditFounderOptions",
    -1456            json=payload,
    -1457            auth=access_token,
    -1458        )
    +            
    1418    async def edit_clan_options(
    +1419        self,
    +1420        access_token: str,
    +1421        /,
    +1422        group_id: int,
    +1423        *,
    +1424        invite_permissions_override: typedefs.NoneOr[bool] = None,
    +1425        update_culture_permissionOverride: typedefs.NoneOr[bool] = None,
    +1426        host_guided_game_permission_override: typedefs.NoneOr[
    +1427            typing.Literal[0, 1, 2]
    +1428        ] = None,
    +1429        update_banner_permission_override: typedefs.NoneOr[bool] = None,
    +1430        join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None,
    +1431    ) -> None:
    +1432
    +1433        payload = {
    +1434            "InvitePermissionOverride": invite_permissions_override,
    +1435            "UpdateCulturePermissionOverride": update_culture_permissionOverride,
    +1436            "HostGuidedGamePermissionOverride": host_guided_game_permission_override,
    +1437            "UpdateBannerPermissionOverride": update_banner_permission_override,
    +1438            "JoinLevel": int(join_level) if join_level else None,
    +1439        }
    +1440
    +1441        await self._request(
    +1442            RequestMethod.POST,
    +1443            f"GroupV2/{group_id}/EditFounderOptions",
    +1444            json=payload,
    +1445            auth=access_token,
    +1446        )
     
    @@ -27917,7 +22864,7 @@
    Other Parameters
    Default is False for clans, True for groups.
  • join_level (aiobungie.ClanMemberType): Level to join a member at when accepting an invite, application, or joining an open clan. -Default is aiobungie.ClanMemberType.BEGINNER
  • +Default is aiobungie.ClanMemberType.BEGINNER
    @@ -27934,15 +22881,15 @@
    Other Parameters
    -
    1460    async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject:
    -1461        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1462        resp = await self._request(
    -1463            RequestMethod.GET,
    -1464            "Social/Friends/",
    -1465            auth=access_token,
    -1466        )
    -1467        assert isinstance(resp, dict)
    -1468        return resp
    +            
    1448    async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject:
    +1449        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1450        resp = await self._request(
    +1451            RequestMethod.GET,
    +1452            "Social/Friends/",
    +1453            auth=access_token,
    +1454        )
    +1455        assert isinstance(resp, dict)
    +1456        return resp
     
    @@ -27981,15 +22928,15 @@
    Returns
    -
    1470    async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject:
    -1471        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1472        resp = await self._request(
    -1473            RequestMethod.GET,
    -1474            "Social/Friends/Requests",
    -1475            auth=access_token,
    -1476        )
    -1477        assert isinstance(resp, dict)
    -1478        return resp
    +            
    1458    async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject:
    +1459        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1460        resp = await self._request(
    +1461            RequestMethod.GET,
    +1462            "Social/Friends/Requests",
    +1463            auth=access_token,
    +1464        )
    +1465        assert isinstance(resp, dict)
    +1466        return resp
     
    @@ -28028,13 +22975,13 @@
    Returns
    -
    1480    async def accept_friend_request(self, access_token: str, /, member_id: int) -> None:
    -1481        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1482        await self._request(
    -1483            RequestMethod.POST,
    -1484            f"Social/Friends/Requests/Accept/{member_id}",
    -1485            auth=access_token,
    -1486        )
    +            
    1468    async def accept_friend_request(self, access_token: str, /, member_id: int) -> None:
    +1469        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1470        await self._request(
    +1471            RequestMethod.POST,
    +1472            f"Social/Friends/Requests/Accept/{member_id}",
    +1473            auth=access_token,
    +1474        )
     
    @@ -28069,13 +23016,13 @@
    Parameters
    -
    1488    async def send_friend_request(self, access_token: str, /, member_id: int) -> None:
    -1489        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1490        await self._request(
    -1491            RequestMethod.POST,
    -1492            f"Social/Friends/Add/{member_id}",
    -1493            auth=access_token,
    -1494        )
    +            
    1476    async def send_friend_request(self, access_token: str, /, member_id: int) -> None:
    +1477        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1478        await self._request(
    +1479            RequestMethod.POST,
    +1480            f"Social/Friends/Add/{member_id}",
    +1481            auth=access_token,
    +1482        )
     
    @@ -28110,15 +23057,15 @@
    Parameters
    -
    1496    async def decline_friend_request(
    -1497        self, access_token: str, /, member_id: int
    -1498    ) -> None:
    -1499        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1500        await self._request(
    -1501            RequestMethod.POST,
    -1502            f"Social/Friends/Requests/Decline/{member_id}",
    -1503            auth=access_token,
    -1504        )
    +            
    1484    async def decline_friend_request(
    +1485        self, access_token: str, /, member_id: int
    +1486    ) -> None:
    +1487        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1488        await self._request(
    +1489            RequestMethod.POST,
    +1490            f"Social/Friends/Requests/Decline/{member_id}",
    +1491            auth=access_token,
    +1492        )
     
    @@ -28153,13 +23100,13 @@
    Parameters
    -
    1506    async def remove_friend(self, access_token: str, /, member_id: int) -> None:
    -1507        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1508        await self._request(
    -1509            RequestMethod.POST,
    -1510            f"Social/Friends/Remove/{member_id}",
    -1511            auth=access_token,
    -1512        )
    +            
    1494    async def remove_friend(self, access_token: str, /, member_id: int) -> None:
    +1495        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1496        await self._request(
    +1497            RequestMethod.POST,
    +1498            f"Social/Friends/Remove/{member_id}",
    +1499            auth=access_token,
    +1500        )
     
    @@ -28194,13 +23141,13 @@
    Parameters
    -
    1514    async def remove_friend_request(self, access_token: str, /, member_id: int) -> None:
    -1515        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1516        await self._request(
    -1517            RequestMethod.POST,
    -1518            f"Social/Friends/Requests/Remove/{member_id}",
    -1519            auth=access_token,
    -1520        )
    +            
    1502    async def remove_friend_request(self, access_token: str, /, member_id: int) -> None:
    +1503        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1504        await self._request(
    +1505            RequestMethod.POST,
    +1506            f"Social/Friends/Requests/Remove/{member_id}",
    +1507            auth=access_token,
    +1508        )
     
    @@ -28232,20 +23179,20 @@
    Parameters
    -
    1522    async def approve_all_pending_group_users(
    -1523        self,
    -1524        access_token: str,
    -1525        /,
    -1526        group_id: int,
    -1527        message: undefined.UndefinedOr[str] = undefined.Undefined,
    -1528    ) -> None:
    -1529        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1530        await self._request(
    -1531            RequestMethod.POST,
    -1532            f"GroupV2/{group_id}/Members/ApproveAll",
    -1533            auth=access_token,
    -1534            json={"message": str(message)},
    -1535        )
    +            
    1510    async def approve_all_pending_group_users(
    +1511        self,
    +1512        access_token: str,
    +1513        /,
    +1514        group_id: int,
    +1515        message: undefined.UndefinedOr[str] = undefined.Undefined,
    +1516    ) -> None:
    +1517        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1518        await self._request(
    +1519            RequestMethod.POST,
    +1520            f"GroupV2/{group_id}/Members/ApproveAll",
    +1521            auth=access_token,
    +1522            json={"message": str(message)},
    +1523        )
     
    @@ -28287,21 +23234,21 @@
    Other Parameters
    -
    1537    async def deny_all_pending_group_users(
    -1538        self,
    -1539        access_token: str,
    -1540        /,
    -1541        group_id: int,
    -1542        *,
    -1543        message: undefined.UndefinedOr[str] = undefined.Undefined,
    -1544    ) -> None:
    -1545        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1546        await self._request(
    -1547            RequestMethod.POST,
    -1548            f"GroupV2/{group_id}/Members/DenyAll",
    -1549            auth=access_token,
    -1550            json={"message": str(message)},
    -1551        )
    +            
    1525    async def deny_all_pending_group_users(
    +1526        self,
    +1527        access_token: str,
    +1528        /,
    +1529        group_id: int,
    +1530        *,
    +1531        message: undefined.UndefinedOr[str] = undefined.Undefined,
    +1532    ) -> None:
    +1533        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1534        await self._request(
    +1535            RequestMethod.POST,
    +1536            f"GroupV2/{group_id}/Members/DenyAll",
    +1537            auth=access_token,
    +1538            json={"message": str(message)},
    +1539        )
     
    @@ -28343,23 +23290,23 @@
    Other Parameters
    -
    1553    async def add_optional_conversation(
    -1554        self,
    -1555        access_token: str,
    -1556        /,
    -1557        group_id: int,
    -1558        *,
    -1559        name: undefined.UndefinedOr[str] = undefined.Undefined,
    -1560        security: typing.Literal[0, 1] = 0,
    -1561    ) -> None:
    -1562        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1563        payload = {"chatName": str(name), "chatSecurity": security}
    -1564        await self._request(
    -1565            RequestMethod.POST,
    -1566            f"GroupV2/{group_id}/OptionalConversations/Add",
    -1567            json=payload,
    -1568            auth=access_token,
    -1569        )
    +            
    1541    async def add_optional_conversation(
    +1542        self,
    +1543        access_token: str,
    +1544        /,
    +1545        group_id: int,
    +1546        *,
    +1547        name: undefined.UndefinedOr[str] = undefined.Undefined,
    +1548        security: typing.Literal[0, 1] = 0,
    +1549    ) -> None:
    +1550        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1551        payload = {"chatName": str(name), "chatSecurity": security}
    +1552        await self._request(
    +1553            RequestMethod.POST,
    +1554            f"GroupV2/{group_id}/OptionalConversations/Add",
    +1555            json=payload,
    +1556            auth=access_token,
    +1557        )
     
    @@ -28406,29 +23353,29 @@
    Other parameters
    -
    1571    async def edit_optional_conversation(
    -1572        self,
    -1573        access_token: str,
    -1574        /,
    -1575        group_id: int,
    -1576        conversation_id: int,
    -1577        *,
    -1578        name: undefined.UndefinedOr[str] = undefined.Undefined,
    -1579        security: typing.Literal[0, 1] = 0,
    -1580        enable_chat: bool = False,
    -1581    ) -> None:
    -1582        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1583        payload = {
    -1584            "chatEnabled": enable_chat,
    -1585            "chatName": str(name),
    -1586            "chatSecurity": security,
    -1587        }
    -1588        await self._request(
    -1589            RequestMethod.POST,
    -1590            f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}",
    -1591            json=payload,
    -1592            auth=access_token,
    -1593        )
    +            
    1559    async def edit_optional_conversation(
    +1560        self,
    +1561        access_token: str,
    +1562        /,
    +1563        group_id: int,
    +1564        conversation_id: int,
    +1565        *,
    +1566        name: undefined.UndefinedOr[str] = undefined.Undefined,
    +1567        security: typing.Literal[0, 1] = 0,
    +1568        enable_chat: bool = False,
    +1569    ) -> None:
    +1570        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1571        payload = {
    +1572            "chatEnabled": enable_chat,
    +1573            "chatName": str(name),
    +1574            "chatSecurity": security,
    +1575        }
    +1576        await self._request(
    +1577            RequestMethod.POST,
    +1578            f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}",
    +1579            json=payload,
    +1580            auth=access_token,
    +1581        )
     
    @@ -28481,33 +23428,33 @@
    Other parameters
    -
    1595    async def transfer_item(
    -1596        self,
    -1597        access_token: str,
    -1598        /,
    -1599        item_id: int,
    -1600        item_hash: int,
    -1601        character_id: int,
    -1602        member_type: typedefs.IntAnd[enums.MembershipType],
    -1603        *,
    -1604        stack_size: int = 1,
    -1605        vault: bool = False,
    -1606    ) -> None:
    -1607        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1608        payload = {
    -1609            "characterId": character_id,
    -1610            "membershipType": int(member_type),
    -1611            "itemId": item_id,
    -1612            "itemReferenceHash": item_hash,
    -1613            "stackSize": stack_size,
    -1614            "transferToVault": vault,
    -1615        }
    -1616        await self._request(
    -1617            RequestMethod.POST,
    -1618            "Destiny2/Actions/Items/TransferItem",
    -1619            json=payload,
    -1620            auth=access_token,
    -1621        )
    +            
    1583    async def transfer_item(
    +1584        self,
    +1585        access_token: str,
    +1586        /,
    +1587        item_id: int,
    +1588        item_hash: int,
    +1589        character_id: int,
    +1590        member_type: typedefs.IntAnd[enums.MembershipType],
    +1591        *,
    +1592        stack_size: int = 1,
    +1593        vault: bool = False,
    +1594    ) -> None:
    +1595        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1596        payload = {
    +1597            "characterId": character_id,
    +1598            "membershipType": int(member_type),
    +1599            "itemId": item_id,
    +1600            "itemReferenceHash": item_hash,
    +1601            "stackSize": stack_size,
    +1602            "transferToVault": vault,
    +1603        }
    +1604        await self._request(
    +1605            RequestMethod.POST,
    +1606            "Destiny2/Actions/Items/TransferItem",
    +1607            json=payload,
    +1608            auth=access_token,
    +1609        )
     
    @@ -28558,33 +23505,33 @@
    Other Parameters
    -
    1623    async def pull_item(
    -1624        self,
    -1625        access_token: str,
    -1626        /,
    -1627        item_id: int,
    -1628        item_hash: int,
    -1629        character_id: int,
    -1630        member_type: typedefs.IntAnd[enums.MembershipType],
    -1631        *,
    -1632        stack_size: int = 1,
    -1633        vault: bool = False,
    -1634    ) -> None:
    -1635        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1636        payload = {
    -1637            "characterId": character_id,
    -1638            "membershipType": int(member_type),
    -1639            "itemId": item_id,
    -1640            "itemReferenceHash": item_hash,
    -1641            "stackSize": stack_size,
    -1642            "transferToVault": vault,
    -1643        }
    -1644        await self._request(
    -1645            RequestMethod.POST,
    -1646            "Destiny2/Actions/Items/PullFromPostmaster",
    -1647            json=payload,
    -1648            auth=access_token,
    -1649        )
    +            
    1611    async def pull_item(
    +1612        self,
    +1613        access_token: str,
    +1614        /,
    +1615        item_id: int,
    +1616        item_hash: int,
    +1617        character_id: int,
    +1618        member_type: typedefs.IntAnd[enums.MembershipType],
    +1619        *,
    +1620        stack_size: int = 1,
    +1621        vault: bool = False,
    +1622    ) -> None:
    +1623        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1624        payload = {
    +1625            "characterId": character_id,
    +1626            "membershipType": int(member_type),
    +1627            "itemId": item_id,
    +1628            "itemReferenceHash": item_hash,
    +1629            "stackSize": stack_size,
    +1630            "transferToVault": vault,
    +1631        }
    +1632        await self._request(
    +1633            RequestMethod.POST,
    +1634            "Destiny2/Actions/Items/PullFromPostmaster",
    +1635            json=payload,
    +1636            auth=access_token,
    +1637        )
     
    @@ -28629,35 +23576,35 @@
    Other Parameters
    async def - fetch_fireteams( self, activity_type: Union[int, aiobungie.FireteamActivity], *, platform: Union[int, aiobungie.FireteamPlatform] = <FireteamPlatform.ANY: 0>, language: Union[aiobungie.FireteamLanguage, str] = <FireteamLanguage.ALL: >, date_range: Union[int, aiobungie.FireteamDate] = <FireteamDate.ALL: 0>, page: int = 0, slots_filter: int = 0) -> dict[str, typing.Any]: + fetch_fireteams( self, activity_type: Union[int, aiobungie.FireteamActivity], *, platform: Union[int, aiobungie.FireteamPlatform] = <FireteamPlatform.ANY: 0>, language: Union[aiobungie.FireteamLanguage, str] = <FireteamLanguage.ALL: >, date_range: Union[int, aiobungie.FireteamDate] = <FireteamDate.ALL: 0>, page: int = 0, slots_filter: int = 0) -> dict[str, typing.Any]:
    -
    1651    async def fetch_fireteams(
    -1652        self,
    -1653        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    -1654        *,
    -1655        platform: typedefs.IntAnd[
    -1656            fireteams.FireteamPlatform
    -1657        ] = fireteams.FireteamPlatform.ANY,
    -1658        language: typing.Union[
    -1659            fireteams.FireteamLanguage, str
    -1660        ] = fireteams.FireteamLanguage.ALL,
    -1661        date_range: typedefs.IntAnd[
    -1662            fireteams.FireteamDate
    -1663        ] = fireteams.FireteamDate.ALL,
    -1664        page: int = 0,
    -1665        slots_filter: int = 0,
    -1666    ) -> typedefs.JSONObject:
    -1667        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1668        resp = await self._request(
    -1669            RequestMethod.GET,
    -1670            f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}",  # noqa: E501 Line too long
    -1671        )
    -1672        assert isinstance(resp, dict)
    -1673        return resp
    +            
    1639    async def fetch_fireteams(
    +1640        self,
    +1641        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    +1642        *,
    +1643        platform: typedefs.IntAnd[
    +1644            fireteams.FireteamPlatform
    +1645        ] = fireteams.FireteamPlatform.ANY,
    +1646        language: typing.Union[
    +1647            fireteams.FireteamLanguage, str
    +1648        ] = fireteams.FireteamLanguage.ALL,
    +1649        date_range: typedefs.IntAnd[
    +1650            fireteams.FireteamDate
    +1651        ] = fireteams.FireteamDate.ALL,
    +1652        page: int = 0,
    +1653        slots_filter: int = 0,
    +1654    ) -> typedefs.JSONObject:
    +1655        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1656        resp = await self._request(
    +1657            RequestMethod.GET,
    +1658            f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}",  # noqa: E501 Line too long
    +1659        )
    +1660        assert isinstance(resp, dict)
    +1661        return resp
     
    @@ -28680,7 +23627,7 @@
    Other Parameters
    A locale language to filter the used language in that fireteam. Defaults to aiobungie.crates.FireteamLanguage.ALL
  • date_range (aiobungie.typedefs.IntAnd[aiobungie.FireteamDate]): -An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • +An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • page (int): The page number. By default its 0 which returns all available activities.
  • slots_filter (int): @@ -28701,36 +23648,36 @@
    Returns
    async def - fetch_avaliable_clan_fireteams( self, access_token: str, group_id: int, activity_type: Union[int, aiobungie.FireteamActivity], *, platform: Union[int, aiobungie.FireteamPlatform], language: Union[aiobungie.FireteamLanguage, str], date_range: Union[int, aiobungie.FireteamDate] = <FireteamDate.ALL: 0>, page: int = 0, public_only: bool = False, slots_filter: int = 0) -> dict[str, typing.Any]: + fetch_avaliable_clan_fireteams( self, access_token: str, group_id: int, activity_type: Union[int, aiobungie.FireteamActivity], *, platform: Union[int, aiobungie.FireteamPlatform], language: Union[aiobungie.FireteamLanguage, str], date_range: Union[int, aiobungie.FireteamDate] = <FireteamDate.ALL: 0>, page: int = 0, public_only: bool = False, slots_filter: int = 0) -> dict[str, typing.Any]:
    -
    1675    async def fetch_avaliable_clan_fireteams(
    -1676        self,
    -1677        access_token: str,
    -1678        group_id: int,
    -1679        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    -1680        *,
    -1681        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    -1682        language: typing.Union[fireteams.FireteamLanguage, str],
    -1683        date_range: typedefs.IntAnd[
    -1684            fireteams.FireteamDate
    -1685        ] = fireteams.FireteamDate.ALL,
    -1686        page: int = 0,
    -1687        public_only: bool = False,
    -1688        slots_filter: int = 0,
    -1689    ) -> typedefs.JSONObject:
    -1690        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1691        resp = await self._request(
    -1692            RequestMethod.GET,
    -1693            f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}",  # noqa: E501
    -1694            json={"langFilter": str(language)},
    -1695            auth=access_token,
    -1696        )
    -1697        assert isinstance(resp, dict)
    -1698        return resp
    +            
    1663    async def fetch_avaliable_clan_fireteams(
    +1664        self,
    +1665        access_token: str,
    +1666        group_id: int,
    +1667        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    +1668        *,
    +1669        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    +1670        language: typing.Union[fireteams.FireteamLanguage, str],
    +1671        date_range: typedefs.IntAnd[
    +1672            fireteams.FireteamDate
    +1673        ] = fireteams.FireteamDate.ALL,
    +1674        page: int = 0,
    +1675        public_only: bool = False,
    +1676        slots_filter: int = 0,
    +1677    ) -> typedefs.JSONObject:
    +1678        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1679        resp = await self._request(
    +1680            RequestMethod.GET,
    +1681            f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}",  # noqa: E501
    +1682            json={"langFilter": str(language)},
    +1683            auth=access_token,
    +1684        )
    +1685        assert isinstance(resp, dict)
    +1686        return resp
     
    @@ -28763,7 +23710,7 @@
    Other Parameters
    A locale language to filter the used language in that fireteam. Defaults to aiobungie.crates.FireteamLanguage.ALL
  • date_range (aiobungie.typedefs.IntAnd[aiobungie.FireteamDate]): -An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • +An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • page (int): The page number. By default its 0 which returns all available activities.
  • public_only (bool): @@ -28792,17 +23739,17 @@
    Returns
  • -
    1700    async def fetch_clan_fireteam(
    -1701        self, access_token: str, fireteam_id: int, group_id: int
    -1702    ) -> typedefs.JSONObject:
    -1703        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1704        resp = await self._request(
    -1705            RequestMethod.GET,
    -1706            f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}",
    -1707            auth=access_token,
    -1708        )
    -1709        assert isinstance(resp, dict)
    -1710        return resp
    +            
    1688    async def fetch_clan_fireteam(
    +1689        self, access_token: str, fireteam_id: int, group_id: int
    +1690    ) -> typedefs.JSONObject:
    +1691        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1692        resp = await self._request(
    +1693            RequestMethod.GET,
    +1694            f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}",
    +1695            auth=access_token,
    +1696        )
    +1697        assert isinstance(resp, dict)
    +1698        return resp
     
    @@ -28845,27 +23792,27 @@
    Returns
    -
    1712    async def fetch_my_clan_fireteams(
    -1713        self,
    -1714        access_token: str,
    -1715        group_id: int,
    -1716        *,
    -1717        include_closed: bool = True,
    -1718        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    -1719        language: typing.Union[fireteams.FireteamLanguage, str],
    -1720        filtered: bool = True,
    -1721        page: int = 0,
    -1722    ) -> typedefs.JSONObject:
    -1723        payload = {"groupFilter": filtered, "langFilter": str(language)}
    -1724        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1725        resp = await self._request(
    -1726            RequestMethod.GET,
    -1727            f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}",
    -1728            json=payload,
    -1729            auth=access_token,
    -1730        )
    -1731        assert isinstance(resp, dict)
    -1732        return resp
    +            
    1700    async def fetch_my_clan_fireteams(
    +1701        self,
    +1702        access_token: str,
    +1703        group_id: int,
    +1704        *,
    +1705        include_closed: bool = True,
    +1706        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    +1707        language: typing.Union[fireteams.FireteamLanguage, str],
    +1708        filtered: bool = True,
    +1709        page: int = 0,
    +1710    ) -> typedefs.JSONObject:
    +1711        payload = {"groupFilter": filtered, "langFilter": str(language)}
    +1712        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1713        resp = await self._request(
    +1714            RequestMethod.GET,
    +1715            f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}",
    +1716            json=payload,
    +1717            auth=access_token,
    +1718        )
    +1719        assert isinstance(resp, dict)
    +1720        return resp
     
    @@ -28925,17 +23872,17 @@
    Returns
    -
    1734    async def fetch_private_clan_fireteams(
    -1735        self, access_token: str, group_id: int, /
    -1736    ) -> int:
    -1737        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1738        resp = await self._request(
    -1739            RequestMethod.GET,
    -1740            f"Fireteam/Clan/{group_id}/ActiveCount",
    -1741            auth=access_token,
    -1742        )
    -1743        assert isinstance(resp, int)
    -1744        return resp
    +            
    1722    async def fetch_private_clan_fireteams(
    +1723        self, access_token: str, group_id: int, /
    +1724    ) -> int:
    +1725        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1726        resp = await self._request(
    +1727            RequestMethod.GET,
    +1728            f"Fireteam/Clan/{group_id}/ActiveCount",
    +1729            auth=access_token,
    +1730        )
    +1731        assert isinstance(resp, int)
    +1732        return resp
     
    @@ -28976,13 +23923,13 @@
    Returns
    -
    1746    async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject:
    -1747        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1748        resp = await self._request(
    -1749            RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}"
    -1750        )
    -1751        assert isinstance(resp, dict)
    -1752        return resp
    +            
    1734    async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject:
    +1735        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1736        resp = await self._request(
    +1737            RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}"
    +1738        )
    +1739        assert isinstance(resp, dict)
    +1740        return resp
     
    @@ -29015,17 +23962,17 @@
    Returns
    -
    1754    async def search_entities(
    -1755        self, name: str, entity_type: str, *, page: int = 0
    -1756    ) -> typedefs.JSONObject:
    -1757        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1758        resp = await self._request(
    -1759            RequestMethod.GET,
    -1760            f"Destiny2/Armory/Search/{entity_type}/{name}/",
    -1761            json={"page": page},
    -1762        )
    -1763        assert isinstance(resp, dict)
    -1764        return resp
    +            
    1742    async def search_entities(
    +1743        self, name: str, entity_type: str, *, page: int = 0
    +1744    ) -> typedefs.JSONObject:
    +1745        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1746        resp = await self._request(
    +1747            RequestMethod.GET,
    +1748            f"Destiny2/Armory/Search/{entity_type}/{name}/",
    +1749            json={"page": page},
    +1750        )
    +1751        assert isinstance(resp, dict)
    +1752        return resp
     
    @@ -29067,19 +24014,19 @@
    Returns
    -
    1766    async def fetch_unique_weapon_history(
    -1767        self,
    -1768        membership_id: int,
    -1769        character_id: int,
    -1770        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1771    ) -> typedefs.JSONObject:
    -1772        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1773        resp = await self._request(
    -1774            RequestMethod.GET,
    -1775            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/",
    -1776        )
    -1777        assert isinstance(resp, dict)
    -1778        return resp
    +            
    1754    async def fetch_unique_weapon_history(
    +1755        self,
    +1756        membership_id: int,
    +1757        character_id: int,
    +1758        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1759    ) -> typedefs.JSONObject:
    +1760        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1761        resp = await self._request(
    +1762            RequestMethod.GET,
    +1763            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/",
    +1764        )
    +1765        assert isinstance(resp, dict)
    +1766        return resp
     
    @@ -29116,21 +24063,21 @@
    Returns
    -
    1780    async def fetch_item(
    -1781        self,
    -1782        member_id: int,
    -1783        item_id: int,
    -1784        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1785        components: list[enums.ComponentType],
    -1786    ) -> typedefs.JSONObject:
    -1787        collector = _collect_components(components)
    -1788        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1789        resp = await self._request(
    -1790            RequestMethod.GET,
    -1791            f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}",
    -1792        )
    -1793        assert isinstance(resp, dict)
    -1794        return resp
    +            
    1768    async def fetch_item(
    +1769        self,
    +1770        member_id: int,
    +1771        item_id: int,
    +1772        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1773        components: list[enums.ComponentType],
    +1774    ) -> typedefs.JSONObject:
    +1775        collector = _collect_components(components)
    +1776        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1777        resp = await self._request(
    +1778            RequestMethod.GET,
    +1779            f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}",
    +1780        )
    +1781        assert isinstance(resp, dict)
    +1782        return resp
     
    @@ -29169,13 +24116,13 @@
    Returns
    -
    1796    async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject:
    -1797        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1798        resp = await self._request(
    -1799            RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/"
    -1800        )
    -1801        assert isinstance(resp, dict)
    -1802        return resp
    +            
    1784    async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject:
    +1785        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1786        resp = await self._request(
    +1787            RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/"
    +1788        )
    +1789        assert isinstance(resp, dict)
    +1790        return resp
     
    @@ -29208,13 +24155,13 @@
    Returns
    -
    1804    async def fetch_available_locales(self) -> typedefs.JSONObject:
    -1805        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1806        resp = await self._request(
    -1807            RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/"
    -1808        )
    -1809        assert isinstance(resp, dict)
    -1810        return resp
    +            
    1792    async def fetch_available_locales(self) -> typedefs.JSONObject:
    +1793        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1794        resp = await self._request(
    +1795            RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/"
    +1796        )
    +1797        assert isinstance(resp, dict)
    +1798        return resp
     
    @@ -29240,11 +24187,11 @@
    Returns
    -
    1812    async def fetch_common_settings(self) -> typedefs.JSONObject:
    -1813        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1814        resp = await self._request(RequestMethod.GET, "Settings")
    -1815        assert isinstance(resp, dict)
    -1816        return resp
    +            
    1800    async def fetch_common_settings(self) -> typedefs.JSONObject:
    +1801        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1802        resp = await self._request(RequestMethod.GET, "Settings")
    +1803        assert isinstance(resp, dict)
    +1804        return resp
     
    @@ -29270,11 +24217,11 @@
    Returns
    -
    1818    async def fetch_user_systems_overrides(self) -> typedefs.JSONObject:
    -1819        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1820        resp = await self._request(RequestMethod.GET, "UserSystemOverrides")
    -1821        assert isinstance(resp, dict)
    -1822        return resp
    +            
    1806    async def fetch_user_systems_overrides(self) -> typedefs.JSONObject:
    +1807        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1808        resp = await self._request(RequestMethod.GET, "UserSystemOverrides")
    +1809        assert isinstance(resp, dict)
    +1810        return resp
     
    @@ -29300,15 +24247,15 @@
    Returns
    -
    1824    async def fetch_global_alerts(
    -1825        self, *, include_streaming: bool = False
    -1826    ) -> typedefs.JSONArray:
    -1827        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1828        resp = await self._request(
    -1829            RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}"
    -1830        )
    -1831        assert isinstance(resp, list)
    -1832        return resp
    +            
    1812    async def fetch_global_alerts(
    +1813        self, *, include_streaming: bool = False
    +1814    ) -> typedefs.JSONArray:
    +1815        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1816        resp = await self._request(
    +1817            RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}"
    +1818        )
    +1819        assert isinstance(resp, list)
    +1820        return resp
     
    @@ -29341,31 +24288,31 @@
    Returns
    -
    1834    async def awainitialize_request(
    -1835        self,
    -1836        access_token: str,
    -1837        type: typing.Literal[0, 1],
    -1838        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1839        /,
    -1840        *,
    -1841        affected_item_id: typing.Optional[int] = None,
    -1842        character_id: typing.Optional[int] = None,
    -1843    ) -> typedefs.JSONObject:
    -1844        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1845
    -1846        body = {"type": type, "membershipType": int(membership_type)}
    -1847
    -1848        if affected_item_id is not None:
    -1849            body["affectedItemId"] = affected_item_id
    -1850
    -1851        if character_id is not None:
    -1852            body["characterId"] = character_id
    -1853
    -1854        resp = await self._request(
    -1855            RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token
    -1856        )
    -1857        assert isinstance(resp, dict)
    -1858        return resp
    +            
    1822    async def awainitialize_request(
    +1823        self,
    +1824        access_token: str,
    +1825        type: typing.Literal[0, 1],
    +1826        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1827        /,
    +1828        *,
    +1829        affected_item_id: typing.Optional[int] = None,
    +1830        character_id: typing.Optional[int] = None,
    +1831    ) -> typedefs.JSONObject:
    +1832        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1833
    +1834        body = {"type": type, "membershipType": int(membership_type)}
    +1835
    +1836        if affected_item_id is not None:
    +1837            body["affectedItemId"] = affected_item_id
    +1838
    +1839        if character_id is not None:
    +1840            body["characterId"] = character_id
    +1841
    +1842        resp = await self._request(
    +1843            RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token
    +1844        )
    +1845        assert isinstance(resp, dict)
    +1846        return resp
     
    @@ -29419,17 +24366,17 @@
    Returns
    -
    1860    async def awaget_action_token(
    -1861        self, access_token: str, correlation_id: str, /
    -1862    ) -> typedefs.JSONObject:
    -1863        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1864        resp = await self._request(
    -1865            RequestMethod.POST,
    -1866            f"Destiny2/Awa/GetActionToken/{correlation_id}",
    -1867            auth=access_token,
    -1868        )
    -1869        assert isinstance(resp, dict)
    -1870        return resp
    +            
    1848    async def awaget_action_token(
    +1849        self, access_token: str, correlation_id: str, /
    +1850    ) -> typedefs.JSONObject:
    +1851        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1852        resp = await self._request(
    +1853            RequestMethod.POST,
    +1854            f"Destiny2/Awa/GetActionToken/{correlation_id}",
    +1855            auth=access_token,
    +1856        )
    +1857        assert isinstance(resp, dict)
    +1858        return resp
     
    @@ -29470,25 +24417,25 @@
    Returns
    -
    1872    async def awa_provide_authorization_result(
    -1873        self,
    -1874        access_token: str,
    -1875        selection: int,
    -1876        correlation_id: str,
    -1877        nonce: collections.MutableSequence[typing.Union[str, bytes]],
    -1878    ) -> int:
    -1879        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1880
    -1881        body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce}
    -1882
    -1883        resp = await self._request(
    -1884            RequestMethod.POST,
    -1885            "Destiny2/Awa/AwaProvideAuthorizationResult",
    -1886            json=body,
    -1887            auth=access_token,
    -1888        )
    -1889        assert isinstance(resp, int)
    -1890        return resp
    +            
    1860    async def awa_provide_authorization_result(
    +1861        self,
    +1862        access_token: str,
    +1863        selection: int,
    +1864        correlation_id: str,
    +1865        nonce: collections.MutableSequence[typing.Union[str, bytes]],
    +1866    ) -> int:
    +1867        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1868
    +1869        body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce}
    +1870
    +1871        resp = await self._request(
    +1872            RequestMethod.POST,
    +1873            "Destiny2/Awa/AwaProvideAuthorizationResult",
    +1874            json=body,
    +1875            auth=access_token,
    +1876        )
    +1877        assert isinstance(resp, int)
    +1878        return resp
     
    @@ -29533,33 +24480,33 @@
    Returns
    -
    1892    async def fetch_vendors(
    -1893        self,
    -1894        access_token: str,
    -1895        character_id: int,
    -1896        membership_id: int,
    -1897        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1898        /,
    -1899        components: list[enums.ComponentType],
    -1900        filter: typing.Optional[int] = None,
    -1901    ) -> typedefs.JSONObject:
    -1902        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1903        components_ = _collect_components(components)
    -1904        route = (
    -1905            f"Destiny2/{int(membership_type)}/Profile/{membership_id}"
    -1906            f"/Character/{character_id}/Vendors/?components={components_}"
    -1907        )
    -1908
    -1909        if filter is not None:
    -1910            route = route + f"&filter={filter}"
    -1911
    -1912        resp = await self._request(
    -1913            RequestMethod.GET,
    -1914            route,
    -1915            auth=access_token,
    -1916        )
    -1917        assert isinstance(resp, dict)
    -1918        return resp
    +            
    1880    async def fetch_vendors(
    +1881        self,
    +1882        access_token: str,
    +1883        character_id: int,
    +1884        membership_id: int,
    +1885        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1886        /,
    +1887        components: list[enums.ComponentType],
    +1888        filter: typing.Optional[int] = None,
    +1889    ) -> typedefs.JSONObject:
    +1890        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1891        components_ = _collect_components(components)
    +1892        route = (
    +1893            f"Destiny2/{int(membership_type)}/Profile/{membership_id}"
    +1894            f"/Character/{character_id}/Vendors/?components={components_}"
    +1895        )
    +1896
    +1897        if filter is not None:
    +1898            route = route + f"&filter={filter}"
    +1899
    +1900        resp = await self._request(
    +1901            RequestMethod.GET,
    +1902            route,
    +1903            auth=access_token,
    +1904        )
    +1905        assert isinstance(resp, dict)
    +1906        return resp
     
    @@ -29607,28 +24554,28 @@
    Returns
    -
    1920    async def fetch_vendor(
    -1921        self,
    -1922        access_token: str,
    -1923        character_id: int,
    -1924        membership_id: int,
    -1925        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1926        vendor_hash: int,
    -1927        /,
    -1928        components: list[enums.ComponentType],
    -1929    ) -> typedefs.JSONObject:
    -1930        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1931        components_ = _collect_components(components)
    -1932        resp = await self._request(
    -1933            RequestMethod.GET,
    -1934            (
    -1935                f"Platform/Destiny2/{int(membership_type)}/Profile/{membership_id}"
    -1936                f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}"
    -1937            ),
    -1938            auth=access_token,
    -1939        )
    -1940        assert isinstance(resp, dict)
    -1941        return resp
    +            
    1908    async def fetch_vendor(
    +1909        self,
    +1910        access_token: str,
    +1911        character_id: int,
    +1912        membership_id: int,
    +1913        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1914        vendor_hash: int,
    +1915        /,
    +1916        components: list[enums.ComponentType],
    +1917    ) -> typedefs.JSONObject:
    +1918        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1919        components_ = _collect_components(components)
    +1920        resp = await self._request(
    +1921            RequestMethod.GET,
    +1922            (
    +1923                f"Platform/Destiny2/{int(membership_type)}/Profile/{membership_id}"
    +1924                f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}"
    +1925            ),
    +1926            auth=access_token,
    +1927        )
    +1928        assert isinstance(resp, dict)
    +1929        return resp
     
    @@ -29671,24 +24618,24 @@
    Returns
    -
    1943    async def fetch_application_api_usage(
    -1944        self,
    -1945        access_token: str,
    -1946        application_id: int,
    -1947        /,
    -1948        *,
    -1949        start: typing.Optional[datetime.datetime] = None,
    -1950        end: typing.Optional[datetime.datetime] = None,
    -1951    ) -> typedefs.JSONObject:
    -1952
    -1953        end_date, start_date = time.parse_date_range(end, start)
    -1954        resp = await self._request(
    -1955            RequestMethod.GET,
    -1956            f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}",
    -1957            auth=access_token,
    -1958        )
    -1959        assert isinstance(resp, dict)
    -1960        return resp
    +            
    1931    async def fetch_application_api_usage(
    +1932        self,
    +1933        access_token: str,
    +1934        application_id: int,
    +1935        /,
    +1936        *,
    +1937        start: typing.Optional[datetime.datetime] = None,
    +1938        end: typing.Optional[datetime.datetime] = None,
    +1939    ) -> typedefs.JSONObject:
    +1940
    +1941        end_date, start_date = time.parse_date_range(end, start)
    +1942        resp = await self._request(
    +1943            RequestMethod.GET,
    +1944            f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}",
    +1945            auth=access_token,
    +1946        )
    +1947        assert isinstance(resp, dict)
    +1948        return resp
     
    @@ -29719,13 +24666,15 @@
    Other Parameters
    Example
    -
    import datetime
    +
    +
    import datetime
     
     # Fetch data from 2021 Dec 10th to 2021 Dec 20th
     await fetch_application_api_usage(
         start=datetime.datetime(2021, 12, 10), end=datetime.datetime(2021, 12, 20)
     )
    -
    +
    +
    Returns
    @@ -29747,10 +24696,10 @@
    Returns
    -
    1962    async def fetch_bungie_applications(self) -> typedefs.JSONArray:
    -1963        resp = await self._request(RequestMethod.GET, "App/FirstParty")
    -1964        assert isinstance(resp, list)
    -1965        return resp
    +            
    1950    async def fetch_bungie_applications(self) -> typedefs.JSONArray:
    +1951        resp = await self._request(RequestMethod.GET, "App/FirstParty")
    +1952        assert isinstance(resp, list)
    +1953        return resp
     
    @@ -29776,10 +24725,10 @@
    Returns
    -
    1967    async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject:
    -1968        resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/")
    -1969        assert isinstance(resp, dict)
    -1970        return resp
    +            
    1955    async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject:
    +1956        resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/")
    +1957        assert isinstance(resp, dict)
    +1958        return resp
     
    @@ -29797,16 +24746,16 @@
    Returns
    -
    1972    async def fetch_content_by_id(
    -1973        self, id: int, locale: str, /, *, head: bool = False
    -1974    ) -> typedefs.JSONObject:
    -1975        resp = await self._request(
    -1976            RequestMethod.GET,
    -1977            f"Content/GetContentById/{id}/{locale}/",
    -1978            json={"head": head},
    -1979        )
    -1980        assert isinstance(resp, dict)
    -1981        return resp
    +            
    1960    async def fetch_content_by_id(
    +1961        self, id: int, locale: str, /, *, head: bool = False
    +1962    ) -> typedefs.JSONObject:
    +1963        resp = await self._request(
    +1964            RequestMethod.GET,
    +1965            f"Content/GetContentById/{id}/{locale}/",
    +1966            json={"head": head},
    +1967        )
    +1968        assert isinstance(resp, dict)
    +1969        return resp
     
    @@ -29824,16 +24773,16 @@
    Returns
    -
    1983    async def fetch_content_by_tag_and_type(
    -1984        self, locale: str, tag: str, type: str, *, head: bool = False
    -1985    ) -> typedefs.JSONObject:
    -1986        resp = await self._request(
    -1987            RequestMethod.GET,
    -1988            f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/",
    -1989            json={"head": head},
    -1990        )
    -1991        assert isinstance(resp, dict)
    -1992        return resp
    +            
    1971    async def fetch_content_by_tag_and_type(
    +1972        self, locale: str, tag: str, type: str, *, head: bool = False
    +1973    ) -> typedefs.JSONObject:
    +1974        resp = await self._request(
    +1975            RequestMethod.GET,
    +1976            f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/",
    +1977            json={"head": head},
    +1978        )
    +1979        assert isinstance(resp, dict)
    +1980        return resp
     
    @@ -29851,38 +24800,38 @@
    Returns
    -
    1994    async def search_content_with_text(
    -1995        self,
    -1996        locale: str,
    -1997        /,
    -1998        content_type: str,
    -1999        search_text: str,
    -2000        tag: str,
    -2001        *,
    -2002        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2003        source: undefined.UndefinedOr[str] = undefined.Undefined,
    -2004    ) -> typedefs.JSONObject:
    -2005
    -2006        body: typedefs.JSONObject = {}
    -2007
    -2008        body["ctype"] = content_type
    -2009        body["searchtext"] = search_text
    -2010        body["tag"] = tag
    -2011
    -2012        if page is not undefined.Undefined:
    -2013            body["currentpage"] = page
    -2014        else:
    -2015            body["currentpage"] = 1
    -2016
    -2017        if source is not undefined.Undefined:
    -2018            body["source"] = source
    -2019        else:
    -2020            source = ""
    -2021        resp = await self._request(
    -2022            RequestMethod.GET, f"Content/Search/{locale}/", json=body
    -2023        )
    -2024        assert isinstance(resp, dict)
    -2025        return resp
    +            
    1982    async def search_content_with_text(
    +1983        self,
    +1984        locale: str,
    +1985        /,
    +1986        content_type: str,
    +1987        search_text: str,
    +1988        tag: str,
    +1989        *,
    +1990        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +1991        source: undefined.UndefinedOr[str] = undefined.Undefined,
    +1992    ) -> typedefs.JSONObject:
    +1993
    +1994        body: typedefs.JSONObject = {}
    +1995
    +1996        body["ctype"] = content_type
    +1997        body["searchtext"] = search_text
    +1998        body["tag"] = tag
    +1999
    +2000        if page is not undefined.Undefined:
    +2001            body["currentpage"] = page
    +2002        else:
    +2003            body["currentpage"] = 1
    +2004
    +2005        if source is not undefined.Undefined:
    +2006            body["source"] = source
    +2007        else:
    +2008            source = ""
    +2009        resp = await self._request(
    +2010            RequestMethod.GET, f"Content/Search/{locale}/", json=body
    +2011        )
    +2012        assert isinstance(resp, dict)
    +2013        return resp
     
    @@ -29900,23 +24849,23 @@
    Returns
    -
    2027    async def search_content_by_tag_and_type(
    -2028        self,
    -2029        locale: str,
    -2030        tag: str,
    -2031        type: str,
    -2032        *,
    -2033        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2034    ) -> typedefs.JSONObject:
    -2035        body: typedefs.JSONObject = {}
    -2036        body["currentpage"] = 1 if page is undefined.Undefined else page
    -2037        resp = await self._request(
    -2038            RequestMethod.GET,
    -2039            f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/",
    -2040            json=body,
    -2041        )
    -2042        assert isinstance(resp, dict)
    -2043        return resp
    +            
    2015    async def search_content_by_tag_and_type(
    +2016        self,
    +2017        locale: str,
    +2018        tag: str,
    +2019        type: str,
    +2020        *,
    +2021        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +2022    ) -> typedefs.JSONObject:
    +2023        body: typedefs.JSONObject = {}
    +2024        body["currentpage"] = 1 if page is undefined.Undefined else page
    +2025        resp = await self._request(
    +2026            RequestMethod.GET,
    +2027            f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/",
    +2028            json=body,
    +2029        )
    +2030        assert isinstance(resp, dict)
    +2031        return resp
     
    @@ -29934,14 +24883,14 @@
    Returns
    -
    2045    async def search_help_articles(
    -2046        self, text: str, size: str, /
    -2047    ) -> typedefs.JSONObject:
    -2048        resp = await self._request(
    -2049            RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/"
    -2050        )
    -2051        assert isinstance(resp, dict)
    -2052        return resp
    +            
    2033    async def search_help_articles(
    +2034        self, text: str, size: str, /
    +2035    ) -> typedefs.JSONObject:
    +2036        resp = await self._request(
    +2037            RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/"
    +2038        )
    +2039        assert isinstance(resp, dict)
    +2040        return resp
     
    @@ -29959,38 +24908,38 @@
    Returns
    -
    2054    async def fetch_topics_page(
    -2055        self,
    -2056        category_filter: int,
    -2057        group: int,
    -2058        date_filter: int,
    -2059        sort: typing.Union[str, bytes],
    -2060        *,
    -2061        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2062        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    -2063        tag_filter: undefined.UndefinedOr[str] = undefined.Undefined,
    -2064    ) -> typedefs.JSONObject:
    -2065
    -2066        body: typedefs.JSONObject = {}
    -2067        if locales is not undefined.Undefined:
    -2068            body["locales"] = ",".join(str(locales))
    -2069        else:
    -2070            body["locales"] = ",".join([])
    -2071
    -2072        if tag_filter is not undefined.Undefined:
    -2073            body["tagstring"] = tag_filter
    -2074        else:
    -2075            body["tagstring"] = ""
    -2076
    -2077        page = 0 if page is not undefined.Undefined else page
    -2078
    -2079        resp = await self._request(
    -2080            RequestMethod.GET,
    -2081            f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/",
    -2082            json=body,
    -2083        )
    -2084        assert isinstance(resp, dict)
    -2085        return resp
    +            
    2042    async def fetch_topics_page(
    +2043        self,
    +2044        category_filter: int,
    +2045        group: int,
    +2046        date_filter: int,
    +2047        sort: typing.Union[str, bytes],
    +2048        *,
    +2049        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +2050        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    +2051        tag_filter: undefined.UndefinedOr[str] = undefined.Undefined,
    +2052    ) -> typedefs.JSONObject:
    +2053
    +2054        body: typedefs.JSONObject = {}
    +2055        if locales is not undefined.Undefined:
    +2056            body["locales"] = ",".join(str(locales))
    +2057        else:
    +2058            body["locales"] = ",".join([])
    +2059
    +2060        if tag_filter is not undefined.Undefined:
    +2061            body["tagstring"] = tag_filter
    +2062        else:
    +2063            body["tagstring"] = ""
    +2064
    +2065        page = 0 if page is not undefined.Undefined else page
    +2066
    +2067        resp = await self._request(
    +2068            RequestMethod.GET,
    +2069            f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/",
    +2070            json=body,
    +2071        )
    +2072        assert isinstance(resp, dict)
    +2073        return resp
     
    @@ -30008,30 +24957,30 @@
    Returns
    -
    2087    async def fetch_core_topics_page(
    -2088        self,
    -2089        category_filter: int,
    -2090        date_filter: int,
    -2091        sort: typing.Union[str, bytes],
    -2092        *,
    -2093        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2094        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    -2095    ) -> typedefs.JSONObject:
    -2096        body: typedefs.JSONObject = {}
    -2097
    -2098        if locales is not undefined.Undefined:
    -2099            body["locales"] = ",".join(str(locales))
    -2100        else:
    -2101            body["locales"] = ",".join([])
    -2102
    -2103        resp = await self._request(
    -2104            RequestMethod.GET,
    -2105            f"Forum/GetCoreTopicsPaged/{0 if page is undefined.Undefined else page}"
    -2106            f"/{sort!s}/{date_filter}/{category_filter}/",
    -2107            json=body,
    -2108        )
    -2109        assert isinstance(resp, dict)
    -2110        return resp
    +            
    2075    async def fetch_core_topics_page(
    +2076        self,
    +2077        category_filter: int,
    +2078        date_filter: int,
    +2079        sort: typing.Union[str, bytes],
    +2080        *,
    +2081        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +2082        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    +2083    ) -> typedefs.JSONObject:
    +2084        body: typedefs.JSONObject = {}
    +2085
    +2086        if locales is not undefined.Undefined:
    +2087            body["locales"] = ",".join(str(locales))
    +2088        else:
    +2089            body["locales"] = ",".join([])
    +2090
    +2091        resp = await self._request(
    +2092            RequestMethod.GET,
    +2093            f"Forum/GetCoreTopicsPaged/{0 if page is undefined.Undefined else page}"
    +2094            f"/{sort!s}/{date_filter}/{category_filter}/",
    +2095            json=body,
    +2096        )
    +2097        assert isinstance(resp, dict)
    +2098        return resp
     
    @@ -30049,25 +24998,25 @@
    Returns
    -
    2112    async def fetch_posts_threaded_page(
    -2113        self,
    -2114        parent_post: bool,
    -2115        page: int,
    -2116        page_size: int,
    -2117        parent_post_id: int,
    -2118        reply_size: int,
    -2119        root_thread_mode: bool,
    -2120        sort_mode: int,
    -2121        show_banned: typing.Optional[str] = None,
    -2122    ) -> typedefs.JSONObject:
    -2123        resp = await self._request(
    -2124            RequestMethod.GET,
    -2125            f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/"
    -2126            f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/",
    -2127            json={"showbanned": show_banned},
    -2128        )
    -2129        assert isinstance(resp, dict)
    -2130        return resp
    +            
    2100    async def fetch_posts_threaded_page(
    +2101        self,
    +2102        parent_post: bool,
    +2103        page: int,
    +2104        page_size: int,
    +2105        parent_post_id: int,
    +2106        reply_size: int,
    +2107        root_thread_mode: bool,
    +2108        sort_mode: int,
    +2109        show_banned: typing.Optional[str] = None,
    +2110    ) -> typedefs.JSONObject:
    +2111        resp = await self._request(
    +2112            RequestMethod.GET,
    +2113            f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/"
    +2114            f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/",
    +2115            json={"showbanned": show_banned},
    +2116        )
    +2117        assert isinstance(resp, dict)
    +2118        return resp
     
    @@ -30085,24 +25034,24 @@
    Returns
    -
    2132    async def fetch_posts_threaded_page_from_child(
    -2133        self,
    -2134        child_id: bool,
    -2135        page: int,
    -2136        page_size: int,
    -2137        reply_size: int,
    -2138        root_thread_mode: bool,
    -2139        sort_mode: int,
    -2140        show_banned: typing.Optional[str] = None,
    -2141    ) -> typedefs.JSONObject:
    -2142        resp = await self._request(
    -2143            RequestMethod.GET,
    -2144            f"Forum/GetPostsThreadedPagedFromChild/{child_id}/"
    -2145            f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/",
    -2146            json={"showbanned": show_banned},
    -2147        )
    -2148        assert isinstance(resp, dict)
    -2149        return resp
    +            
    2120    async def fetch_posts_threaded_page_from_child(
    +2121        self,
    +2122        child_id: bool,
    +2123        page: int,
    +2124        page_size: int,
    +2125        reply_size: int,
    +2126        root_thread_mode: bool,
    +2127        sort_mode: int,
    +2128        show_banned: typing.Optional[str] = None,
    +2129    ) -> typedefs.JSONObject:
    +2130        resp = await self._request(
    +2131            RequestMethod.GET,
    +2132            f"Forum/GetPostsThreadedPagedFromChild/{child_id}/"
    +2133            f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/",
    +2134            json={"showbanned": show_banned},
    +2135        )
    +2136        assert isinstance(resp, dict)
    +2137        return resp
     
    @@ -30120,16 +25069,16 @@
    Returns
    -
    2151    async def fetch_post_and_parent(
    -2152        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
    -2153    ) -> typedefs.JSONObject:
    -2154        resp = await self._request(
    -2155            RequestMethod.GET,
    -2156            f"Forum/GetPostAndParent/{child_id}/",
    -2157            json={"showbanned": show_banned},
    -2158        )
    -2159        assert isinstance(resp, dict)
    -2160        return resp
    +            
    2139    async def fetch_post_and_parent(
    +2140        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
    +2141    ) -> typedefs.JSONObject:
    +2142        resp = await self._request(
    +2143            RequestMethod.GET,
    +2144            f"Forum/GetPostAndParent/{child_id}/",
    +2145            json={"showbanned": show_banned},
    +2146        )
    +2147        assert isinstance(resp, dict)
    +2148        return resp
     
    @@ -30147,16 +25096,16 @@
    Returns
    -
    2162    async def fetch_posts_and_parent_awaiting(
    -2163        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
    -2164    ) -> typedefs.JSONObject:
    -2165        resp = await self._request(
    -2166            RequestMethod.GET,
    -2167            f"Forum/GetPostAndParentAwaitingApproval/{child_id}/",
    -2168            json={"showbanned": show_banned},
    -2169        )
    -2170        assert isinstance(resp, dict)
    -2171        return resp
    +            
    2150    async def fetch_posts_and_parent_awaiting(
    +2151        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
    +2152    ) -> typedefs.JSONObject:
    +2153        resp = await self._request(
    +2154            RequestMethod.GET,
    +2155            f"Forum/GetPostAndParentAwaitingApproval/{child_id}/",
    +2156            json={"showbanned": show_banned},
    +2157        )
    +2158        assert isinstance(resp, dict)
    +2159        return resp
     
    @@ -30174,12 +25123,12 @@
    Returns
    -
    2173    async def fetch_topic_for_content(self, content_id: int, /) -> int:
    -2174        resp = await self._request(
    -2175            RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/"
    -2176        )
    -2177        assert isinstance(resp, int)
    -2178        return resp
    +            
    2161    async def fetch_topic_for_content(self, content_id: int, /) -> int:
    +2162        resp = await self._request(
    +2163            RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/"
    +2164        )
    +2165        assert isinstance(resp, int)
    +2166        return resp
     
    @@ -30197,16 +25146,16 @@
    Returns
    -
    2180    async def fetch_forum_tag_suggestions(
    -2181        self, partial_tag: str, /
    -2182    ) -> typedefs.JSONObject:
    -2183        resp = await self._request(
    -2184            RequestMethod.GET,
    -2185            "Forum/GetForumTagSuggestions/",
    -2186            json={"partialtag": partial_tag},
    -2187        )
    -2188        assert isinstance(resp, dict)
    -2189        return resp
    +            
    2168    async def fetch_forum_tag_suggestions(
    +2169        self, partial_tag: str, /
    +2170    ) -> typedefs.JSONObject:
    +2171        resp = await self._request(
    +2172            RequestMethod.GET,
    +2173            "Forum/GetForumTagSuggestions/",
    +2174            json={"partialtag": partial_tag},
    +2175        )
    +2176        assert isinstance(resp, dict)
    +2177        return resp
     
    @@ -30224,10 +25173,10 @@
    Returns
    -
    2191    async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject:
    -2192        resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/")
    -2193        assert isinstance(resp, dict)
    -2194        return resp
    +            
    2179    async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject:
    +2180        resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/")
    +2181        assert isinstance(resp, dict)
    +2182        return resp
     
    @@ -30245,10 +25194,10 @@
    Returns
    -
    2196    async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray:
    -2197        resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/")
    -2198        assert isinstance(resp, list)
    -2199        return resp
    +            
    2184    async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray:
    +2185        resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/")
    +2186        assert isinstance(resp, list)
    +2187        return resp
     
    @@ -30260,27 +25209,27 @@
    Returns
    async def - fetch_recommended_groups( self, accecss_token: str, /, *, date_range: int = 0, group_type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> list[typing.Any]: + fetch_recommended_groups( self, accecss_token: str, /, *, date_range: int = 0, group_type: Union[int, aiobungie.GroupType] = <GroupType.CLAN: 1>) -> list[typing.Any]:
    -
    2201    async def fetch_recommended_groups(
    -2202        self,
    -2203        accecss_token: str,
    -2204        /,
    -2205        *,
    -2206        date_range: int = 0,
    -2207        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    -2208    ) -> typedefs.JSONArray:
    -2209        resp = await self._request(
    -2210            RequestMethod.POST,
    -2211            f"GroupV2/Recommended/{int(group_type)}/{date_range}/",
    -2212            auth=accecss_token,
    -2213        )
    -2214        assert isinstance(resp, list)
    -2215        return resp
    +            
    2189    async def fetch_recommended_groups(
    +2190        self,
    +2191        accecss_token: str,
    +2192        /,
    +2193        *,
    +2194        date_range: int = 0,
    +2195        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    +2196    ) -> typedefs.JSONArray:
    +2197        resp = await self._request(
    +2198            RequestMethod.POST,
    +2199            f"GroupV2/Recommended/{int(group_type)}/{date_range}/",
    +2200            auth=accecss_token,
    +2201        )
    +2202        assert isinstance(resp, list)
    +2203        return resp
     
    @@ -30298,10 +25247,10 @@
    Returns
    -
    2217    async def fetch_available_avatars(self) -> collections.Mapping[str, int]:
    -2218        resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/")
    -2219        assert isinstance(resp, dict)
    -2220        return resp
    +            
    2205    async def fetch_available_avatars(self) -> collections.Mapping[str, int]:
    +2206        resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/")
    +2207        assert isinstance(resp, dict)
    +2208        return resp
     
    @@ -30319,19 +25268,19 @@
    Returns
    -
    2222    async def fetch_user_clan_invite_setting(
    -2223        self,
    -2224        access_token: str,
    -2225        /,
    -2226        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2227    ) -> bool:
    -2228        resp = await self._request(
    -2229            RequestMethod.GET,
    -2230            f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/",
    -2231            auth=access_token,
    -2232        )
    -2233        assert isinstance(resp, bool)
    -2234        return resp
    +            
    2210    async def fetch_user_clan_invite_setting(
    +2211        self,
    +2212        access_token: str,
    +2213        /,
    +2214        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2215    ) -> bool:
    +2216        resp = await self._request(
    +2217            RequestMethod.GET,
    +2218            f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/",
    +2219            auth=access_token,
    +2220        )
    +2221        assert isinstance(resp, bool)
    +2222        return resp
     
    @@ -30349,16 +25298,16 @@
    Returns
    -
    2236    async def fetch_banned_group_members(
    -2237        self, access_token: str, group_id: int, /, *, page: int = 1
    -2238    ) -> typedefs.JSONObject:
    -2239        resp = await self._request(
    -2240            RequestMethod.GET,
    -2241            f"GroupV2/{group_id}/Banned/?currentpage={page}",
    -2242            auth=access_token,
    -2243        )
    -2244        assert isinstance(resp, dict)
    -2245        return resp
    +            
    2224    async def fetch_banned_group_members(
    +2225        self, access_token: str, group_id: int, /, *, page: int = 1
    +2226    ) -> typedefs.JSONObject:
    +2227        resp = await self._request(
    +2228            RequestMethod.GET,
    +2229            f"GroupV2/{group_id}/Banned/?currentpage={page}",
    +2230            auth=access_token,
    +2231        )
    +2232        assert isinstance(resp, dict)
    +2233        return resp
     
    @@ -30376,16 +25325,16 @@
    Returns
    -
    2247    async def fetch_pending_group_memberships(
    -2248        self, access_token: str, group_id: int, /, *, current_page: int = 1
    -2249    ) -> typedefs.JSONObject:
    -2250        resp = await self._request(
    -2251            RequestMethod.GET,
    -2252            f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}",
    -2253            auth=access_token,
    -2254        )
    -2255        assert isinstance(resp, dict)
    -2256        return resp
    +            
    2235    async def fetch_pending_group_memberships(
    +2236        self, access_token: str, group_id: int, /, *, current_page: int = 1
    +2237    ) -> typedefs.JSONObject:
    +2238        resp = await self._request(
    +2239            RequestMethod.GET,
    +2240            f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}",
    +2241            auth=access_token,
    +2242        )
    +2243        assert isinstance(resp, dict)
    +2244        return resp
     
    @@ -30403,16 +25352,16 @@
    Returns
    -
    2258    async def fetch_invited_group_memberships(
    -2259        self, access_token: str, group_id: int, /, *, current_page: int = 1
    -2260    ) -> typedefs.JSONObject:
    -2261        resp = await self._request(
    -2262            RequestMethod.GET,
    -2263            f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}",
    -2264            auth=access_token,
    -2265        )
    -2266        assert isinstance(resp, dict)
    -2267        return resp
    +            
    2246    async def fetch_invited_group_memberships(
    +2247        self, access_token: str, group_id: int, /, *, current_page: int = 1
    +2248    ) -> typedefs.JSONObject:
    +2249        resp = await self._request(
    +2250            RequestMethod.GET,
    +2251            f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}",
    +2252            auth=access_token,
    +2253        )
    +2254        assert isinstance(resp, dict)
    +2255        return resp
     
    @@ -30430,24 +25379,24 @@
    Returns
    -
    2269    async def invite_member_to_group(
    -2270        self,
    -2271        access_token: str,
    -2272        /,
    -2273        group_id: int,
    -2274        membership_id: int,
    -2275        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2276        *,
    -2277        message: undefined.UndefinedOr[str] = undefined.Undefined,
    -2278    ) -> typedefs.JSONObject:
    -2279        resp = await self._request(
    -2280            RequestMethod.POST,
    -2281            f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/",
    -2282            auth=access_token,
    -2283            json={"message": str(message)},
    -2284        )
    -2285        assert isinstance(resp, dict)
    -2286        return resp
    +            
    2257    async def invite_member_to_group(
    +2258        self,
    +2259        access_token: str,
    +2260        /,
    +2261        group_id: int,
    +2262        membership_id: int,
    +2263        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2264        *,
    +2265        message: undefined.UndefinedOr[str] = undefined.Undefined,
    +2266    ) -> typedefs.JSONObject:
    +2267        resp = await self._request(
    +2268            RequestMethod.POST,
    +2269            f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/",
    +2270            auth=access_token,
    +2271            json={"message": str(message)},
    +2272        )
    +2273        assert isinstance(resp, dict)
    +2274        return resp
     
    @@ -30465,21 +25414,21 @@
    Returns
    -
    2288    async def cancel_group_member_invite(
    -2289        self,
    -2290        access_token: str,
    -2291        /,
    -2292        group_id: int,
    -2293        membership_id: int,
    -2294        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2295    ) -> typedefs.JSONObject:
    -2296        resp = await self._request(
    -2297            RequestMethod.POST,
    -2298            f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/",
    -2299            auth=access_token,
    -2300        )
    -2301        assert isinstance(resp, dict)
    -2302        return resp
    +            
    2276    async def cancel_group_member_invite(
    +2277        self,
    +2278        access_token: str,
    +2279        /,
    +2280        group_id: int,
    +2281        membership_id: int,
    +2282        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2283    ) -> typedefs.JSONObject:
    +2284        resp = await self._request(
    +2285            RequestMethod.POST,
    +2286            f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/",
    +2287            auth=access_token,
    +2288        )
    +2289        assert isinstance(resp, dict)
    +2290        return resp
     
    @@ -30497,10 +25446,10 @@
    Returns
    -
    2304    async def fetch_historical_definition(self) -> typedefs.JSONObject:
    -2305        resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/")
    -2306        assert isinstance(resp, dict)
    -2307        return resp
    +            
    2292    async def fetch_historical_definition(self) -> typedefs.JSONObject:
    +2293        resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/")
    +2294        assert isinstance(resp, dict)
    +2295        return resp
     
    @@ -30518,33 +25467,33 @@
    Returns
    -
    2309    async def fetch_historical_stats(
    -2310        self,
    -2311        character_id: int,
    -2312        membership_id: int,
    -2313        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2314        day_start: datetime.datetime,
    -2315        day_end: datetime.datetime,
    -2316        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    -2317        modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]],
    -2318        *,
    -2319        period_type: enums.PeriodType = enums.PeriodType.ALL_TIME,
    -2320    ) -> typedefs.JSONObject:
    -2321
    -2322        end, start = time.parse_date_range(day_end, day_start)
    -2323        resp = await self._request(
    -2324            RequestMethod.GET,
    -2325            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/",
    -2326            json={
    -2327                "dayend": end,
    -2328                "daystart": start,
    -2329                "groups": [str(int(group)) for group in groups],
    -2330                "modes": [str(int(mode)) for mode in modes],
    -2331                "periodType": int(period_type),
    -2332            },
    -2333        )
    -2334        assert isinstance(resp, dict)
    -2335        return resp
    +            
    2297    async def fetch_historical_stats(
    +2298        self,
    +2299        character_id: int,
    +2300        membership_id: int,
    +2301        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2302        day_start: datetime.datetime,
    +2303        day_end: datetime.datetime,
    +2304        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    +2305        modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]],
    +2306        *,
    +2307        period_type: enums.PeriodType = enums.PeriodType.ALL_TIME,
    +2308    ) -> typedefs.JSONObject:
    +2309
    +2310        end, start = time.parse_date_range(day_end, day_start)
    +2311        resp = await self._request(
    +2312            RequestMethod.GET,
    +2313            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/",
    +2314            json={
    +2315                "dayend": end,
    +2316                "daystart": start,
    +2317                "groups": [str(int(group)) for group in groups],
    +2318                "modes": [str(int(mode)) for mode in modes],
    +2319                "periodType": int(period_type),
    +2320            },
    +2321        )
    +2322        assert isinstance(resp, dict)
    +2323        return resp
     
    @@ -30592,19 +25541,19 @@
    Returns
    -
    2337    async def fetch_historical_stats_for_account(
    -2338        self,
    -2339        membership_id: int,
    -2340        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2341        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    -2342    ) -> typedefs.JSONObject:
    -2343        resp = await self._request(
    -2344            RequestMethod.GET,
    -2345            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/",
    -2346            json={"groups": [str(int(group)) for group in groups]},
    -2347        )
    -2348        assert isinstance(resp, dict)
    -2349        return resp
    +            
    2325    async def fetch_historical_stats_for_account(
    +2326        self,
    +2327        membership_id: int,
    +2328        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2329        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    +2330    ) -> typedefs.JSONObject:
    +2331        resp = await self._request(
    +2332            RequestMethod.GET,
    +2333            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/",
    +2334            json={"groups": [str(int(group)) for group in groups]},
    +2335        )
    +2336        assert isinstance(resp, dict)
    +2337        return resp
     
    @@ -30642,20 +25591,20 @@
    Returns
    -
    2351    async def fetch_aggregated_activity_stats(
    -2352        self,
    -2353        character_id: int,
    -2354        membership_id: int,
    -2355        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2356        /,
    -2357    ) -> typedefs.JSONObject:
    -2358        resp = await self._request(
    -2359            RequestMethod.GET,
    -2360            f"Destiny2/{int(membership_type)}/Account/{membership_id}/"
    -2361            f"Character/{character_id}/Stats/AggregateActivityStats/",
    -2362        )
    -2363        assert isinstance(resp, dict)
    -2364        return resp
    +            
    2339    async def fetch_aggregated_activity_stats(
    +2340        self,
    +2341        character_id: int,
    +2342        membership_id: int,
    +2343        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2344        /,
    +2345    ) -> typedefs.JSONObject:
    +2346        resp = await self._request(
    +2347            RequestMethod.GET,
    +2348            f"Destiny2/{int(membership_type)}/Account/{membership_id}/"
    +2349            f"Character/{character_id}/Stats/AggregateActivityStats/",
    +2350        )
    +2351        assert isinstance(resp, dict)
    +2352        return resp
     
    @@ -30693,124 +25642,124 @@
    Returns
    -
    244class RESTPool:
    -245    """Pool of `RESTClient` instances.
    -246
    -247    This allows to create multiple instances of `RESTClient`s that can be acquired
    -248    which share the same config and metadata.
    -249
    -250    Example
    -251    -------
    -252    ```py
    -253    import aiobungie
    -254    import asyncio
    +            
    242class RESTPool:
    +243    """Pool of `RESTClient` instances.
    +244
    +245    This allows to create multiple instances of `RESTClient`s that can be acquired
    +246    which share the same config and metadata.
    +247
    +248    Example
    +249    -------
    +250    ```py
    +251    import aiobungie
    +252    import asyncio
    +253
    +254    client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret')
     255
    -256    client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret')
    -257
    -258    # Using a context manager to acquire an instance
    -259    # of the pool and close the connection after finishing.
    -260
    -261    async def first() -> str:
    -262        async with client_pool.acquire() as client:
    -263            return client.build_oauth2_url()
    -264
    -265    async def second() -> None:
    -266        async with client_pool.acquire() as client:
    -267            new_tokens = await client.refresh_access_token("token")
    -268            client.metadata['tokens'] = new_tokens
    -269
    -270    # Client instances are independent from first and second.
    -271    await asyncio.gather(first(), second())
    -272    ```
    -273
    -274    Parameters
    -275    ----------
    -276    token : `str`
    -277        A valid application token from Bungie's developer portal.
    -278
    -279    Other Parameters
    -280    ----------------
    -281    max_retries : `int`
    -282        The max retries number to retry if the request hit a `5xx` status code.
    -283    max_ratelimit_retries : `int`
    -284        The max retries number to retry if the request hit a `429` status code. Defaults to `3`.
    -285    client_secret : `typing.Optional[str]`
    -286        An optional application client secret,
    -287        This is only needed if you're fetching OAuth2 tokens with this client.
    -288    client_id : `typing.Optional[int]`
    -289        An optional application client id,
    -290        This is only needed if you're fetching OAuth2 tokens with this client.
    -291    enable_debugging : `bool | str`
    -292        Whether to enable logging responses or not.
    -293
    -294    Logging Levels
    -295    --------------
    -296    * `False`: This will disable logging.
    -297    * `True`: This will set the level to `DEBUG` and enable logging minimal information.
    -298    Like the response status, route, taken time and so on.
    -299    * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information.
    -300    """
    -301
    -302    __slots__ = (
    -303        "_token",
    -304        "_max_retries",
    -305        "_client_secret",
    -306        "_client_id",
    -307        "_max_rate_limit_retries",
    -308        "_metadata",
    -309        "_enable_debug",
    -310    )
    -311
    -312    # Looks like mypy doesn't like this.
    -313    if typing.TYPE_CHECKING:
    -314        _enable_debug: typing.Union[typing.Literal["TRACE"], bool, int]
    -315
    -316    def __init__(
    -317        self,
    -318        token: str,
    -319        /,
    -320        client_secret: typing.Optional[str] = None,
    -321        client_id: typing.Optional[int] = None,
    -322        *,
    -323        max_retries: int = 4,
    -324        max_rate_limit_retries: int = 3,
    -325        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    -326    ) -> None:
    -327        self._client_secret = client_secret
    -328        self._client_id = client_id
    -329        self._token: str = token
    -330        self._max_retries = max_retries
    -331        self._max_rate_limit_retries = max_rate_limit_retries
    -332        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    -333        self._enable_debug = enable_debugging
    -334
    -335    @property
    -336    def client_id(self) -> typing.Optional[int]:
    -337        return self._client_id
    -338
    -339    @property
    -340    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    -341        """Pool's Metadata. This is different from client instance metadata."""
    -342        return self._metadata
    -343
    -344    @typing.final
    -345    def acquire(self) -> RESTClient:
    -346        """Acquires a new `RESTClient` instance from this REST pool.
    -347
    -348        Returns
    -349        -------
    -350        `RESTClient`
    -351            An instance of a REST client.
    -352        """
    -353        instance = RESTClient(
    -354            self._token,
    -355            client_secret=self._client_secret,
    -356            client_id=self._client_id,
    -357            max_retries=self._max_retries,
    -358            max_ratelimit_retries=self._max_rate_limit_retries,
    -359            enable_debugging=self._enable_debug,
    -360        )
    -361        return instance
    +256    # Using a context manager to acquire an instance
    +257    # of the pool and close the connection after finishing.
    +258
    +259    async def first() -> str:
    +260        async with client_pool.acquire() as client:
    +261            return client.build_oauth2_url()
    +262
    +263    async def second() -> None:
    +264        async with client_pool.acquire() as client:
    +265            new_tokens = await client.refresh_access_token("token")
    +266            client.metadata['tokens'] = new_tokens
    +267
    +268    # Client instances are independent from first and second.
    +269    await asyncio.gather(first(), second())
    +270    ```
    +271
    +272    Parameters
    +273    ----------
    +274    token : `str`
    +275        A valid application token from Bungie's developer portal.
    +276
    +277    Other Parameters
    +278    ----------------
    +279    max_retries : `int`
    +280        The max retries number to retry if the request hit a `5xx` status code.
    +281    max_ratelimit_retries : `int`
    +282        The max retries number to retry if the request hit a `429` status code. Defaults to `3`.
    +283    client_secret : `typing.Optional[str]`
    +284        An optional application client secret,
    +285        This is only needed if you're fetching OAuth2 tokens with this client.
    +286    client_id : `typing.Optional[int]`
    +287        An optional application client id,
    +288        This is only needed if you're fetching OAuth2 tokens with this client.
    +289    enable_debugging : `bool | str`
    +290        Whether to enable logging responses or not.
    +291
    +292    Logging Levels
    +293    --------------
    +294    * `False`: This will disable logging.
    +295    * `True`: This will set the level to `DEBUG` and enable logging minimal information.
    +296    Like the response status, route, taken time and so on.
    +297    * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information.
    +298    """
    +299
    +300    __slots__ = (
    +301        "_token",
    +302        "_max_retries",
    +303        "_client_secret",
    +304        "_client_id",
    +305        "_max_rate_limit_retries",
    +306        "_metadata",
    +307        "_enable_debug",
    +308    )
    +309
    +310    # Looks like mypy doesn't like this.
    +311    if typing.TYPE_CHECKING:
    +312        _enable_debug: typing.Union[typing.Literal["TRACE"], bool, int]
    +313
    +314    def __init__(
    +315        self,
    +316        token: str,
    +317        /,
    +318        client_secret: typing.Optional[str] = None,
    +319        client_id: typing.Optional[int] = None,
    +320        *,
    +321        max_retries: int = 4,
    +322        max_rate_limit_retries: int = 3,
    +323        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    +324    ) -> None:
    +325        self._client_secret = client_secret
    +326        self._client_id = client_id
    +327        self._token: str = token
    +328        self._max_retries = max_retries
    +329        self._max_rate_limit_retries = max_rate_limit_retries
    +330        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    +331        self._enable_debug = enable_debugging
    +332
    +333    @property
    +334    def client_id(self) -> typing.Optional[int]:
    +335        return self._client_id
    +336
    +337    @property
    +338    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    +339        """Pool's Metadata. This is different from client instance metadata."""
    +340        return self._metadata
    +341
    +342    @typing.final
    +343    def acquire(self) -> RESTClient:
    +344        """Acquires a new `RESTClient` instance from this REST pool.
    +345
    +346        Returns
    +347        -------
    +348        `RESTClient`
    +349            An instance of a REST client.
    +350        """
    +351        instance = RESTClient(
    +352            self._token,
    +353            client_secret=self._client_secret,
    +354            client_id=self._client_id,
    +355            max_retries=self._max_retries,
    +356            max_ratelimit_retries=self._max_rate_limit_retries,
    +357            enable_debugging=self._enable_debug,
    +358        )
    +359        return instance
     
    @@ -30821,7 +25770,8 @@
    Returns
    Example
    -
    import aiobungie
    +
    +
    import aiobungie
     import asyncio
     
     client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret')
    @@ -30840,7 +25790,8 @@ 
    Example
    # Client instances are independent from first and second. await asyncio.gather(first(), second()) -
    +
    +
    Parameters
    @@ -30887,40 +25838,29 @@
    Logging Levels
    -
    316    def __init__(
    -317        self,
    -318        token: str,
    -319        /,
    -320        client_secret: typing.Optional[str] = None,
    -321        client_id: typing.Optional[int] = None,
    -322        *,
    -323        max_retries: int = 4,
    -324        max_rate_limit_retries: int = 3,
    -325        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    -326    ) -> None:
    -327        self._client_secret = client_secret
    -328        self._client_id = client_id
    -329        self._token: str = token
    -330        self._max_retries = max_retries
    -331        self._max_rate_limit_retries = max_rate_limit_retries
    -332        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    -333        self._enable_debug = enable_debugging
    +            
    314    def __init__(
    +315        self,
    +316        token: str,
    +317        /,
    +318        client_secret: typing.Optional[str] = None,
    +319        client_id: typing.Optional[int] = None,
    +320        *,
    +321        max_retries: int = 4,
    +322        max_rate_limit_retries: int = 3,
    +323        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    +324    ) -> None:
    +325        self._client_secret = client_secret
    +326        self._client_id = client_id
    +327        self._token: str = token
    +328        self._max_retries = max_retries
    +329        self._max_rate_limit_retries = max_rate_limit_retries
    +330        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    +331        self._enable_debug = enable_debugging
     
    -
    -
    -
    - client_id: Optional[int] - - -
    - - - -
    @@ -30947,24 +25887,24 @@
    Logging Levels
    -
    344    @typing.final
    -345    def acquire(self) -> RESTClient:
    -346        """Acquires a new `RESTClient` instance from this REST pool.
    -347
    -348        Returns
    -349        -------
    -350        `RESTClient`
    -351            An instance of a REST client.
    -352        """
    -353        instance = RESTClient(
    -354            self._token,
    -355            client_secret=self._client_secret,
    -356            client_id=self._client_id,
    -357            max_retries=self._max_retries,
    -358            max_ratelimit_retries=self._max_rate_limit_retries,
    -359            enable_debugging=self._enable_debug,
    -360        )
    -361        return instance
    +            
    342    @typing.final
    +343    def acquire(self) -> RESTClient:
    +344        """Acquires a new `RESTClient` instance from this REST pool.
    +345
    +346        Returns
    +347        -------
    +348        `RESTClient`
    +349            An instance of a REST client.
    +350        """
    +351        instance = RESTClient(
    +352            self._token,
    +353            client_secret=self._client_secret,
    +354            client_id=self._client_id,
    +355            max_retries=self._max_retries,
    +356            max_ratelimit_retries=self._max_rate_limit_retries,
    +357            enable_debugging=self._enable_debug,
    +358        )
    +359        return instance
     
    @@ -30992,14 +25932,14 @@
    Returns
    -
    496@typing.final
    -497class Race(int, Enum):
    -498    """An Enum for Destiny races."""
    -499
    -500    HUMAN = 0
    -501    AWOKEN = 1
    -502    EXO = 2
    -503    UNKNOWN = 3
    +            
    493@typing.final
    +494class Race(int, Enum):
    +495    """An Enum for Destiny races."""
    +496
    +497    HUMAN = 0
    +498    AWOKEN = 1
    +499    EXO = 2
    +500    UNKNOWN = 3
     
    @@ -31007,50 +25947,6 @@
    Returns
    -
    -
    - HUMAN = <Race.HUMAN: 0> - - -
    - - - - -
    -
    -
    - AWOKEN = <Race.AWOKEN: 1> - - -
    - - - - -
    -
    -
    - EXO = <Race.EXO: 2> - - -
    - - - - -
    -
    -
    - UNKNOWN = <Race.UNKNOWN: 3> - - -
    - - - - -
    Inherited Members
    @@ -31087,21 +25983,21 @@
    Inherited Members
    -
    148@typing.final
    -149class Raid(int, Enum):
    -150    """An Enum for all available raids in Destiny 2."""
    -151
    -152    DSC = 910380154
    -153    """Deep Stone Crypt"""
    -154
    -155    LW = 2122313384
    -156    """Last Wish"""
    -157
    -158    VOG = 3881495763
    -159    """Normal Valut of Glass"""
    -160
    -161    GOS = 3458480158
    -162    """Garden Of Salvation"""
    +            
    143@typing.final
    +144class Raid(int, Enum):
    +145    """An Enum for all available raids in Destiny 2."""
    +146
    +147    DSC = 910380154
    +148    """Deep Stone Crypt"""
    +149
    +150    LW = 2122313384
    +151    """Last Wish"""
    +152
    +153    VOG = 3881495763
    +154    """Normal Valut of Glass"""
    +155
    +156    GOS = 3458480158
    +157    """Garden Of Salvation"""
     
    @@ -31326,7 +26222,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -31344,18 +26239,18 @@
    Inherited Members
    -
    49@typing.final
    -50class RecordState(enums.Flag):
    -51    """An enum for records component states."""
    -52
    -53    NONE = 0
    -54    REDEEMED = 1
    -55    UNAVAILABLE = 2
    -56    OBJECTIVE_NOT_COMPLETED = 4
    -57    OBSCURED = 8
    -58    INVISIBLE = 16
    -59    ENTITLEMENT_UNOWNED = 32
    -60    CAN_EQUIP_TITLE = 64
    +            
    48@typing.final
    +49class RecordState(enums.Flag):
    +50    """An enum for records component states."""
    +51
    +52    NONE = 0
    +53    REDEEMED = 1 << 0
    +54    UNAVAILABLE = 1 << 1
    +55    OBJECTIVE_NOT_COMPLETED = 1 << 2
    +56    OBSCURED = 1 << 3
    +57    INVISIBLE = 1 << 4
    +58    ENTITLEMENT_UNOWNED = 1 << 5
    +59    CAN_EQUIP_TITLE = 1 << 6
     
    @@ -31363,94 +26258,6 @@
    Inherited Members
    -
    -
    - NONE = <RecordState.NONE: 0> - - -
    - - - - -
    -
    -
    - REDEEMED = <RecordState.REDEEMED: 1> - - -
    - - - - -
    -
    -
    - UNAVAILABLE = <RecordState.UNAVAILABLE: 2> - - -
    - - - - -
    -
    -
    - OBJECTIVE_NOT_COMPLETED = <RecordState.OBJECTIVE_NOT_COMPLETED: 4> - - -
    - - - - -
    -
    -
    - OBSCURED = <RecordState.OBSCURED: 8> - - -
    - - - - -
    -
    -
    - INVISIBLE = <RecordState.INVISIBLE: 16> - - -
    - - - - -
    -
    -
    - ENTITLEMENT_UNOWNED = <RecordState.ENTITLEMENT_UNOWNED: 32> - - -
    - - - - -
    -
    -
    - CAN_EQUIP_TITLE = <RecordState.CAN_EQUIP_TITLE: 64> - - -
    - - - - -
    Inherited Members
    @@ -31474,14 +26281,14 @@
    Inherited Members
    -
    691@typing.final
    -692class Relationship(int, Enum):
    -693    """An enum for bungie friends relationship types."""
    -694
    -695    UNKNOWN = 0
    -696    FRIEND = 1
    -697    INCOMING_REQUEST = 2
    -698    OUTGOING_REQUEST = 3
    +            
    688@typing.final
    +689class Relationship(int, Enum):
    +690    """An enum for bungie friends relationship types."""
    +691
    +692    UNKNOWN = 0
    +693    FRIEND = 1
    +694    INCOMING_REQUEST = 2
    +695    OUTGOING_REQUEST = 3
     
    @@ -31489,50 +26296,6 @@
    Inherited Members
    -
    -
    - UNKNOWN = <Relationship.UNKNOWN: 0> - - -
    - - - - -
    -
    -
    - FRIEND = <Relationship.FRIEND: 1> - - -
    - - - - -
    -
    -
    - INCOMING_REQUEST = <Relationship.INCOMING_REQUEST: 2> - - -
    - - - - -
    -
    -
    - OUTGOING_REQUEST = <Relationship.OUTGOING_REQUEST: 3> - - -
    - - - - -
    Inherited Members
    @@ -31568,19 +26331,19 @@
    Inherited Members
    -
    225class RequestMethod(str, enums.Enum):
    -226    """HTTP request methods enum."""
    -227
    -228    GET = "GET"
    -229    """GET methods."""
    -230    POST = "POST"
    -231    """POST methods."""
    -232    PUT = "PUT"
    -233    """PUT methods."""
    -234    PATCH = "PATCH"
    -235    """PATCH methods."""
    -236    DELETE = "DELETE"
    -237    """DELETE methods"""
    +            
    223class RequestMethod(str, enums.Enum):
    +224    """HTTP request methods enum."""
    +225
    +226    GET = "GET"
    +227    """GET methods."""
    +228    POST = "POST"
    +229    """POST methods."""
    +230    PUT = "PUT"
    +231    """PUT methods."""
    +232    PATCH = "PATCH"
    +233    """PATCH methods."""
    +234    DELETE = "DELETE"
    +235    """DELETE methods"""
     
    @@ -31782,131 +26545,42 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    - -
    - -
    - -
    - -
    -
    @typing.final
    - - class - Stat(builtins.int, aiobungie.Enum): - - - -
    - -
    518@typing.final
    -519class Stat(int, Enum):
    -520    """An Enum for Destiny 2 character stats."""
    -521
    -522    NONE = 0
    -523    MOBILITY = 2996146975
    -524    RESILIENCE = 392767087
    -525    RECOVERY = 1943323491
    -526    DISCIPLINE = 1735777505
    -527    INTELLECT = 144602215
    -528    STRENGTH = 4244567218
    -529    LIGHT_POWER = 1935470627
    -
    - - -

    An Enum for Destiny 2 character stats.

    -
    - - -
    -
    - NONE = <Stat.NONE: 0> - - -
    - - - - -
    -
    -
    - MOBILITY = <Stat.MOBILITY: 2996146975> - - -
    - - - - -
    -
    -
    - RESILIENCE = <Stat.RESILIENCE: 392767087> - - -
    - - - - -
    -
    -
    - RECOVERY = <Stat.RECOVERY: 1943323491> - - -
    - - - - -
    -
    -
    - DISCIPLINE = <Stat.DISCIPLINE: 1735777505> - - -
    - - - - -
    -
    -
    - INTELLECT = <Stat.INTELLECT: 144602215> - - -
    - - - +
    +
    -
    -
    - STRENGTH = <Stat.STRENGTH: 4244567218> + +
    + +
    +
    @typing.final
    - -
    - - - + class + Stat(builtins.int, aiobungie.Enum): -
    -
    -
    - LIGHT_POWER = <Stat.LIGHT_POWER: 1935470627> + -
    - - - + +
    515@typing.final
    +516class Stat(int, Enum):
    +517    """An Enum for Destiny 2 character stats."""
    +518
    +519    NONE = 0
    +520    MOBILITY = 2996146975
    +521    RESILIENCE = 392767087
    +522    RECOVERY = 1943323491
    +523    DISCIPLINE = 1735777505
    +524    INTELLECT = 144602215
    +525    STRENGTH = 4244567218
    +526    LIGHT_POWER = 1935470627
    +
    + + +

    An Enum for Destiny 2 character stats.

    +
    + -
    Inherited Members
    @@ -31954,17 +26628,17 @@
    Inherited Members
    -
    633@typing.final
    -634class TierType(int, Enum):
    -635    """An enum for a Destiny 2 item tier type."""
    -636
    -637    UNKNOWN = 0
    -638    CURRENCY = 1
    -639    BASIC = 2
    -640    COMMON = 3
    -641    RARE = 4
    -642    SUPERIOR = 5
    -643    EXOTIC = 6
    +            
    630@typing.final
    +631class TierType(int, Enum):
    +632    """An enum for a Destiny 2 item tier type."""
    +633
    +634    UNKNOWN = 0
    +635    CURRENCY = 1
    +636    BASIC = 2
    +637    COMMON = 3
    +638    RARE = 4
    +639    SUPERIOR = 5
    +640    EXOTIC = 6
     
    @@ -31972,83 +26646,6 @@
    Inherited Members
    -
    -
    - UNKNOWN = <TierType.UNKNOWN: 0> - - -
    - - - - -
    -
    -
    - CURRENCY = <TierType.CURRENCY: 1> - - -
    - - - - -
    -
    -
    - BASIC = <TierType.BASIC: 2> - - -
    - - - - -
    -
    -
    - COMMON = <TierType.COMMON: 3> - - -
    - - - - -
    -
    -
    - RARE = <TierType.RARE: 4> - - -
    - - - - -
    -
    -
    - SUPERIOR = <TierType.SUPERIOR: 5> - - -
    - - - - -
    -
    -
    - EXOTIC = <TierType.EXOTIC: 6> - - -
    - - - - -
    Inherited Members
    @@ -32085,18 +26682,18 @@
    Inherited Members
    -
    743@typing.final
    -744class TransferStatus(Flag):
    -745    """An enum for items transfer statuses."""
    -746
    -747    CAN_TRANSFER = 0
    -748    """The item can be transferred."""
    -749    IS_EQUIPPED = 1
    -750    """You can't transfer since the item is equipped."""
    -751    NOT_TRASNFERRABLE = 2
    -752    """This item can not be transferred."""
    -753    COULD_BE_TRANSFERRED = 4
    -754    """You can trasnfer the item. But the place you're trying to put it at has no space for it."""
    +            
    740@typing.final
    +741class TransferStatus(Flag):
    +742    """An enum for items transfer statuses."""
    +743
    +744    CAN_TRANSFER = 0
    +745    """The item can be transferred."""
    +746    IS_EQUIPPED = 1 << 0
    +747    """You can't transfer since the item is equipped."""
    +748    NOT_TRASNFERRABLE = 1 << 1
    +749    """This item can not be transferred."""
    +750    COULD_BE_TRANSFERRED = 1 << 2
    +751    """You can trasnfer the item. But the place you're trying to put it at has no space for it."""
     
    @@ -32249,290 +26846,124 @@
    Inherited Members
    message_data
    -
    builtins.BaseException
    -
    with_traceback
    -
    args
    - -
    - -
    - -
    -
    - Undefined = UNDEFINED - - -
    - - - - -
    -
    -
    - UndefinedOr = typing.Union[aiobungie.UndefinedType, +_T] - - -
    - - - - -
    -
    - -
    - - class - UndefinedType: - - - -
    - -
    33class UndefinedType:
    -34    """An `UNDEFINED` type."""
    -35
    -36    __instance: typing.Optional[UndefinedType] = None
    -37
    -38    def __bool__(self) -> typing.Literal[False]:
    -39        return False
    -40
    -41    def __int__(self) -> typing.Literal[0]:
    -42        return 0
    -43
    -44    def __repr__(self) -> str:
    -45        return "UNDEFINED"
    -46
    -47    def __str__(self) -> str:
    -48        return "UNDEFINED"
    -49
    -50    def __new__(cls) -> UndefinedType:
    -51        if cls.__instance is None:
    -52            o = super().__new__(cls)
    -53            cls.__instance = o
    -54        return cls.__instance
    -
    - - -

    An UNDEFINED type.

    -
    - - -
    -
    - - UndefinedType() - - -
    - - - - -
    -
    -
    - -
    -
    @typing.final
    - - class - ValueUIStyle(builtins.int, aiobungie.Enum): - - - -
    - -
    75@typing.final
    -76class ValueUIStyle(int, enums.Enum):
    -77    AUTOMATIC = 0
    -78    FRACTION = 1
    -79    CHECK_BOX = 2
    -80    PERCENTAGE = 3
    -81    DATETIME = 4
    -82    FRACTION_FLOAT = 5
    -83    INTEGER = 6
    -84    TIME_DURATION = 7
    -85    HIDDEN = 8
    -86    MULTIPLIER = 9
    -87    GREEN_PIPS = 10
    -88    RED_PIPS = 11
    -89    EXPLICIT_PERCENTAGE = 12
    -90    RAW_FLOAT = 13
    -91    LEVEL_AND_REWARD = 14
    -
    - - -

    An enumeration.

    -
    - - -
    -
    - AUTOMATIC = <ValueUIStyle.AUTOMATIC: 0> - - -
    - - - - -
    -
    -
    - FRACTION = <ValueUIStyle.FRACTION: 1> - - -
    - - - - -
    -
    -
    - CHECK_BOX = <ValueUIStyle.CHECK_BOX: 2> - - -
    - - - - -
    -
    -
    - PERCENTAGE = <ValueUIStyle.PERCENTAGE: 3> - - -
    - - - - -
    -
    -
    - DATETIME = <ValueUIStyle.DATETIME: 4> - - -
    - - - - -
    -
    -
    - FRACTION_FLOAT = <ValueUIStyle.FRACTION_FLOAT: 5> - - -
    - - - - -
    -
    -
    - INTEGER = <ValueUIStyle.INTEGER: 6> - - -
    - - - +
    builtins.BaseException
    +
    with_traceback
    +
    +
    -
    -
    - TIME_DURATION = <ValueUIStyle.TIME_DURATION: 7> +
    +
    +
    + Undefined = UNDEFINED
    - + -
    -
    -
    - HIDDEN = <ValueUIStyle.HIDDEN: 8> + +
    +
    + UndefinedOr = typing.Union[aiobungie.UndefinedType, +_T]
    - + -
    -
    -
    - MULTIPLIER = <ValueUIStyle.MULTIPLIER: 9> + +
    + +
    + + class + UndefinedType: + + -
    - - - + +
    33class UndefinedType:
    +34    """An `UNDEFINED` type."""
    +35
    +36    __instance: typing.Optional[UndefinedType] = None
    +37
    +38    def __bool__(self) -> typing.Literal[False]:
    +39        return False
    +40
    +41    def __int__(self) -> typing.Literal[0]:
    +42        return 0
    +43
    +44    def __repr__(self) -> str:
    +45        return "UNDEFINED"
    +46
    +47    def __str__(self) -> str:
    +48        return "UNDEFINED"
    +49
    +50    def __new__(cls) -> UndefinedType:
    +51        if cls.__instance is None:
    +52            o = super().__new__(cls)
    +53            cls.__instance = o
    +54        return cls.__instance
    +
    -
    -
    -
    - GREEN_PIPS = <ValueUIStyle.GREEN_PIPS: 10> - -
    - - - +

    An UNDEFINED type.

    +
    -
    -
    -
    - RED_PIPS = <ValueUIStyle.RED_PIPS: 11> + +
    +
    + + UndefinedType()
    - +
    -
    -
    - EXPLICIT_PERCENTAGE = <ValueUIStyle.EXPLICIT_PERCENTAGE: 12> + +
    + +
    +
    @typing.final
    - -
    - - - + class + ValueUIStyle(builtins.int, aiobungie.Enum): -
    -
    -
    - RAW_FLOAT = <ValueUIStyle.RAW_FLOAT: 13> + -
    - - - + +
    75@typing.final
    +76class ValueUIStyle(int, enums.Enum):
    +77    AUTOMATIC = 0
    +78    FRACTION = 1
    +79    CHECK_BOX = 2
    +80    PERCENTAGE = 3
    +81    DATETIME = 4
    +82    FRACTION_FLOAT = 5
    +83    INTEGER = 6
    +84    TIME_DURATION = 7
    +85    HIDDEN = 8
    +86    MULTIPLIER = 9
    +87    GREEN_PIPS = 10
    +88    RED_PIPS = 11
    +89    EXPLICIT_PERCENTAGE = 12
    +90    RAW_FLOAT = 13
    +91    LEVEL_AND_REWARD = 14
    +
    -
    -
    -
    - LEVEL_AND_REWARD = <ValueUIStyle.LEVEL_AND_REWARD: 14> - -
    - - - +

    An enumeration.

    +
    + -
    Inherited Members
    @@ -32569,33 +27000,33 @@
    Inherited Members
    -
    245@typing.final
    -246class Vendor(int, Enum):
    -247    """An Enum for all available vendors in Destiny 2."""
    -248
    -249    ZAVALA = 69482069
    -250    XUR = 2190858386
    -251    BANSHE = 672118013
    -252    SPIDER = 863940356
    -253    SHAXX = 3603221665
    -254    KADI = 529635856
    -255    """Postmaster exo."""
    -256    YUNA = 1796504621
    -257    """Asia servers only."""
    -258    EVERVERSE = 3361454721
    -259    AMANDA = 460529231
    -260    """Amanda holiday"""
    -261    CROW = 3611983588
    -262    HAWTHORNE = 3347378076
    -263    ADA1 = 350061650
    -264    DRIFTER = 248695599
    -265    IKORA = 1976548992
    -266    SAINT = 765357505
    -267    """Saint-14"""
    -268    ERIS_MORN = 1616085565
    -269    SHAW_HAWN = 1816541247
    -270    """COSMODROME Guy"""
    -271    VARIKS = 2531198101
    +            
    240@typing.final
    +241class Vendor(int, Enum):
    +242    """An Enum for all available vendors in Destiny 2."""
    +243
    +244    ZAVALA = 69482069
    +245    XUR = 2190858386
    +246    BANSHE = 672118013
    +247    SPIDER = 863940356
    +248    SHAXX = 3603221665
    +249    KADI = 529635856
    +250    """Postmaster exo."""
    +251    YUNA = 1796504621
    +252    """Asia servers only."""
    +253    EVERVERSE = 3361454721
    +254    AMANDA = 460529231
    +255    """Amanda holiday"""
    +256    CROW = 3611983588
    +257    HAWTHORNE = 3347378076
    +258    ADA1 = 350061650
    +259    DRIFTER = 248695599
    +260    IKORA = 1976548992
    +261    SAINT = 765357505
    +262    """Saint-14"""
    +263    ERIS_MORN = 1616085565
    +264    SHAW_HAWN = 1816541247
    +265    """COSMODROME Guy"""
    +266    VARIKS = 2531198101
     
    @@ -32603,61 +27034,6 @@
    Inherited Members
    -
    -
    - ZAVALA = <Vendor.ZAVALA: 69482069> - - -
    - - - - -
    -
    -
    - XUR = <Vendor.XUR: 2190858386> - - -
    - - - - -
    -
    -
    - BANSHE = <Vendor.BANSHE: 672118013> - - -
    - - - - -
    -
    -
    - SPIDER = <Vendor.SPIDER: 863940356> - - -
    - - - - -
    -
    -
    - SHAXX = <Vendor.SHAXX: 3603221665> - - -
    - - - - -
    KADI = <Vendor.KADI: 529635856> @@ -32683,17 +27059,6 @@
    Inherited Members
    -
    -
    -
    - EVERVERSE = <Vendor.EVERVERSE: 3361454721> - - -
    - - - -
    @@ -32707,61 +27072,6 @@
    Inherited Members
    -
    -
    -
    - CROW = <Vendor.CROW: 3611983588> - - -
    - - - - -
    -
    -
    - HAWTHORNE = <Vendor.HAWTHORNE: 3347378076> - - -
    - - - - -
    -
    -
    - ADA1 = <Vendor.ADA1: 350061650> - - -
    - - - - -
    -
    -
    - DRIFTER = <Vendor.DRIFTER: 248695599> - - -
    - - - - -
    -
    -
    - IKORA = <Vendor.IKORA: 1976548992> - - -
    - - - -
    @@ -32775,17 +27085,6 @@
    Inherited Members
    -
    -
    -
    - ERIS_MORN = <Vendor.ERIS_MORN: 1616085565> - - -
    - - - -
    @@ -32799,17 +27098,6 @@
    Inherited Members
    -
    -
    -
    - VARIKS = <Vendor.VARIKS: 2531198101> - - -
    - - - -
    Inherited Members
    @@ -32847,14 +27135,14 @@
    Inherited Members
    -
    532@typing.final
    -533class WeaponType(int, Enum):
    -534    """Enums for The three Destiny Weapon Types"""
    -535
    -536    NONE = 0
    -537    KINETIC = 1498876634
    -538    ENERGY = 2465295065
    -539    POWER = 953998645
    +            
    529@typing.final
    +530class WeaponType(int, Enum):
    +531    """Enums for The three Destiny Weapon Types"""
    +532
    +533    NONE = 0
    +534    KINETIC = 1498876634
    +535    ENERGY = 2465295065
    +536    POWER = 953998645
     
    @@ -32862,50 +27150,6 @@
    Inherited Members
    -
    -
    - NONE = <WeaponType.NONE: 0> - - -
    - - - - -
    -
    -
    - KINETIC = <WeaponType.KINETIC: 1498876634> - - -
    - - - - -
    -
    -
    - ENERGY = <WeaponType.ENERGY: 2465295065> - - -
    - - - - -
    -
    -
    - POWER = <WeaponType.POWER: 953998645> - - -
    - - - - -
    Inherited Members
    @@ -32946,39 +27190,39 @@
    Inherited Members
    def - into_iter( iterable: collections.abc.Iterable[~Item]) -> aiobungie.FlatIterator[~Item]: + into_iter( iterable: collections.abc.Iterable[~Item]) -> aiobungie.Iterator[~Item]:
    -
    588def into_iter(
    -589    iterable: collections.Iterable[Item],
    -590) -> FlatIterator[Item]:
    -591    """Transform an iterable into an flat iterator.
    -592
    -593    Example
    -594    -------
    -595    ```py
    -596    sequence = [1,2,3]
    -597    for item in aiobungie.into_iter(sequence).reversed():
    -598        print(item)
    -599    # 3
    -600    # 2
    -601    # 1
    -602    ```
    -603
    -604    Parameters
    -605    ----------
    -606    iterable: `typing.Iterable[Item]`
    -607        The iterable to convert.
    -608
    -609    Raises
    -610    ------
    -611    `StopIteration`
    -612        If no elements are left in the iterator.
    -613    """
    -614    return FlatIterator(iterable)
    +            
    559def into_iter(
    +560    iterable: collections.Iterable[Item],
    +561) -> Iterator[Item]:
    +562    """Transform an iterable into an flat iterator.
    +563
    +564    Example
    +565    -------
    +566    ```py
    +567    sequence = [1,2,3]
    +568    for item in aiobungie.into_iter(sequence).reversed():
    +569        print(item)
    +570    # 3
    +571    # 2
    +572    # 1
    +573    ```
    +574
    +575    Parameters
    +576    ----------
    +577    iterable: `typing.Iterable[Item]`
    +578        The iterable to convert.
    +579
    +580    Raises
    +581    ------
    +582    `StopIteration`
    +583        If no elements are left in the iterator.
    +584    """
    +585    return Iterator(iterable)
     
    @@ -32986,13 +27230,15 @@
    Inherited Members
    Example
    -
    sequence = [1,2,3]
    +
    +
    sequence = [1,2,3]
     for item in aiobungie.into_iter(sequence).reversed():
         print(item)
     # 3
     # 2
     # 1
    -
    +
    +
    Parameters
    @@ -33313,7 +27559,11 @@
    Raises
    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/builders.html b/docs/aiobungie/builders.html index e30365fd..575b8473 100644 --- a/docs/aiobungie/builders.html +++ b/docs/aiobungie/builders.html @@ -3,7 +3,7 @@ - + aiobungie.builders API documentation @@ -81,6 +81,27 @@

    API Documentation

    +
  • + OAuthURL + + +
  • @@ -100,9 +121,9 @@

    Objects that helps building entities to be sent/received to/from the API.

    - + - +
      1# MIT License
       2#
    @@ -129,136 +150,174 @@ 

    23 24from __future__ import annotations 25 - 26__all__: tuple[str, ...] = ("OAuth2Response", "PlugSocketBuilder") + 26__all__: tuple[str, ...] = ("OAuth2Response", "PlugSocketBuilder", "OAuthURL") 27 28import typing - 29 - 30import attrs - 31 - 32if typing.TYPE_CHECKING: - 33 from aiobungie import typedefs + 29import uuid + 30 + 31import attrs + 32 + 33from aiobungie import url 34 - 35 - 36@attrs.mutable(kw_only=True, repr=False) - 37class OAuth2Response: - 38 """Represents a proxy object for returned information from an OAuth2 successful response.""" - 39 - 40 access_token: str - 41 """The returned OAuth2 `access_token` field.""" + 35if typing.TYPE_CHECKING: + 36 from aiobungie import typedefs + 37 + 38 + 39@attrs.mutable(kw_only=True, repr=False) + 40class OAuth2Response: + 41 """Represents a proxy object for returned information from an OAuth2 successful response.""" 42 - 43 refresh_token: str - 44 """The returned OAuth2 `refresh_token` field.""" + 43 access_token: str + 44 """The returned OAuth2 `access_token` field.""" 45 - 46 expires_in: int - 47 """The returned OAuth2 `expires_in` field.""" + 46 refresh_token: str + 47 """The returned OAuth2 `refresh_token` field.""" 48 - 49 token_type: str - 50 """The returned OAuth2 `token_type` field. This is usually just `Bearer`""" + 49 expires_in: int + 50 """The returned OAuth2 `expires_in` field.""" 51 - 52 refresh_expires_in: int - 53 """The returned OAuth2 `refresh_expires_in` field.""" + 52 token_type: str + 53 """The returned OAuth2 `token_type` field. This is usually just `Bearer`""" 54 - 55 membership_id: int - 56 """The returned BungieNet membership id for the authorized user.""" + 55 refresh_expires_in: int + 56 """The returned OAuth2 `refresh_expires_in` field.""" 57 - 58 @classmethod - 59 def build_response(cls, payload: typedefs.JSONObject, /) -> OAuth2Response: - 60 """Deserialize and builds the JSON object into this object.""" - 61 return OAuth2Response( - 62 access_token=payload["access_token"], - 63 refresh_token=payload["refresh_token"], - 64 expires_in=int(payload["expires_in"]), - 65 token_type=payload["token_type"], - 66 refresh_expires_in=payload["refresh_expires_in"], - 67 membership_id=int(payload["membership_id"]), - 68 ) - 69 - 70 - 71class PlugSocketBuilder: - 72 """A helper for building insert socket plugs. + 58 membership_id: int + 59 """The returned BungieNet membership id for the authorized user.""" + 60 + 61 @classmethod + 62 def build_response(cls, payload: typedefs.JSONObject, /) -> OAuth2Response: + 63 """Deserialize and builds the JSON object into this object.""" + 64 return OAuth2Response( + 65 access_token=payload["access_token"], + 66 refresh_token=payload["refresh_token"], + 67 expires_in=int(payload["expires_in"]), + 68 token_type=payload["token_type"], + 69 refresh_expires_in=payload["refresh_expires_in"], + 70 membership_id=int(payload["membership_id"]), + 71 ) + 72 73 - 74 Example - 75 ------- - 76 ```py - 77 import aiobungie - 78 - 79 rest = aiobungie.RESTClient(...) - 80 plug = ( - 81 aiobungie.builders.PlugSocketBuilder() - 82 .set_socket_array(0) - 83 .set_socket_index(0) - 84 .set_plug_item(3023847) - 85 .collect() - 86 ) - 87 await rest.insert_socket_plug_free(..., plug=plug) - 88 ``` - 89 """ - 90 - 91 __slots__ = ("_map",) + 74@attrs.define(kw_only=True) + 75class OAuthURL: + 76 """The result of calling `aiobungie.RESTClient.build_oauth2_url`. + 77 + 78 Example + 79 ------- + 80 ```py + 81 url = aiobungie.builders.OAuthURL(client_id=1234) + 82 print(url.compile()) # Full URL to make an OAuth2 request. + 83 print(url.state) # The UUID state to be used in the OAuth2 request. + 84 ``` + 85 """ + 86 + 87 state: uuid.UUID = attrs.field(factory=uuid.uuid4) + 88 """The state parameter for the URL.""" + 89 + 90 client_id: int + 91 """The client id for that's making the request.""" 92 - 93 def __init__(self, map: typing.Optional[dict[str, int]] = None, /) -> None: - 94 self._map = map or {} - 95 - 96 def set_socket_array( - 97 self, socket_type: typing.Literal[0, 1], / - 98 ) -> PlugSocketBuilder: - 99 """Set the array socket type. -100 -101 Parameters -102 ---------- -103 socket_type : `typing.Literal[0, 1]` -104 Either 0, or 1. If set to 0 it will be the default, -105 Otherwise if 1 it will be Intrinsic. -106 -107 Returns -108 ------- -109 `Self` -110 The class itself to allow chained methods. -111 """ -112 self._map["socketArrayType"] = socket_type -113 return self -114 -115 def set_socket_index(self, index: int, /) -> PlugSocketBuilder: -116 """Set the socket index into the array. -117 -118 Parameters -119 ---------- -120 index : `int` -121 The socket index. -122 -123 Returns -124 ------- -125 `Self` -126 The class itself to allow chained methods. -127 """ -128 self._map["socketIndex"] = index -129 return self + 93 @property + 94 def url(self) -> str: + 95 """An alias for `OAuthURL.compile`.""" + 96 return self.compile() + 97 + 98 def compile(self) -> str: + 99 """Compiles the URL to finallize the result of the URL.""" +100 return ( +101 url.OAUTH_EP +102 + f"?client_id={self.client_id}&response_type=code&state={self.state}" # noqa: W503 +103 ) +104 +105 def __str__(self) -> str: +106 return self.compile() +107 +108 +109class PlugSocketBuilder: +110 """A helper for building insert socket plugs. +111 +112 Example +113 ------- +114 ```py +115 import aiobungie +116 +117 rest = aiobungie.RESTClient(...) +118 plug = ( +119 aiobungie.builders.PlugSocketBuilder() +120 .set_socket_array(0) +121 .set_socket_index(0) +122 .set_plug_item(3023847) +123 .collect() +124 ) +125 await rest.insert_socket_plug_free(..., plug=plug) +126 ``` +127 """ +128 +129 __slots__ = ("_map",) 130 -131 def set_plug_item(self, item_hash: int, /) -> PlugSocketBuilder: -132 """Set the socket index into the array. +131 def __init__(self, map: typing.Optional[dict[str, int]] = None, /) -> None: +132 self._map = map or {} 133 -134 Parameters -135 ---------- -136 item_hash : `int` -137 The hash of the item to plug. +134 def set_socket_array( +135 self, socket_type: typing.Literal[0, 1], / +136 ) -> PlugSocketBuilder: +137 """Set the array socket type. 138 -139 Returns -140 ------- -141 `Self` -142 The class itself to allow chained methods. -143 """ -144 self._map["plugItemHash"] = item_hash -145 return self -146 -147 def collect(self) -> dict[str, int]: -148 """Collect the set values and return its map to be passed to the request. -149 -150 Returns -151 ------- -152 `dict[str, int]` -153 The built map. -154 """ -155 return self._map +139 Parameters +140 ---------- +141 socket_type : `typing.Literal[0, 1]` +142 Either 0, or 1. If set to 0 it will be the default, +143 Otherwise if 1 it will be Intrinsic. +144 +145 Returns +146 ------- +147 `Self` +148 The class itself to allow chained methods. +149 """ +150 self._map["socketArrayType"] = socket_type +151 return self +152 +153 def set_socket_index(self, index: int, /) -> PlugSocketBuilder: +154 """Set the socket index into the array. +155 +156 Parameters +157 ---------- +158 index : `int` +159 The socket index. +160 +161 Returns +162 ------- +163 `Self` +164 The class itself to allow chained methods. +165 """ +166 self._map["socketIndex"] = index +167 return self +168 +169 def set_plug_item(self, item_hash: int, /) -> PlugSocketBuilder: +170 """Set the socket index into the array. +171 +172 Parameters +173 ---------- +174 item_hash : `int` +175 The hash of the item to plug. +176 +177 Returns +178 ------- +179 `Self` +180 The class itself to allow chained methods. +181 """ +182 self._map["plugItemHash"] = item_hash +183 return self +184 +185 def collect(self) -> dict[str, int]: +186 """Collect the set values and return its map to be passed to the request. +187 +188 Returns +189 ------- +190 `dict[str, int]` +191 The built map. +192 """ +193 return self._map

    @@ -275,39 +334,39 @@

    -
    37@attrs.mutable(kw_only=True, repr=False)
    -38class OAuth2Response:
    -39    """Represents a proxy object for returned information from an OAuth2 successful response."""
    -40
    -41    access_token: str
    -42    """The returned OAuth2 `access_token` field."""
    +            
    40@attrs.mutable(kw_only=True, repr=False)
    +41class OAuth2Response:
    +42    """Represents a proxy object for returned information from an OAuth2 successful response."""
     43
    -44    refresh_token: str
    -45    """The returned OAuth2 `refresh_token` field."""
    +44    access_token: str
    +45    """The returned OAuth2 `access_token` field."""
     46
    -47    expires_in: int
    -48    """The returned OAuth2 `expires_in` field."""
    +47    refresh_token: str
    +48    """The returned OAuth2 `refresh_token` field."""
     49
    -50    token_type: str
    -51    """The returned OAuth2 `token_type` field. This is usually just `Bearer`"""
    +50    expires_in: int
    +51    """The returned OAuth2 `expires_in` field."""
     52
    -53    refresh_expires_in: int
    -54    """The returned OAuth2 `refresh_expires_in` field."""
    +53    token_type: str
    +54    """The returned OAuth2 `token_type` field. This is usually just `Bearer`"""
     55
    -56    membership_id: int
    -57    """The returned BungieNet membership id for the authorized user."""
    +56    refresh_expires_in: int
    +57    """The returned OAuth2 `refresh_expires_in` field."""
     58
    -59    @classmethod
    -60    def build_response(cls, payload: typedefs.JSONObject, /) -> OAuth2Response:
    -61        """Deserialize and builds the JSON object into this object."""
    -62        return OAuth2Response(
    -63            access_token=payload["access_token"],
    -64            refresh_token=payload["refresh_token"],
    -65            expires_in=int(payload["expires_in"]),
    -66            token_type=payload["token_type"],
    -67            refresh_expires_in=payload["refresh_expires_in"],
    -68            membership_id=int(payload["membership_id"]),
    -69        )
    +59    membership_id: int
    +60    """The returned BungieNet membership id for the authorized user."""
    +61
    +62    @classmethod
    +63    def build_response(cls, payload: typedefs.JSONObject, /) -> OAuth2Response:
    +64        """Deserialize and builds the JSON object into this object."""
    +65        return OAuth2Response(
    +66            access_token=payload["access_token"],
    +67            refresh_token=payload["refresh_token"],
    +68            expires_in=int(payload["expires_in"]),
    +69            token_type=payload["token_type"],
    +70            refresh_expires_in=payload["refresh_expires_in"],
    +71            membership_id=int(payload["membership_id"]),
    +72        )
     
    @@ -430,17 +489,17 @@

    -
    59    @classmethod
    -60    def build_response(cls, payload: typedefs.JSONObject, /) -> OAuth2Response:
    -61        """Deserialize and builds the JSON object into this object."""
    -62        return OAuth2Response(
    -63            access_token=payload["access_token"],
    -64            refresh_token=payload["refresh_token"],
    -65            expires_in=int(payload["expires_in"]),
    -66            token_type=payload["token_type"],
    -67            refresh_expires_in=payload["refresh_expires_in"],
    -68            membership_id=int(payload["membership_id"]),
    -69        )
    +            
    62    @classmethod
    +63    def build_response(cls, payload: typedefs.JSONObject, /) -> OAuth2Response:
    +64        """Deserialize and builds the JSON object into this object."""
    +65        return OAuth2Response(
    +66            access_token=payload["access_token"],
    +67            refresh_token=payload["refresh_token"],
    +68            expires_in=int(payload["expires_in"]),
    +69            token_type=payload["token_type"],
    +70            refresh_expires_in=payload["refresh_expires_in"],
    +71            membership_id=int(payload["membership_id"]),
    +72        )
     
    @@ -461,91 +520,91 @@

    -
     72class PlugSocketBuilder:
    - 73    """A helper for building insert socket plugs.
    - 74
    - 75    Example
    - 76    -------
    - 77    ```py
    - 78    import aiobungie
    - 79
    - 80    rest = aiobungie.RESTClient(...)
    - 81    plug = (
    - 82        aiobungie.builders.PlugSocketBuilder()
    - 83        .set_socket_array(0)
    - 84        .set_socket_index(0)
    - 85        .set_plug_item(3023847)
    - 86        .collect()
    - 87    )
    - 88    await rest.insert_socket_plug_free(..., plug=plug)
    - 89    ```
    - 90    """
    - 91
    - 92    __slots__ = ("_map",)
    - 93
    - 94    def __init__(self, map: typing.Optional[dict[str, int]] = None, /) -> None:
    - 95        self._map = map or {}
    - 96
    - 97    def set_socket_array(
    - 98        self, socket_type: typing.Literal[0, 1], /
    - 99    ) -> PlugSocketBuilder:
    -100        """Set the array socket type.
    -101
    -102        Parameters
    -103        ----------
    -104        socket_type : `typing.Literal[0, 1]`
    -105            Either 0, or 1. If set to 0 it will be the default,
    -106            Otherwise if 1 it will be Intrinsic.
    -107
    -108        Returns
    -109        -------
    -110        `Self`
    -111            The class itself to allow chained methods.
    -112        """
    -113        self._map["socketArrayType"] = socket_type
    -114        return self
    -115
    -116    def set_socket_index(self, index: int, /) -> PlugSocketBuilder:
    -117        """Set the socket index into the array.
    -118
    -119        Parameters
    -120        ----------
    -121        index : `int`
    -122            The socket index.
    -123
    -124        Returns
    -125        -------
    -126        `Self`
    -127            The class itself to allow chained methods.
    -128        """
    -129        self._map["socketIndex"] = index
    -130        return self
    +            
    110class PlugSocketBuilder:
    +111    """A helper for building insert socket plugs.
    +112
    +113    Example
    +114    -------
    +115    ```py
    +116    import aiobungie
    +117
    +118    rest = aiobungie.RESTClient(...)
    +119    plug = (
    +120        aiobungie.builders.PlugSocketBuilder()
    +121        .set_socket_array(0)
    +122        .set_socket_index(0)
    +123        .set_plug_item(3023847)
    +124        .collect()
    +125    )
    +126    await rest.insert_socket_plug_free(..., plug=plug)
    +127    ```
    +128    """
    +129
    +130    __slots__ = ("_map",)
     131
    -132    def set_plug_item(self, item_hash: int, /) -> PlugSocketBuilder:
    -133        """Set the socket index into the array.
    +132    def __init__(self, map: typing.Optional[dict[str, int]] = None, /) -> None:
    +133        self._map = map or {}
     134
    -135        Parameters
    -136        ----------
    -137        item_hash : `int`
    -138            The hash of the item to plug.
    +135    def set_socket_array(
    +136        self, socket_type: typing.Literal[0, 1], /
    +137    ) -> PlugSocketBuilder:
    +138        """Set the array socket type.
     139
    -140        Returns
    -141        -------
    -142        `Self`
    -143            The class itself to allow chained methods.
    -144        """
    -145        self._map["plugItemHash"] = item_hash
    -146        return self
    -147
    -148    def collect(self) -> dict[str, int]:
    -149        """Collect the set values and return its map to be passed to the request.
    -150
    -151        Returns
    -152        -------
    -153        `dict[str, int]`
    -154            The built map.
    -155        """
    -156        return self._map
    +140        Parameters
    +141        ----------
    +142        socket_type : `typing.Literal[0, 1]`
    +143            Either 0, or 1. If set to 0 it will be the default,
    +144            Otherwise if 1 it will be Intrinsic.
    +145
    +146        Returns
    +147        -------
    +148        `Self`
    +149            The class itself to allow chained methods.
    +150        """
    +151        self._map["socketArrayType"] = socket_type
    +152        return self
    +153
    +154    def set_socket_index(self, index: int, /) -> PlugSocketBuilder:
    +155        """Set the socket index into the array.
    +156
    +157        Parameters
    +158        ----------
    +159        index : `int`
    +160            The socket index.
    +161
    +162        Returns
    +163        -------
    +164        `Self`
    +165            The class itself to allow chained methods.
    +166        """
    +167        self._map["socketIndex"] = index
    +168        return self
    +169
    +170    def set_plug_item(self, item_hash: int, /) -> PlugSocketBuilder:
    +171        """Set the socket index into the array.
    +172
    +173        Parameters
    +174        ----------
    +175        item_hash : `int`
    +176            The hash of the item to plug.
    +177
    +178        Returns
    +179        -------
    +180        `Self`
    +181            The class itself to allow chained methods.
    +182        """
    +183        self._map["plugItemHash"] = item_hash
    +184        return self
    +185
    +186    def collect(self) -> dict[str, int]:
    +187        """Collect the set values and return its map to be passed to the request.
    +188
    +189        Returns
    +190        -------
    +191        `dict[str, int]`
    +192            The built map.
    +193        """
    +194        return self._map
     
    @@ -553,7 +612,8 @@

    Example
    -
    import aiobungie
    +
    +
    import aiobungie
     
     rest = aiobungie.RESTClient(...)
     plug = (
    @@ -564,7 +624,8 @@ 
    Example
    .collect() ) await rest.insert_socket_plug_free(..., plug=plug) -
    +
    +
    @@ -578,8 +639,8 @@
    Example
    -
    94    def __init__(self, map: typing.Optional[dict[str, int]] = None, /) -> None:
    -95        self._map = map or {}
    +            
    132    def __init__(self, map: typing.Optional[dict[str, int]] = None, /) -> None:
    +133        self._map = map or {}
     
    @@ -597,24 +658,24 @@
    Example
    -
     97    def set_socket_array(
    - 98        self, socket_type: typing.Literal[0, 1], /
    - 99    ) -> PlugSocketBuilder:
    -100        """Set the array socket type.
    -101
    -102        Parameters
    -103        ----------
    -104        socket_type : `typing.Literal[0, 1]`
    -105            Either 0, or 1. If set to 0 it will be the default,
    -106            Otherwise if 1 it will be Intrinsic.
    -107
    -108        Returns
    -109        -------
    -110        `Self`
    -111            The class itself to allow chained methods.
    -112        """
    -113        self._map["socketArrayType"] = socket_type
    -114        return self
    +            
    135    def set_socket_array(
    +136        self, socket_type: typing.Literal[0, 1], /
    +137    ) -> PlugSocketBuilder:
    +138        """Set the array socket type.
    +139
    +140        Parameters
    +141        ----------
    +142        socket_type : `typing.Literal[0, 1]`
    +143            Either 0, or 1. If set to 0 it will be the default,
    +144            Otherwise if 1 it will be Intrinsic.
    +145
    +146        Returns
    +147        -------
    +148        `Self`
    +149            The class itself to allow chained methods.
    +150        """
    +151        self._map["socketArrayType"] = socket_type
    +152        return self
     
    @@ -648,21 +709,21 @@
    Returns
    -
    116    def set_socket_index(self, index: int, /) -> PlugSocketBuilder:
    -117        """Set the socket index into the array.
    -118
    -119        Parameters
    -120        ----------
    -121        index : `int`
    -122            The socket index.
    -123
    -124        Returns
    -125        -------
    -126        `Self`
    -127            The class itself to allow chained methods.
    -128        """
    -129        self._map["socketIndex"] = index
    -130        return self
    +            
    154    def set_socket_index(self, index: int, /) -> PlugSocketBuilder:
    +155        """Set the socket index into the array.
    +156
    +157        Parameters
    +158        ----------
    +159        index : `int`
    +160            The socket index.
    +161
    +162        Returns
    +163        -------
    +164        `Self`
    +165            The class itself to allow chained methods.
    +166        """
    +167        self._map["socketIndex"] = index
    +168        return self
     
    @@ -695,21 +756,21 @@
    Returns
    -
    132    def set_plug_item(self, item_hash: int, /) -> PlugSocketBuilder:
    -133        """Set the socket index into the array.
    -134
    -135        Parameters
    -136        ----------
    -137        item_hash : `int`
    -138            The hash of the item to plug.
    -139
    -140        Returns
    -141        -------
    -142        `Self`
    -143            The class itself to allow chained methods.
    -144        """
    -145        self._map["plugItemHash"] = item_hash
    -146        return self
    +            
    170    def set_plug_item(self, item_hash: int, /) -> PlugSocketBuilder:
    +171        """Set the socket index into the array.
    +172
    +173        Parameters
    +174        ----------
    +175        item_hash : `int`
    +176            The hash of the item to plug.
    +177
    +178        Returns
    +179        -------
    +180        `Self`
    +181            The class itself to allow chained methods.
    +182        """
    +183        self._map["plugItemHash"] = item_hash
    +184        return self
     
    @@ -742,15 +803,15 @@
    Returns
    -
    148    def collect(self) -> dict[str, int]:
    -149        """Collect the set values and return its map to be passed to the request.
    -150
    -151        Returns
    -152        -------
    -153        `dict[str, int]`
    -154            The built map.
    -155        """
    -156        return self._map
    +            
    186    def collect(self) -> dict[str, int]:
    +187        """Collect the set values and return its map to be passed to the request.
    +188
    +189        Returns
    +190        -------
    +191        `dict[str, int]`
    +192            The built map.
    +193        """
    +194        return self._map
     
    @@ -764,6 +825,156 @@
    Returns
    +
    + +
    + +
    +
    @attrs.define(kw_only=True)
    + + class + OAuthURL: + + + +
    + +
     75@attrs.define(kw_only=True)
    + 76class OAuthURL:
    + 77    """The result of calling `aiobungie.RESTClient.build_oauth2_url`.
    + 78
    + 79    Example
    + 80    -------
    + 81    ```py
    + 82    url = aiobungie.builders.OAuthURL(client_id=1234)
    + 83    print(url.compile()) # Full URL to make an OAuth2 request.
    + 84    print(url.state)  # The UUID state to be used in the OAuth2 request.
    + 85    ```
    + 86    """
    + 87
    + 88    state: uuid.UUID = attrs.field(factory=uuid.uuid4)
    + 89    """The state parameter for the URL."""
    + 90
    + 91    client_id: int
    + 92    """The client id for that's making the request."""
    + 93
    + 94    @property
    + 95    def url(self) -> str:
    + 96        """An alias for `OAuthURL.compile`."""
    + 97        return self.compile()
    + 98
    + 99    def compile(self) -> str:
    +100        """Compiles the URL to finallize the result of the URL."""
    +101        return (
    +102            url.OAUTH_EP
    +103            + f"?client_id={self.client_id}&response_type=code&state={self.state}"  # noqa: W503
    +104        )
    +105
    +106    def __str__(self) -> str:
    +107        return self.compile()
    +
    + + +

    The result of calling aiobungie.RESTClient.build_oauth2_url.

    + +
    Example
    + +
    +
    url = aiobungie.builders.OAuthURL(client_id=1234)
    +print(url.compile()) # Full URL to make an OAuth2 request.
    +print(url.state)  # The UUID state to be used in the OAuth2 request.
    +
    +
    +
    + + +
    + +
    + + OAuthURL(*, state: uuid.UUID = NOTHING, client_id: int) + + + +
    + +
    2def __init__(self, *, state=NOTHING, client_id):
    +3    if state is not NOTHING:
    +4        self.state = state
    +5    else:
    +6        self.state = __attr_factory_state()
    +7    self.client_id = client_id
    +
    + + +

    Method generated by attrs for class OAuthURL.

    +
    + + +
    +
    +
    + state: uuid.UUID + + +
    + + +

    The state parameter for the URL.

    +
    + + +
    +
    +
    + client_id: int + + +
    + + +

    The client id for that's making the request.

    +
    + + +
    +
    +
    + url: str + + +
    + + +

    An alias for OAuthURL.compile.

    +
    + + +
    +
    + +
    + + def + compile(self) -> str: + + + +
    + +
     99    def compile(self) -> str:
    +100        """Compiles the URL to finallize the result of the URL."""
    +101        return (
    +102            url.OAUTH_EP
    +103            + f"?client_id={self.client_id}&response_type=code&state={self.state}"  # noqa: W503
    +104        )
    +
    + + +

    Compiles the URL to finallize the result of the URL.

    +
    + +
    @@ -869,7 +1080,11 @@
    Returns
    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/client.html b/docs/aiobungie/client.html index 07da43d4..7187c0a1 100644 --- a/docs/aiobungie/client.html +++ b/docs/aiobungie/client.html @@ -3,7 +3,7 @@ - + aiobungie.client API documentation @@ -181,9 +181,9 @@

    Standard aiobungie API client implementation.

    - + - +
       1# MIT License
        2#
    @@ -401,7 +401,7 @@ 

    214 215 async def search_users( 216 self, name: str, / - 217 ) -> iterators.FlatIterator[user.SearchableDestinyUser]: + 217 ) -> iterators.Iterator[user.SearchableDestinyUser]: 218 """Search for players and return all players that matches the same name. 219 220 Parameters @@ -411,12 +411,12 @@

    224 225 Returns 226 ------- - 227 `aiobungie.iterators.FlatIterator[aiobungie.crates.DestinyMembership]` + 227 `aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]` 228 A sequence of destiny memberships. 229 """ 230 payload = await self.rest.search_users(name) 231 - 232 return iterators.FlatIterator( + 232 return iterators.Iterator( 233 [ 234 self.factory.deserialize_searched_user(user) 235 for user in payload["searchResults"] @@ -731,7 +731,7 @@

    544 ] = enums.MembershipType.ALL, 545 page: int = 0, 546 limit: int = 250, - 547 ) -> iterators.FlatIterator[activity.Activity]: + 547 ) -> iterators.Iterator[activity.Activity]: 548 """Fetch a Destiny 2 activity for the specified character id. 549 550 Parameters @@ -754,7 +754,7 @@

    567 568 Returns 569 ------- - 570 `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]` + 570 `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` 571 An iterator of the player's activities. 572 573 Raises @@ -795,7 +795,7 @@

    608 character_id: int, 609 membership_id: int, 610 membership_type: typedefs.IntAnd[enums.MembershipType], - 611 ) -> iterators.FlatIterator[activity.AggregatedActivity]: + 611 ) -> iterators.Iterator[activity.AggregatedActivity]: 612 """Fetch aggregated activity stats for a character. 613 614 Parameters @@ -809,7 +809,7 @@

    622 623 Returns 624 ------- - 625 `aiobungie.iterators.FlatIterator[aiobungie.crates.AggregatedActivity]` + 625 `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]` 626 An iterator of the player's activities. 627 628 Raises @@ -913,7 +913,7 @@

    726 727 async def fetch_clan_admins( 728 self, clan_id: int, / - 729 ) -> iterators.FlatIterator[clans.ClanMember]: + 729 ) -> iterators.Iterator[clans.ClanMember]: 730 """Fetch the clan founder and admins. 731 732 Parameters @@ -923,7 +923,7 @@

    736 737 Returns 738 ------- - 739 `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]` + 739 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 740 An iterator over the found clan admins and founder. 741 742 Raises @@ -1020,7 +1020,7 @@

    833 *, 834 name: typing.Optional[str] = None, 835 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, - 836 ) -> iterators.FlatIterator[clans.ClanMember]: + 836 ) -> iterators.Iterator[clans.ClanMember]: 837 """Fetch Bungie clan members. 838 839 Parameters @@ -1040,7 +1040,7 @@

    853 854 Returns 855 ------- - 856 `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]` + 856 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 857 An iterator over the bungie clan members. 858 859 Raises @@ -1159,7 +1159,7 @@

    972 973 async def search_entities( 974 self, name: str, entity_type: str, *, page: int = 0 - 975 ) -> iterators.FlatIterator[entity.SearchableEntity]: + 975 ) -> iterators.Iterator[entity.SearchableEntity]: 976 """Search for Destiny2 entities given a name and its type. 977 978 Parameters @@ -1177,7 +1177,7 @@

    990 991 Returns 992 ------- - 993 `aiobungie.iterators.FlatIterator[aiobungie.crates.SearchableEntity]` + 993 `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]` 994 An iterator over the found results matching the provided name. 995 """ 996 resp = await self.rest.search_entities(name, entity_type, page=page) @@ -1646,7 +1646,7 @@

    215 216 async def search_users( 217 self, name: str, / - 218 ) -> iterators.FlatIterator[user.SearchableDestinyUser]: + 218 ) -> iterators.Iterator[user.SearchableDestinyUser]: 219 """Search for players and return all players that matches the same name. 220 221 Parameters @@ -1656,12 +1656,12 @@

    225 226 Returns 227 ------- - 228 `aiobungie.iterators.FlatIterator[aiobungie.crates.DestinyMembership]` + 228 `aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]` 229 A sequence of destiny memberships. 230 """ 231 payload = await self.rest.search_users(name) 232 - 233 return iterators.FlatIterator( + 233 return iterators.Iterator( 234 [ 235 self.factory.deserialize_searched_user(user) 236 for user in payload["searchResults"] @@ -1976,7 +1976,7 @@

    545 ] = enums.MembershipType.ALL, 546 page: int = 0, 547 limit: int = 250, - 548 ) -> iterators.FlatIterator[activity.Activity]: + 548 ) -> iterators.Iterator[activity.Activity]: 549 """Fetch a Destiny 2 activity for the specified character id. 550 551 Parameters @@ -1999,7 +1999,7 @@

    568 569 Returns 570 ------- - 571 `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]` + 571 `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` 572 An iterator of the player's activities. 573 574 Raises @@ -2040,7 +2040,7 @@

    609 character_id: int, 610 membership_id: int, 611 membership_type: typedefs.IntAnd[enums.MembershipType], - 612 ) -> iterators.FlatIterator[activity.AggregatedActivity]: + 612 ) -> iterators.Iterator[activity.AggregatedActivity]: 613 """Fetch aggregated activity stats for a character. 614 615 Parameters @@ -2054,7 +2054,7 @@

    623 624 Returns 625 ------- - 626 `aiobungie.iterators.FlatIterator[aiobungie.crates.AggregatedActivity]` + 626 `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]` 627 An iterator of the player's activities. 628 629 Raises @@ -2158,7 +2158,7 @@

    727 728 async def fetch_clan_admins( 729 self, clan_id: int, / - 730 ) -> iterators.FlatIterator[clans.ClanMember]: + 730 ) -> iterators.Iterator[clans.ClanMember]: 731 """Fetch the clan founder and admins. 732 733 Parameters @@ -2168,7 +2168,7 @@

    737 738 Returns 739 ------- - 740 `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]` + 740 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 741 An iterator over the found clan admins and founder. 742 743 Raises @@ -2265,7 +2265,7 @@

    834 *, 835 name: typing.Optional[str] = None, 836 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, - 837 ) -> iterators.FlatIterator[clans.ClanMember]: + 837 ) -> iterators.Iterator[clans.ClanMember]: 838 """Fetch Bungie clan members. 839 840 Parameters @@ -2285,7 +2285,7 @@

    854 855 Returns 856 ------- - 857 `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]` + 857 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 858 An iterator over the bungie clan members. 859 860 Raises @@ -2404,7 +2404,7 @@

    973 974 async def search_entities( 975 self, name: str, entity_type: str, *, page: int = 0 - 976 ) -> iterators.FlatIterator[entity.SearchableEntity]: + 976 ) -> iterators.Iterator[entity.SearchableEntity]: 977 """Search for Destiny2 entities given a name and its type. 978 979 Parameters @@ -2422,7 +2422,7 @@

    991 992 Returns 993 ------- - 994 `aiobungie.iterators.FlatIterator[aiobungie.crates.SearchableEntity]` + 994 `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]` 995 An iterator over the found results matching the provided name. 996 """ 997 resp = await self.rest.search_entities(name, entity_type, page=page) @@ -2731,7 +2731,8 @@

    Example
    -
    import aiobungie
    +
    +
    import aiobungie
     
     client = aiobungie.Client('...')
     
    @@ -2739,7 +2740,8 @@ 
    Example
    async with client.rest: user = await client.fetch_current_user_memberships('...') print(user) -
    +
    +
    Parameters
    @@ -2908,12 +2910,14 @@
    Parameters
    Example
    -
    async def main() -> None:
    +
    +
    async def main() -> None:
         await fetch(...)
     
     # Run the coroutine.
     client.run(main())
    -
    +
    +

    @@ -3050,7 +3054,7 @@

    Raises
    async def - search_users( self, name: str, /) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.user.SearchableDestinyUser]: + search_users( self, name: str, /) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.user.SearchableDestinyUser]: @@ -3058,7 +3062,7 @@
    Raises
    216    async def search_users(
     217        self, name: str, /
    -218    ) -> iterators.FlatIterator[user.SearchableDestinyUser]:
    +218    ) -> iterators.Iterator[user.SearchableDestinyUser]:
     219        """Search for players and return all players that matches the same name.
     220
     221        Parameters
    @@ -3068,12 +3072,12 @@ 
    Raises
    225 226 Returns 227 ------- -228 `aiobungie.iterators.FlatIterator[aiobungie.crates.DestinyMembership]` +228 `aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]` 229 A sequence of destiny memberships. 230 """ 231 payload = await self.rest.search_users(name) 232 -233 return iterators.FlatIterator( +233 return iterators.Iterator( 234 [ 235 self.factory.deserialize_searched_user(user) 236 for user in payload["searchResults"] @@ -3094,7 +3098,7 @@
    Parameters
    Returns
    @@ -3182,7 +3186,7 @@
    Returns

    Gets any hard linked membership given a credential. -Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now. +Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now. Cross Save aware.

    Parameters
    @@ -3776,7 +3780,7 @@
    Returns
    async def - fetch_activities( self, member_id: int, character_id: int, mode: Union[int, aiobungie.internal.enums.GameMode], *, membership_type: Union[int, aiobungie.internal.enums.MembershipType] = <MembershipType.ALL: -1>, page: int = 0, limit: int = 250) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.activity.Activity]: + fetch_activities( self, member_id: int, character_id: int, mode: Union[int, aiobungie.internal.enums.GameMode], *, membership_type: Union[int, aiobungie.internal.enums.MembershipType] = <MembershipType.ALL: -1>, page: int = 0, limit: int = 250) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.activity.Activity]: @@ -3793,7 +3797,7 @@
    Returns
    545 ] = enums.MembershipType.ALL, 546 page: int = 0, 547 limit: int = 250, -548 ) -> iterators.FlatIterator[activity.Activity]: +548 ) -> iterators.Iterator[activity.Activity]: 549 """Fetch a Destiny 2 activity for the specified character id. 550 551 Parameters @@ -3816,7 +3820,7 @@
    Returns
    568 569 Returns 570 ------- -571 `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]` +571 `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` 572 An iterator of the player's activities. 573 574 Raises @@ -3864,7 +3868,7 @@
    Other Parameters
    Returns
    Raises
    @@ -3929,7 +3933,7 @@
    Returns
    async def - fetch_aggregated_activity_stats( self, character_id: int, membership_id: int, membership_type: Union[int, aiobungie.internal.enums.MembershipType]) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.activity.AggregatedActivity]: + fetch_aggregated_activity_stats( self, character_id: int, membership_id: int, membership_type: Union[int, aiobungie.internal.enums.MembershipType]) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.activity.AggregatedActivity]: @@ -3940,7 +3944,7 @@
    Returns
    609 character_id: int, 610 membership_id: int, 611 membership_type: typedefs.IntAnd[enums.MembershipType], -612 ) -> iterators.FlatIterator[activity.AggregatedActivity]: +612 ) -> iterators.Iterator[activity.AggregatedActivity]: 613 """Fetch aggregated activity stats for a character. 614 615 Parameters @@ -3954,7 +3958,7 @@
    Returns
    623 624 Returns 625 ------- -626 `aiobungie.iterators.FlatIterator[aiobungie.crates.AggregatedActivity]` +626 `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]` 627 An iterator of the player's activities. 628 629 Raises @@ -3986,7 +3990,7 @@
    Parameters
    Returns
    Raises
    @@ -4136,7 +4140,7 @@
    Other Parameters
    This field aiobungie.crates.Clan.current_user_membership will be available and will return the membership of the user who made this request.

  • type (aiobungie.GroupType): -The group type, Default is aiobungie.GroupType.CLAN.
  • +The group type, Default is aiobungie.GroupType.CLAN.
    Returns
    @@ -4204,7 +4208,7 @@
    Parameters
    async def - fetch_clan_admins( self, clan_id: int, /) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.clans.ClanMember]: + fetch_clan_admins( self, clan_id: int, /) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.clans.ClanMember]: @@ -4212,7 +4216,7 @@
    Parameters
    728    async def fetch_clan_admins(
     729        self, clan_id: int, /
    -730    ) -> iterators.FlatIterator[clans.ClanMember]:
    +730    ) -> iterators.Iterator[clans.ClanMember]:
     731        """Fetch the clan founder and admins.
     732
     733        Parameters
    @@ -4222,7 +4226,7 @@ 
    Parameters
    737 738 Returns 739 ------- -740 `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]` +740 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 741 An iterator over the found clan admins and founder. 742 743 Raises @@ -4248,7 +4252,7 @@
    Parameters
    Returns
    Raises
    @@ -4330,7 +4334,7 @@
    Other Parameters
    Filter apply to list of joined groups. This Default to 0
  • group_type (aiobungie.GroupType): The group's type. -This is always set to aiobungie.GroupType.CLAN and should not be changed.
  • +This is always set to aiobungie.GroupType.CLAN and should not be changed.
    Returns
    @@ -4412,7 +4416,7 @@
    Other Parameters
    Filter apply to list of joined groups. This Default to 0
  • group_type (aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. -This is always set to aiobungie.GroupType.CLAN and should not be changed.
  • +This is always set to aiobungie.GroupType.CLAN and should not be changed.
    Returns
    @@ -4429,7 +4433,7 @@
    Returns
    async def - fetch_clan_members( self, clan_id: int, /, *, name: Optional[str] = None, type: Union[int, aiobungie.internal.enums.MembershipType] = <MembershipType.NONE: 0>) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.clans.ClanMember]: + fetch_clan_members( self, clan_id: int, /, *, name: Optional[str] = None, type: Union[int, aiobungie.internal.enums.MembershipType] = <MembershipType.NONE: 0>) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.clans.ClanMember]: @@ -4442,7 +4446,7 @@
    Returns
    834 *, 835 name: typing.Optional[str] = None, 836 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, -837 ) -> iterators.FlatIterator[clans.ClanMember]: +837 ) -> iterators.Iterator[clans.ClanMember]: 838 """Fetch Bungie clan members. 839 840 Parameters @@ -4462,7 +4466,7 @@
    Returns
    854 855 Returns 856 ------- -857 `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]` +857 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 858 An iterator over the bungie clan members. 859 860 Raises @@ -4500,7 +4504,7 @@
    Other Parameters
    Returns
    Raises
    @@ -4779,7 +4783,7 @@
    Returns
    async def - search_entities( self, name: str, entity_type: str, *, page: int = 0) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.entity.SearchableEntity]: + search_entities( self, name: str, entity_type: str, *, page: int = 0) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.entity.SearchableEntity]: @@ -4787,7 +4791,7 @@
    Returns
    974    async def search_entities(
     975        self, name: str, entity_type: str, *, page: int = 0
    -976    ) -> iterators.FlatIterator[entity.SearchableEntity]:
    +976    ) -> iterators.Iterator[entity.SearchableEntity]:
     977        """Search for Destiny2 entities given a name and its type.
     978
     979        Parameters
    @@ -4805,7 +4809,7 @@ 
    Returns
    991 992 Returns 993 ------- -994 `aiobungie.iterators.FlatIterator[aiobungie.crates.SearchableEntity]` +994 `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]` 995 An iterator over the found results matching the provided name. 996 """ 997 resp = await self.rest.search_entities(name, entity_type, page=page) @@ -4836,7 +4840,7 @@
    Other Parameters
    Returns
    @@ -4927,7 +4931,7 @@
    Other Parameters
    A locale language to filter the used language in that fireteam. Defaults to aiobungie.crates.FireteamLanguage.ALL
  • date_range (int): -An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • +An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • page (int): The page number. By default its 0 which returns all available activities.
  • slots_filter (int): @@ -5572,7 +5576,11 @@
    Returns
    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/crates.html b/docs/aiobungie/crates.html index b10a96ad..5703d90c 100644 --- a/docs/aiobungie/crates.html +++ b/docs/aiobungie/crates.html @@ -3,7 +3,7 @@ - + aiobungie.crates API documentation @@ -363,9 +363,6 @@

    API Documentation

  • Rewards
  • -
  • - net -
  • hash
  • @@ -390,9 +387,6 @@

    API Documentation

  • Challenges
  • -
  • - net -
  • objective_hash
  • @@ -558,27 +552,6 @@

    API Documentation

  • best_goals_hit
  • -
  • - goals_hit -
  • -
  • - special_score -
  • -
  • - best_single_score -
  • -
  • - kd_ratio -
  • -
  • - kd_assists -
  • -
  • - assists -
  • -
  • - precision_kills -
  • @@ -798,42 +771,6 @@

    API Documentation

  • CustomizationOptions
  • -
  • - personality -
  • -
  • - face -
  • -
  • - skin_color -
  • -
  • - lip_color -
  • -
  • - eye_color -
  • -
  • - hair_colors -
  • -
  • - feature_colors -
  • -
  • - decal_color -
  • -
  • - wear_helmet -
  • -
  • - hair_index -
  • -
  • - feature_index -
  • -
  • - decal_index -
  • @@ -852,9 +789,6 @@

    API Documentation

  • milestones
  • -
  • - checklists -
  • seasonal_artifact
  • @@ -909,21 +843,9 @@

    API Documentation

  • theme
  • -
  • - conversation_id -
  • -
  • - allow_chat -
  • -
  • - chat_security -
  • progressions
  • -
  • - banner_data -
  • call_sign
  • @@ -972,9 +894,6 @@

    API Documentation

  • fetch_invited_members
  • -
  • - url -
  • @@ -1053,9 +972,6 @@

    API Documentation

  • update_banner_permissions
  • -
  • - update_culture_permissions -
  • join_level
  • @@ -1389,12 +1305,6 @@

    API Documentation

  • objects
  • -
  • - trait_ids -
  • -
  • - trait_hashes -
  • item_class
  • @@ -1407,18 +1317,9 @@

    API Documentation

  • breaker_type_hash
  • -
  • - damagetype_hashes -
  • damage_types
  • -
  • - default_damagetype -
  • -
  • - default_damagetype_hash -
  • collectible_hash
  • @@ -1443,9 +1344,6 @@

    API Documentation

  • screenshot
  • -
  • - ui_display_style -
  • tier_type
  • @@ -1473,9 +1371,6 @@

    API Documentation

  • stack_label
  • -
  • - tooltip_notifications -
  • display_source
  • @@ -1491,9 +1386,6 @@

    API Documentation

  • expire_in_orbit_message
  • -
  • - suppress_expiration -
  • lore_hash
  • @@ -1503,21 +1395,12 @@

    API Documentation

  • summary_hash
  • -
  • - allow_actions -
  • has_postmaster_effect
  • not_transferable
  • -
  • - category_hashes -
  • -
  • - season_hash -
  • @@ -1566,9 +1449,6 @@

    API Documentation

  • unlock_strings
  • -
  • - inherits_free_room -
  • playlist_activities
  • @@ -1638,63 +1518,6 @@

    API Documentation

  • ObjectiveEntity
  • -
  • - unlock_value_hash -
  • -
  • - minimum_visibility -
  • -
  • - completion_value -
  • -
  • - scope -
  • -
  • - location_hash -
  • -
  • - allowed_negative_value -
  • -
  • - allowed_value_change -
  • -
  • - counting_downward -
  • -
  • - display_only_objective -
  • -
  • - value_style -
  • -
  • - complete_value_style -
  • -
  • - progress_value_style -
  • -
  • - allow_over_completion -
  • -
  • - show_value_style -
  • -
  • - progress_description -
  • -
  • - perks -
  • -
  • - stats -
  • -
  • - ui_label -
  • -
  • - ui_style -
  • @@ -1869,12 +1692,6 @@

    API Documentation

  • has_microphone
  • -
  • - last_platform_invite_date -
  • -
  • - last_platform_invite_result -
  • @@ -2097,9 +1914,6 @@

    API Documentation

  • end_date
  • -
  • - order -
  • rewards
  • @@ -2136,12 +1950,6 @@

    API Documentation

  • MilestoneQuest
  • -
  • - item_hash -
  • -
  • - status -
  • @@ -2151,12 +1959,6 @@

    API Documentation

  • MilestoneVendor
  • -
  • - vendor_hash -
  • -
  • - preview_itemhash -
  • @@ -2181,9 +1983,6 @@

    API Documentation

  • QuestStatus
  • -
  • - net -
  • quest_hash
  • @@ -2226,9 +2025,6 @@

    API Documentation

  • MilestoneReward
  • -
  • - category_hash -
  • entries
  • @@ -2439,9 +2235,6 @@

    API Documentation

  • Objective
  • -
  • - net -
  • hash
  • @@ -2544,9 +2337,6 @@

    API Documentation

  • state
  • -
  • - objective -
  • progress_value
  • @@ -2592,18 +2382,6 @@

    API Documentation

  • ArtifactTier
  • -
  • - hash -
  • -
  • - is_unlocked -
  • -
  • - points_to_unlock -
  • -
  • - items -
  • @@ -2613,12 +2391,6 @@

    API Documentation

  • ArtifactTierItem
  • -
  • - hash -
  • -
  • - is_active -
  • @@ -2628,18 +2400,6 @@

    API Documentation

  • CharacterScopedArtifact
  • -
  • - hash -
  • -
  • - points_used -
  • -
  • - reset_count -
  • -
  • - tiers -
  • @@ -2952,9 +2712,6 @@

    API Documentation

  • breaker_type_hash
  • -
  • - energy -
  • @@ -3012,9 +2769,6 @@

    API Documentation

  • is_enabled
  • -
  • - insert_fail_indexes -
  • enable_fail_indexes
  • @@ -3100,9 +2854,9 @@

    for functional usage for the Bungie API objects.

    - + - +
      1# MIT License
       2#
    @@ -3284,69 +3038,69 @@ 

    -
    556@attrs.define(kw_only=True)
    -557class Activity:
    -558    """Represents a Bungie Activity."""
    +            
    553@attrs.define(kw_only=True)
    +554class Activity:
    +555    """Represents a Bungie Activity."""
    +556
    +557    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    +558    """A network state used for making external requests."""
     559
    -560    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    -561    """A network state used for making external requests."""
    +560    hash: int
    +561    """The activity's reference id or hash."""
     562
    -563    hash: int
    -564    """The activity's reference id or hash."""
    +563    membership_type: enums.MembershipType
    +564    """The activity player's membership type."""
     565
    -566    membership_type: enums.MembershipType
    -567    """The activity player's membership type."""
    +566    instance_id: int
    +567    """The activity's instance id."""
     568
    -569    instance_id: int
    -570    """The activity's instance id."""
    +569    mode: enums.GameMode
    +570    """The activity mode or type."""
     571
    -572    mode: enums.GameMode
    -573    """The activity mode or type."""
    +572    modes: collections.Sequence[enums.GameMode]
    +573    """Sequence of the activity's gamemodes."""
     574
    -575    modes: collections.Sequence[enums.GameMode]
    -576    """Sequence of the activity's gamemodes."""
    +575    is_private: bool
    +576    """Whether this activity is private or not."""
     577
    -578    is_private: bool
    -579    """Whether this activity is private or not."""
    +578    occurred_at: datetime.datetime
    +579    """A datetime of when did this activity occurred."""
     580
    -581    occurred_at: datetime.datetime
    -582    """A datetime of when did this activity occurred."""
    +581    values: ActivityValues
    +582    """Information occurred in this activity."""
     583
    -584    values: ActivityValues
    -585    """Information occurred in this activity."""
    -586
    -587    @property
    -588    def is_flawless(self) -> bool:
    -589        """Whether this activity was a flawless run or not."""
    -590        return self.values.deaths == 0 and self.values.is_completed is True
    -591
    -592    @property
    -593    def is_solo(self) -> bool:
    -594        """Whether this activity was completed solo or not."""
    -595        return self.values.player_count == 1 and self.values.is_completed
    -596
    -597    @property
    -598    def is_solo_flawless(self) -> bool:
    -599        """Whether this activity was completed solo and flawless."""
    -600        return self.is_solo & self.is_flawless
    -601
    -602    @property
    -603    def reference_id(self) -> int:
    -604        """An alias to the activity's hash"""
    -605        return self.hash
    +584    @property
    +585    def is_flawless(self) -> bool:
    +586        """Whether this activity was a flawless run or not."""
    +587        return self.values.deaths == 0 and self.values.is_completed is True
    +588
    +589    @property
    +590    def is_solo(self) -> bool:
    +591        """Whether this activity was completed solo or not."""
    +592        return self.values.player_count == 1 and self.values.is_completed
    +593
    +594    @property
    +595    def is_solo_flawless(self) -> bool:
    +596        """Whether this activity was completed solo and flawless."""
    +597        return self.is_solo & self.is_flawless
    +598
    +599    @property
    +600    def reference_id(self) -> int:
    +601        """An alias to the activity's hash"""
    +602        return self.hash
    +603
    +604    async def fetch_post(self) -> PostActivity:
    +605        """Fetch this activity's data after it was finished.
     606
    -607    async def fetch_post(self) -> PostActivity:
    -608        """Fetch this activity's data after it was finished.
    -609
    -610        Returns
    -611        -------
    -612        `PostActivity`
    -613            A post activity object.
    -614        """
    -615        return await self.net.request.fetch_post_activity(self.instance_id)
    -616
    -617    def __int__(self) -> int:
    -618        return self.instance_id
    +607        Returns
    +608        -------
    +609        `PostActivity`
    +610            A post activity object.
    +611        """
    +612        return await self.net.request.fetch_post_activity(self.instance_id)
    +613
    +614    def __int__(self) -> int:
    +615        return self.instance_id
     
    @@ -3562,15 +3316,15 @@

    -
    607    async def fetch_post(self) -> PostActivity:
    -608        """Fetch this activity's data after it was finished.
    -609
    -610        Returns
    -611        -------
    -612        `PostActivity`
    -613            A post activity object.
    -614        """
    -615        return await self.net.request.fetch_post_activity(self.instance_id)
    +            
    604    async def fetch_post(self) -> PostActivity:
    +605        """Fetch this activity's data after it was finished.
    +606
    +607        Returns
    +608        -------
    +609        `PostActivity`
    +610            A post activity object.
    +611        """
    +612        return await self.net.request.fetch_post_activity(self.instance_id)
     
    @@ -3598,68 +3352,68 @@
    Returns
    -
    492@attrs.define(kw_only=True)
    -493class PostActivity:
    -494    """Represents a Destiny 2 post activity details."""
    +            
    489@attrs.define(kw_only=True)
    +490class PostActivity:
    +491    """Represents a Destiny 2 post activity details."""
    +492
    +493    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    +494    """A network state used for making external requests."""
     495
    -496    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    -497    """A network state used for making external requests."""
    +496    starting_phase: int
    +497    """If this activity has "phases", this is the phase at which the activity was started."""
     498
    -499    starting_phase: int
    -500    """If this activity has "phases", this is the phase at which the activity was started."""
    +499    hash: int
    +500    """The activity's reference id or hash."""
     501
    -502    hash: int
    -503    """The activity's reference id or hash."""
    +502    membership_type: enums.MembershipType
    +503    """The activity player's membership type."""
     504
    -505    membership_type: enums.MembershipType
    -506    """The activity player's membership type."""
    +505    instance_id: int
    +506    """The activity's instance id."""
     507
    -508    instance_id: int
    -509    """The activity's instance id."""
    +508    mode: enums.GameMode
    +509    """The activity mode or type."""
     510
    -511    mode: enums.GameMode
    -512    """The activity mode or type."""
    +511    modes: collections.Sequence[enums.GameMode]
    +512    """A sequence of the activity's gamemodes."""
     513
    -514    modes: collections.Sequence[enums.GameMode]
    -515    """A sequence of the activity's gamemodes."""
    +514    is_private: bool
    +515    """Whether this activity is private or not."""
     516
    -517    is_private: bool
    -518    """Whether this activity is private or not."""
    +517    occurred_at: datetime.datetime
    +518    """A datetime of when did this activity occurred."""
     519
    -520    occurred_at: datetime.datetime
    -521    """A datetime of when did this activity occurred."""
    +520    players: collections.Collection[PostActivityPlayer]
    +521    """Collection of players that were in the activity."""
     522
    -523    players: collections.Collection[PostActivityPlayer]
    -524    """Collection of players that were in the activity."""
    +523    teams: typing.Optional[collections.Collection[PostActivityTeam]]
    +524    """Collections the teams that were playing against each other.
     525
    -526    teams: typing.Optional[collections.Collection[PostActivityTeam]]
    -527    """Collections the teams that were playing against each other.
    +526    This field is optional and will be `None` if the activity don't have teams.
    +527    """
     528
    -529    This field is optional and will be `None` if the activity don't have teams.
    -530    """
    -531
    -532    @property
    -533    def is_flawless(self) -> bool:
    -534        """Whether this activity was a flawless run or not."""
    -535        return all(player.values.deaths == 0 for player in self.players)
    -536
    -537    @property
    -538    def is_solo(self) -> bool:
    -539        """Whether this activity was completed solo or not."""
    -540        return len(self.players) == 1
    -541
    -542    @property
    -543    def is_solo_flawless(self) -> bool:
    -544        """Whether this activity was completed solo and flawless."""
    -545        return self.is_solo & self.is_flawless
    -546
    -547    @property
    -548    def reference_id(self) -> int:
    -549        """An alias to the activity's hash"""
    +529    @property
    +530    def is_flawless(self) -> bool:
    +531        """Whether this activity was a flawless run or not."""
    +532        return all(player.values.deaths == 0 for player in self.players)
    +533
    +534    @property
    +535    def is_solo(self) -> bool:
    +536        """Whether this activity was completed solo or not."""
    +537        return len(self.players) == 1
    +538
    +539    @property
    +540    def is_solo_flawless(self) -> bool:
    +541        """Whether this activity was completed solo and flawless."""
    +542        return self.is_solo & self.is_flawless
    +543
    +544    @property
    +545    def reference_id(self) -> int:
    +546        """An alias to the activity's hash"""
    +547        return self.hash
    +548
    +549    def __int__(self) -> int:
     550        return self.hash
    -551
    -552    def __int__(self) -> int:
    -553        return self.hash
     
    @@ -3907,68 +3661,68 @@
    Returns
    -
    254@attrs.define(kw_only=True)
    -255class ActivityValues:
    -256    """Information about values found in an activity.
    +            
    251@attrs.define(kw_only=True)
    +252class ActivityValues:
    +253    """Information about values found in an activity.
    +254
    +255    fields here include kills, deaths, K/D, assists, completion time, etc.
    +256    """
     257
    -258    fields here include kills, deaths, K/D, assists, completion time, etc.
    -259    """
    +258    assists: int
    +259    """Activity's assists"""
     260
    -261    assists: int
    -262    """Activity's assists"""
    +261    is_completed: bool
    +262    """Whether the activity was completed or no."""
     263
    -264    is_completed: bool
    -265    """Whether the activity was completed or no."""
    +264    kills: int
    +265    """Activity's kills."""
     266
    -267    kills: int
    -268    """Activity's kills."""
    +267    deaths: int
    +268    """Activity's deaths."""
     269
    -270    deaths: int
    -271    """Activity's deaths."""
    +270    opponents_defeated: int
    +271    """The amount of opponents killed in this activity."""
     272
    -273    opponents_defeated: int
    -274    """The amount of opponents killed in this activity."""
    +273    efficiency: float
    +274    """Activity's efficiently."""
     275
    -276    efficiency: float
    -277    """Activity's efficiently."""
    +276    kd_ratio: float
    +277    """Activity's kill/death ratio."""
     278
    -279    kd_ratio: float
    -280    """Activity's kill/death ratio."""
    +279    kd_assists: float
    +280    """Activity's Kill/Death/Assists."""
     281
    -282    kd_assists: float
    -283    """Activity's Kill/Death/Assists."""
    +282    score: int
    +283    """If the activity has a score, This will be available otherwise 0."""
     284
    -285    score: int
    -286    """If the activity has a score, This will be available otherwise 0."""
    +285    played_time: tuple[int, str]
    +286    """The total time the player was in this activity represented as a tuple of int, str."""
     287
    -288    played_time: tuple[int, str]
    -289    """The total time the player was in this activity represented as a tuple of int, str."""
    +288    team: typing.Optional[int]
    +289    """???"""
     290
    -291    team: typing.Optional[int]
    -292    """???"""
    +291    completion_reason: str
    +292    """The reason why the activity was completed. usually its Unknown."""
     293
    -294    completion_reason: str
    -295    """The reason why the activity was completed. usually its Unknown."""
    +294    fireteam_id: int
    +295    """The fireteam id associated with this activity."""
     296
    -297    fireteam_id: int
    -298    """The fireteam id associated with this activity."""
    +297    player_count: int
    +298    """Activity's player count."""
     299
    -300    player_count: int
    -301    """Activity's player count."""
    +300    start_seconds: tuple[int, str]
    +301    """A tuple of int and str of when did the player start the activity in seconds."""
     302
    -303    start_seconds: tuple[int, str]
    -304    """A tuple of int and str of when did the player start the activity in seconds."""
    +303    duration: tuple[int, str]
    +304    """A tuple of int, string of The activity's duration, Example int, string format `1845`, `30m 45s`"""
     305
    -306    duration: tuple[int, str]
    -307    """A tuple of int, string of The activity's duration, Example int, string format `1845`, `30m 45s`"""
    -308
    -309    # activity_id: typing.Optional[int]
    -310    # """When a stat represents the best, most, longest, fastest or some other personal best,
    -311    # the actual activity ID where that personal best was established is available on this property.
    -312    # """
    -313
    -314    team_score: int
    -315    """???"""
    +306    # activity_id: typing.Optional[int]
    +307    # """When a stat represents the best, most, longest, fastest or some other personal best,
    +308    # the actual activity ID where that personal best was established is available on this property.
    +309    # """
    +310
    +311    team_score: int
    +312    """???"""
     
    @@ -4248,27 +4002,27 @@
    Returns
    -
    402@attrs.define(kw_only=True)
    -403class ExtendedValues:
    -404    """Information about post activity extended player values data."""
    +            
    399@attrs.define(kw_only=True)
    +400class ExtendedValues:
    +401    """Information about post activity extended player values data."""
    +402
    +403    precision_kills: int
    +404    """Player precision kills."""
     405
    -406    precision_kills: int
    -407    """Player precision kills."""
    +406    grenade_kills: int
    +407    """Player grenade kills."""
     408
    -409    grenade_kills: int
    -410    """Player grenade kills."""
    +409    melee_kills: int
    +410    """Player melee kills."""
     411
    -412    melee_kills: int
    -413    """Player melee kills."""
    +412    super_kills: int
    +413    """Player super kills."""
     414
    -415    super_kills: int
    -416    """Player super kills."""
    +415    ability_kills: int
    +416    """Player ability kills."""
     417
    -418    ability_kills: int
    -419    """Player ability kills."""
    -420
    -421    weapons: typing.Optional[collections.Collection[ExtendedWeaponValues]]
    -422    """Collection of unique player weapons used in this activity. if no weapons found None will be returned."""
    +418    weapons: typing.Optional[collections.Collection[ExtendedWeaponValues]]
    +419    """Collection of unique player weapons used in this activity. if no weapons found None will be returned."""
     
    @@ -4392,31 +4146,31 @@
    Returns
    -
    375@attrs.define(kw_only=True)
    -376class ExtendedWeaponValues:
    -377    """Information about post activity extended player's weapon values data."""
    +            
    372@attrs.define(kw_only=True)
    +373class ExtendedWeaponValues:
    +374    """Information about post activity extended player's weapon values data."""
    +375
    +376    reference_id: int
    +377    """Weapon's hash or reference id."""
     378
    -379    reference_id: int
    -380    """Weapon's hash or reference id."""
    +379    kills: int
    +380    """Weapon's total kills."""
     381
    -382    kills: int
    -383    """Weapon's total kills."""
    +382    precision_kills: int
    +383    """Weapon's total precision kills."""
     384
    -385    precision_kills: int
    -386    """Weapon's total precision kills."""
    +385    assists: typing.Optional[int]
    +386    """Optional weapon assists number."""
     387
    -388    assists: typing.Optional[int]
    -389    """Optional weapon assists number."""
    +388    assists_damage: typing.Optional[int]
    +389    """Optional weapon assists damage number."""
     390
    -391    assists_damage: typing.Optional[int]
    -392    """Optional weapon assists damage number."""
    +391    precision_kills_percentage: tuple[int, str]
    +392    """A tuple of weapon's precision kills percentage as an int and a str.
     393
    -394    precision_kills_percentage: tuple[int, str]
    -395    """A tuple of weapon's precision kills percentage as an int and a str.
    -396
    -397    A string version will be formatted as: `100%`
    -398    and the int version will be formatted as: `1`
    -399    """
    +394    A string version will be formatted as: `100%`
    +395    and the int version will be formatted as: `1`
    +396    """
     
    @@ -4543,51 +4297,51 @@
    Returns
    -
    445@attrs.define(kw_only=True)
    -446class PostActivityPlayer:
    -447    """Represents a post activity Destiny 2 player."""
    +            
    442@attrs.define(kw_only=True)
    +443class PostActivityPlayer:
    +444    """Represents a post activity Destiny 2 player."""
    +445
    +446    standing: int
    +447    """Sanding of the player."""
     448
    -449    standing: int
    -450    """Sanding of the player."""
    +449    destiny_user: user.DestinyMembership
    +450    """An object of the destiny membership bound to this player."""
     451
    -452    destiny_user: user.DestinyMembership
    -453    """An object of the destiny membership bound to this player."""
    +452    score: int
    +453    """Score of the player."""
     454
    -455    score: int
    -456    """Score of the player."""
    +455    character_id: int
    +456    """The id of the character the player finished this activity with."""
     457
    -458    character_id: int
    -459    """The id of the character the player finished this activity with."""
    +458    character_class: undefined.UndefinedOr[str]
    +459    """A string of the character class the player finished this activity with."""
     460
    -461    character_class: undefined.UndefinedOr[str]
    -462    """A string of the character class the player finished this activity with."""
    +461    class_hash: typing.Optional[int]
    +462    """The hash of the player's character class."""
     463
    -464    class_hash: typing.Optional[int]
    -465    """The hash of the player's character class."""
    +464    race_hash: typing.Optional[int]
    +465    """The hash of the player's character race."""
     466
    -467    race_hash: typing.Optional[int]
    -468    """The hash of the player's character race."""
    +467    gender_hash: typing.Optional[int]
    +468    """The hash of the player's character gender."""
     469
    -470    gender_hash: typing.Optional[int]
    -471    """The hash of the player's character gender."""
    +470    character_level: typing.Optional[int]
    +471    """The player's character's level."""
     472
    -473    character_level: typing.Optional[int]
    -474    """The player's character's level."""
    +473    light_level: int
    +474    """The light level of the player's character."""
     475
    -476    light_level: int
    -477    """The light level of the player's character."""
    +476    emblem_hash: int
    +477    """The emblem hash of the player's character."""
     478
    -479    emblem_hash: int
    -480    """The emblem hash of the player's character."""
    +479    values: ActivityValues
    +480    """Player's information that occurred in this activity."""
     481
    -482    values: ActivityValues
    -483    """Player's information that occurred in this activity."""
    +482    extended_values: ExtendedValues
    +483    """Extended player information occurred in this activity.
     484
    -485    extended_values: ExtendedValues
    -486    """Extended player information occurred in this activity.
    -487
    -488    This include weapon, super, grenade kills and more.
    -489    """
    +485    This include weapon, super, grenade kills and more.
    +486    """
     
    @@ -4811,24 +4565,24 @@
    Returns
    -
    425@attrs.define(kw_only=True)
    -426class PostActivityTeam:
    -427    """Represents a post activity team information.
    +            
    422@attrs.define(kw_only=True)
    +423class PostActivityTeam:
    +424    """Represents a post activity team information.
    +425
    +426    Teams will be available in PvP gamemodes, e.g., Gambit, Crucible, Iron Banner. etc.
    +427    """
     428
    -429    Teams will be available in PvP gamemodes, e.g., Gambit, Crucible, Iron Banner. etc.
    -430    """
    +429    id: int
    +430    """Team id."""
     431
    -432    id: int
    -433    """Team id."""
    +432    name: str
    +433    """Team name."""
     434
    -435    name: str
    -436    """Team name."""
    +435    is_defeated: bool
    +436    """Whether the team has been defeated or won."""
     437
    -438    is_defeated: bool
    -439    """Whether the team has been defeated or won."""
    -440
    -441    score: int
    -442    """Team score"""
    +438    score: int
    +439    """Team score"""
     
    @@ -4926,41 +4680,41 @@
    Returns
    -
    217@attrs.define(kw_only=True)
    -218class AvailableActivity:
    -219    """Represents an available activity that can be found in character activities profile component."""
    +            
    214@attrs.define(kw_only=True)
    +215class AvailableActivity:
    +216    """Represents an available activity that can be found in character activities profile component."""
    +217
    +218    hash: int
    +219    """Activity's hash."""
     220
    -221    hash: int
    -222    """Activity's hash."""
    +221    is_new: bool
    +222    """Whether the activity is new or not."""
     223
    -224    is_new: bool
    -225    """Whether the activity is new or not."""
    +224    can_lead: bool
    +225    """Whether the character can lead this activity or not."""
     226
    -227    can_lead: bool
    -228    """Whether the character can lead this activity or not."""
    +227    can_join: bool
    +228    """Whether the character can join this activity or not."""
     229
    -230    can_join: bool
    -231    """Whether the character can join this activity or not."""
    +230    is_completed: bool
    +231    """Whether the character completed this activity before or not."""
     232
    -233    is_completed: bool
    -234    """Whether the character completed this activity before or not."""
    +233    is_visible: bool
    +234    """Whether the activity is visible to this character or not."""
     235
    -236    is_visible: bool
    -237    """Whether the activity is visible to this character or not."""
    +236    display_level: typing.Optional[int]
    +237    """The activity's display level."""
     238
    -239    display_level: typing.Optional[int]
    -240    """The activity's display level."""
    +239    recommended_light: typing.Optional[int]
    +240    """The recommended light power to enter this activity."""
     241
    -242    recommended_light: typing.Optional[int]
    -243    """The recommended light power to enter this activity."""
    +242    difficulty: Difficulty
    +243    """Activity's difficulty tier."""
     244
    -245    difficulty: typedefs.IntAnd[Difficulty]
    -246    """Activity's difficulty tier."""
    -247
    -248    @helpers.unimplemented(available_in="0.2.7")
    -249    async def fetch_self(self) -> entity.ActivityEntity:
    -250        """Fetch the definition of this activity."""
    -251        ...
    +245    @helpers.unimplemented()
    +246    async def fetch_self(self) -> entity.ActivityEntity:
    +247        """Fetch the definition of this activity."""
    +248        ...
     
    @@ -4972,7 +4726,7 @@
    Returns
    - AvailableActivity( *, hash: int, is_new: bool, can_lead: bool, can_join: bool, is_completed: bool, is_visible: bool, display_level: Optional[int], recommended_light: Optional[int], difficulty: Union[int, aiobungie.crates.activity.Difficulty]) + AvailableActivity( *, hash: int, is_new: bool, can_lead: bool, can_join: bool, is_completed: bool, is_visible: bool, display_level: Optional[int], recommended_light: Optional[int], difficulty: aiobungie.crates.activity.Difficulty) @@ -5102,7 +4856,7 @@
    Returns
    - difficulty: Union[int, aiobungie.crates.activity.Difficulty] + difficulty: aiobungie.crates.activity.Difficulty
    @@ -5116,7 +4870,7 @@
    Returns
    -
    @helpers.unimplemented(available_in='0.2.7')
    +
    @helpers.unimplemented()
    def fetch_self(self) -> aiobungie.crates.ActivityEntity: @@ -5125,10 +4879,10 @@
    Returns
    -
    248    @helpers.unimplemented(available_in="0.2.7")
    -249    async def fetch_self(self) -> entity.ActivityEntity:
    -250        """Fetch the definition of this activity."""
    -251        ...
    +            
    245    @helpers.unimplemented()
    +246    async def fetch_self(self) -> entity.ActivityEntity:
    +247        """Fetch the definition of this activity."""
    +248        ...
     
    @@ -5150,33 +4904,33 @@
    Returns
    -
     79@attrs.define(kw_only=True)
    - 80class Rewards:
    - 81    """Represents rewards achieved from activities."""
    - 82
    - 83    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    - 84
    - 85    hash: int
    - 86    """Reward's hash."""
    - 87
    - 88    instance_id: typing.Optional[int]
    - 89    """An optional instance id for this reward. `None` if not found."""
    - 90
    - 91    quantity: int
    - 92    """Reward's quantity."""
    - 93
    - 94    has_conditional_visibility: bool
    - 95    """???"""
    - 96
    - 97    async def fetch_self(self) -> entity.InventoryEntity:
    - 98        """Fetch the definition of this reward.
    - 99
    -100        Returns
    -101        -------
    -102        `aiobungie.crates.InventoryEntity`
    -103            An inventory item entity of the associated hash.
    -104        """
    -105        return await self.net.request.fetch_inventory_item(self.hash)
    +            
     78@attrs.define(kw_only=True)
    + 79class Rewards:
    + 80    """Represents rewards achieved from activities."""
    + 81
    + 82    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    + 83
    + 84    hash: int
    + 85    """Reward's hash."""
    + 86
    + 87    instance_id: typing.Optional[int]
    + 88    """An optional instance id for this reward. `None` if not found."""
    + 89
    + 90    quantity: int
    + 91    """Reward's quantity."""
    + 92
    + 93    has_conditional_visibility: bool
    + 94    """???"""
    + 95
    + 96    async def fetch_self(self) -> entity.InventoryEntity:
    + 97        """Fetch the definition of this reward.
    + 98
    + 99        Returns
    +100        -------
    +101        `aiobungie.crates.InventoryEntity`
    +102            An inventory item entity of the associated hash.
    +103        """
    +104        return await self.net.request.fetch_inventory_item(self.hash)
     
    @@ -5207,17 +4961,6 @@
    Returns
    -
    -
    - - - - -
    @@ -5282,15 +5025,15 @@
    Returns
    -
     97    async def fetch_self(self) -> entity.InventoryEntity:
    - 98        """Fetch the definition of this reward.
    - 99
    -100        Returns
    -101        -------
    -102        `aiobungie.crates.InventoryEntity`
    -103            An inventory item entity of the associated hash.
    -104        """
    -105        return await self.net.request.fetch_inventory_item(self.hash)
    +            
     96    async def fetch_self(self) -> entity.InventoryEntity:
    + 97        """Fetch the definition of this reward.
    + 98
    + 99        Returns
    +100        -------
    +101        `aiobungie.crates.InventoryEntity`
    +102            An inventory item entity of the associated hash.
    +103        """
    +104        return await self.net.request.fetch_inventory_item(self.hash)
     
    @@ -5318,21 +5061,21 @@
    Returns
    -
    108@attrs.define(kw_only=True)
    -109class Challenges:
    -110    """Represents challenges found in activities."""
    -111
    -112    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    -113
    -114    objective_hash: int
    -115    """The challenge's objective hash."""
    -116
    -117    dummy_rewards: collections.Sequence[Rewards]
    -118    """A sequence of the challenge rewards as they're represented in the UI."""
    -119
    -120    async def fetch_objective(self) -> entity.ObjectiveEntity:
    -121        """Fetch the objective of this challenge."""
    -122        return await self.net.request.fetch_objective_entity(self.objective_hash)
    +            
    107@attrs.define(kw_only=True)
    +108class Challenges:
    +109    """Represents challenges found in activities."""
    +110
    +111    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    +112
    +113    objective_hash: int
    +114    """The challenge's objective hash."""
    +115
    +116    dummy_rewards: collections.Sequence[Rewards]
    +117    """A sequence of the challenge rewards as they're represented in the UI."""
    +118
    +119    async def fetch_objective(self) -> entity.ObjectiveEntity:
    +120        """Fetch the objective of this challenge."""
    +121        return await self.net.request.fetch_objective_entity(self.objective_hash)
     
    @@ -5361,17 +5104,6 @@
    Returns
    -
    -
    - - - - -
    @@ -5410,9 +5142,9 @@
    Returns
    -
    120    async def fetch_objective(self) -> entity.ObjectiveEntity:
    -121        """Fetch the objective of this challenge."""
    -122        return await self.net.request.fetch_objective_entity(self.objective_hash)
    +            
    119    async def fetch_objective(self) -> entity.ObjectiveEntity:
    +120        """Fetch the objective of this challenge."""
    +121        return await self.net.request.fetch_objective_entity(self.objective_hash)
     
    @@ -5434,24 +5166,24 @@
    Returns
    -
    125@attrs.define(kw_only=True)
    -126class Matchmaking:
    -127    """Represents activity's matchmaking information."""
    -128
    -129    is_matchmaking: bool
    -130    """Whether the activity is matchmaking or not."""
    -131
    -132    min_party: int
    -133    """The minimum number of how many player can join this activity as a party."""
    -134
    -135    max_party: int
    -136    """The maximum number of how many player can join this activity as a party."""
    -137
    -138    max_player: int
    -139    """The maximum number of how many player can join this activity."""
    -140
    -141    requires_guardian_oath: bool
    -142    """If true, you have to Solemnly Swear to be up to Nothing But Good(tm) to play."""
    +            
    124@attrs.define(kw_only=True)
    +125class Matchmaking:
    +126    """Represents activity's matchmaking information."""
    +127
    +128    is_matchmaking: bool
    +129    """Whether the activity is matchmaking or not."""
    +130
    +131    min_party: int
    +132    """The minimum number of how many player can join this activity as a party."""
    +133
    +134    max_party: int
    +135    """The maximum number of how many player can join this activity as a party."""
    +136
    +137    max_player: int
    +138    """The maximum number of how many player can join this activity."""
    +139
    +140    requires_guardian_oath: bool
    +141    """If true, you have to Solemnly Swear to be up to Nothing But Good(tm) to play."""
     
    @@ -5561,22 +5293,22 @@
    Returns
    -
    145@attrs.define(kw_only=True)
    -146class GuidedGame:
    -147    """Represents information about a guided game activity."""
    -148
    -149    max_lobby_size: int
    -150    """The max amount of people that can be in the lobby."""
    -151
    -152    min_lobby_size: int
    -153    """The minimum amount of people that can be in the lobby."""
    -154
    -155    disband_count: int
    -156    """If 1, the guided group cannot be disbanded.
    -157    Otherwise, take the total number of players in the activity and subtract this number
    -158
    -159    That is the total number of votes needed for the guided group to disband.
    -160    """
    +            
    144@attrs.define(kw_only=True)
    +145class GuidedGame:
    +146    """Represents information about a guided game activity."""
    +147
    +148    max_lobby_size: int
    +149    """The max amount of people that can be in the lobby."""
    +150
    +151    min_lobby_size: int
    +152    """The minimum amount of people that can be in the lobby."""
    +153
    +154    disband_count: int
    +155    """If 1, the guided group cannot be disbanded.
    +156    Otherwise, take the total number of players in the activity and subtract this number
    +157
    +158    That is the total number of votes needed for the guided group to disband.
    +159    """
     
    @@ -5661,24 +5393,24 @@
    Returns
    -
    163@attrs.define(kw_only=True)
    -164class Location:
    -165    """Represents information about an activity location."""
    -166
    -167    hash: typing.Union[typedefs.IntAnd[enums.Place], typedefs.IntAnd[enums.Planet]]
    -168    """Location hash."""
    -169
    -170    activision_source: str
    -171    """A hint that the UI uses to figure out how this location is activated by the player."""
    -172
    -173    item_hash: typing.Optional[int]
    -174    """The items hash if populated."""
    -175
    -176    objective_hash: typing.Optional[int]
    -177    """The objective hash if populated."""
    -178
    -179    activity_hash: typing.Optional[int]
    -180    """The activity hash if populated."""
    +            
    162@attrs.define(kw_only=True)
    +163class Location:
    +164    """Represents information about an activity location."""
    +165
    +166    hash: typing.Union[enums.Place, enums.Planet]
    +167    """Location hash."""
    +168
    +169    activision_source: str
    +170    """A hint that the UI uses to figure out how this location is activated by the player."""
    +171
    +172    item_hash: typing.Optional[int]
    +173    """The items hash if populated."""
    +174
    +175    objective_hash: typing.Optional[int]
    +176    """The objective hash if populated."""
    +177
    +178    activity_hash: typing.Optional[int]
    +179    """The activity hash if populated."""
     
    @@ -5690,7 +5422,7 @@
    Returns
    - Location( *, hash: Union[int, aiobungie.internal.enums.Place, aiobungie.internal.enums.Planet], activision_source: str, item_hash: Optional[int], objective_hash: Optional[int], activity_hash: Optional[int]) + Location( *, hash: Union[aiobungie.internal.enums.Place, aiobungie.internal.enums.Planet], activision_source: str, item_hash: Optional[int], objective_hash: Optional[int], activity_hash: Optional[int]) @@ -5712,7 +5444,7 @@
    Returns
    -
    183@attrs.define(kw_only=True)
    -184class CharacterActivity:
    -185    """Represents a character activity profile component."""
    -186
    -187    date_started: datetime.datetime
    -188    """The start datetime of the activity."""
    -189
    -190    current_hash: int
    -191    """The current activity hash that the player is now playing."""
    -192
    -193    current_mode_hash: int
    -194    """The current activity mode hash that the player is now playing."""
    -195
    -196    current_mode: typing.Optional[typedefs.IntAnd[enums.GameMode]]
    -197    """The current activity mode presented an an enum."""
    -198
    -199    current_mode_types: typing.Optional[
    -200        collections.Sequence[typedefs.IntAnd[enums.GameMode]]
    -201    ]
    -202    """A sequence of the current activity game-mode types presented as an enum."""
    +            
    182@attrs.define(kw_only=True)
    +183class CharacterActivity:
    +184    """Represents a character activity profile component."""
    +185
    +186    date_started: datetime.datetime
    +187    """The start datetime of the activity."""
    +188
    +189    current_hash: int
    +190    """The current activity hash that the player is now playing."""
    +191
    +192    current_mode_hash: int
    +193    """The current activity mode hash that the player is now playing."""
    +194
    +195    current_mode: typing.Optional[enums.GameMode]
    +196    """The current activity mode presented an an enum."""
    +197
    +198    current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]]
    +199    """A sequence of the current activity game-mode types presented as an enum."""
    +200
    +201    current_mode_hashes: typing.Optional[collections.Sequence[int]]
    +202    """A sequence of the current activity's mode hashes."""
     203
    -204    current_mode_hashes: typing.Optional[collections.Sequence[int]]
    -205    """A sequence of the current activity's mode hashes."""
    +204    current_playlist_hash: typing.Optional[int]
    +205    """The current activity playlist hash."""
     206
    -207    current_playlist_hash: typing.Optional[int]
    -208    """The current activity playlist hash."""
    +207    last_story_hash: int
    +208    """The last completed story hash."""
     209
    -210    last_story_hash: int
    -211    """The last completed story hash."""
    -212
    -213    available_activities: collections.Sequence[AvailableActivity]
    -214    """A sequence of the available activities associated with this character."""
    +210    available_activities: collections.Sequence[AvailableActivity]
    +211    """A sequence of the available activities associated with this character."""
     
    @@ -5831,7 +5561,7 @@
    Returns
    - CharacterActivity( *, date_started: datetime.datetime, current_hash: int, current_mode_hash: int, current_mode: Union[int, aiobungie.internal.enums.GameMode, NoneType], current_mode_types: Optional[collections.abc.Sequence[Union[int, aiobungie.internal.enums.GameMode]]], current_mode_hashes: Optional[collections.abc.Sequence[int]], current_playlist_hash: Optional[int], last_story_hash: int, available_activities: collections.abc.Sequence[aiobungie.crates.AvailableActivity]) + CharacterActivity( *, date_started: datetime.datetime, current_hash: int, current_mode_hash: int, current_mode: Optional[aiobungie.internal.enums.GameMode], current_mode_types: Optional[collections.abc.Sequence[aiobungie.internal.enums.GameMode]], current_mode_hashes: Optional[collections.abc.Sequence[int]], current_playlist_hash: Optional[int], last_story_hash: int, available_activities: collections.abc.Sequence[aiobungie.crates.AvailableActivity]) @@ -5896,7 +5626,7 @@
    Returns
    - current_mode: Union[int, aiobungie.internal.enums.GameMode, NoneType] + current_mode: Optional[aiobungie.internal.enums.GameMode]
    @@ -5909,7 +5639,7 @@
    Returns
    - current_mode_types: Optional[collections.abc.Sequence[Union[int, aiobungie.internal.enums.GameMode]]] + current_mode_types: Optional[collections.abc.Sequence[aiobungie.internal.enums.GameMode]]
    @@ -5985,15 +5715,15 @@
    Returns
    -
    621@attrs.define(kw_only=True)
    -622class AggregatedActivity:
    -623    """Represents aggergated activity data."""
    +            
    618@attrs.define(kw_only=True)
    +619class AggregatedActivity:
    +620    """Represents aggergated activity data."""
    +621
    +622    hash: int
    +623    """The activity hash."""
     624
    -625    hash: int
    -626    """The activity hash."""
    -627
    -628    values: AggregatedActivityValues
    -629    """Aggregated activity values. This contains kills, deaths, etc."""
    +625    values: AggregatedActivityValues
    +626    """Aggregated activity values. This contains kills, deaths, etc."""
     
    @@ -6061,61 +5791,61 @@
    Returns
    -
    318@attrs.define(kw_only=True)
    -319class AggregatedActivityValues:
    -320    """Information found in an aggregated activity stats."""
    +            
    315@attrs.define(kw_only=True)
    +316class AggregatedActivityValues:
    +317    """Information found in an aggregated activity stats."""
    +318
    +319    id: int
    +320    """Activity's id."""
     321
    -322    id: int
    -323    """Activity's id."""
    +322    fastest_completion_time: tuple[int, str]
    +323    """A tuple that contains a representation of the fastest completion for that activity in different data types.
     324
    -325    fastest_completion_time: tuple[int, str]
    -326    """A tuple that contains a representation of the fastest completion for that activity in different data types.
    -327
    -328    Order
    -329    -----
    -330    - `int`: The completion time in seconds.
    -331    - `str`: The completion time in a readable format. i.e., `0:18.500`
    -332    """
    +325    Order
    +326    -----
    +327    - `int`: The completion time in seconds.
    +328    - `str`: The completion time in a readable format. i.e., `0:18.500`
    +329    """
    +330
    +331    completions: int
    +332    """The amount of times the activity was completed."""
     333
    -334    completions: int
    -335    """The amount of times the activity was completed."""
    +334    kills: int
    +335    """"The amount of kills the player has in this activity."""
     336
    -337    kills: int
    -338    """"The amount of kills the player has in this activity."""
    +337    deaths: int
    +338    """The amount of deaths the player has in this activity."""
     339
    -340    deaths: int
    -341    """The amount of deaths the player has in this activity."""
    -342
    -343    seconds_played: tuple[int, str]
    -344    """A tuple that contains an int and a string representation of
    -345    the total time the player has spent in this activity.
    -346    """
    +340    seconds_played: tuple[int, str]
    +341    """A tuple that contains an int and a string representation of
    +342    the total time the player has spent in this activity.
    +343    """
    +344
    +345    wins: int
    +346    """The amount of wins the player has in this activity."""
     347
    -348    wins: int
    -349    """The amount of wins the player has in this activity."""
    +348    goals_missed: int
    +349    """The amount of goals missed the player has in this activity."""
     350
    -351    goals_missed: int
    -352    """The amount of goals missed the player has in this activity."""
    +351    special_actions: int
    +352    """The amount of special actions the player has in this activity."""
     353
    -354    special_actions: int
    -355    """The amount of special actions the player has in this activity."""
    +354    best_goals_hit: int
    +355    """The amount of best goals hit the player has in this activity."""
     356
    -357    best_goals_hit: int
    -358    """The amount of best goals hit the player has in this activity."""
    -359
    -360    goals_hit: int
    -361
    -362    special_score: int
    -363
    -364    best_single_score: int
    -365
    -366    kd_ratio: float
    -367
    -368    kd_assists: int
    -369
    -370    assists: int
    -371
    -372    precision_kills: int
    +357    goals_hit: int
    +358
    +359    special_score: int
    +360
    +361    best_single_score: int
    +362
    +363    kd_ratio: float
    +364
    +365    kd_assists: int
    +366
    +367    assists: int
    +368
    +369    precision_kills: int
     
    @@ -6296,83 +6026,6 @@
    Order
    -
    -
    -
    - goals_hit: int - - -
    - - - - -
    -
    -
    - special_score: int - - -
    - - - - -
    -
    -
    - best_single_score: int - - -
    - - - - -
    -
    -
    - kd_ratio: float - - -
    - - - - -
    -
    -
    - kd_assists: int - - -
    - - - - -
    -
    -
    - assists: int - - -
    - - - - -
    -
    -
    - precision_kills: int - - -
    - - - -
    @@ -6914,7 +6567,7 @@
    Inherited Members
    245 *, 246 page: int = 0, 247 limit: int = 250, -248 ) -> iterators.FlatIterator[activity.Activity]: +248 ) -> iterators.Iterator[activity.Activity]: 249 """Fetch Destiny 2 activities for this character. 250 251 Parameters @@ -6931,7 +6584,7 @@
    Inherited Members
    262 263 Returns 264 ------- -265 `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]` +265 `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` 266 A iterator over the character's activities. 267 268 Raises @@ -7334,7 +6987,7 @@
    Inherited Members
    async def - fetch_activities( self, mode: Union[int, aiobungie.internal.enums.GameMode], *, page: int = 0, limit: int = 250) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.Activity]: + fetch_activities( self, mode: Union[int, aiobungie.internal.enums.GameMode], *, page: int = 0, limit: int = 250) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.Activity]: @@ -7346,7 +6999,7 @@
    Inherited Members
    245 *, 246 page: int = 0, 247 limit: int = 250, -248 ) -> iterators.FlatIterator[activity.Activity]: +248 ) -> iterators.Iterator[activity.Activity]: 249 """Fetch Destiny 2 activities for this character. 250 251 Parameters @@ -7363,7 +7016,7 @@
    Inherited Members
    262 263 Returns 264 ------- -265 `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]` +265 `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` 266 A iterator over the character's activities. 267 268 Raises @@ -7403,7 +7056,7 @@
    Other Parameters
    Returns
    Raises
    @@ -8163,146 +7816,14 @@
    Returns
    -
    -
    - personality: int +
    +
    + +
    +
    @attrs.define(kw_only=True)
    - -
    - - - - -
    -
    -
    - face: int - - -
    - - - - -
    -
    -
    - skin_color: int - - -
    - - - - -
    -
    -
    - lip_color: int - - -
    - - - - -
    -
    -
    - eye_color: int - - -
    - - - - -
    -
    -
    - hair_colors: collections.abc.Sequence[int] - - -
    - - - - -
    -
    -
    - feature_colors: collections.abc.Sequence[int] - - -
    - - - - -
    -
    -
    - decal_color: int - - -
    - - - - -
    -
    -
    - wear_helmet: bool - - -
    - - - - -
    -
    -
    - hair_index: int - - -
    - - - - -
    -
    -
    - feature_index: int - - -
    - - - - -
    -
    -
    - decal_index: int - - -
    - - - - -
    - -
    - -
    -
    @attrs.define(kw_only=True)
    - - class - CharacterProgression: + class + CharacterProgression: @@ -8403,17 +7924,6 @@
    Returns
    -
    -
    -
    - checklists: collections.abc.Mapping[int, collections.abc.Mapping[int, bool]] - - -
    - - - -
    @@ -8841,7 +8351,7 @@
    Returns
    732 *, 733 name: typing.Optional[str] = None, 734 type: enums.MembershipType = enums.MembershipType.NONE, -735 ) -> iterators.FlatIterator[ClanMember]: +735 ) -> iterators.Iterator[ClanMember]: 736 """Fetch the members of the clan. 737 738 Parameters @@ -8854,7 +8364,7 @@
    Returns
    745 746 Returns 747 -------- -748 `aiobungie.FlatIterator[ClanMember]` +748 `aiobungie.Iterator[ClanMember]` 749 An iterator over the clan members found in this clan. 750 751 Raises @@ -9184,39 +8694,6 @@
    Returns
    -
    -
    -
    - conversation_id: int - - -
    - - - - -
    -
    -
    - allow_chat: bool - - -
    - - - - -
    -
    -
    - chat_security: int - - -
    - - - -
    @@ -9230,17 +8707,6 @@
    Returns
    -
    -
    -
    - banner_data: collections.abc.Mapping[str, int] - - -
    - - - -
    @@ -9412,7 +8878,7 @@
    Other Parameters
    Default is False for clans, True for groups.
  • join_level (aiobungie.ClanMemberType): Level to join a member at when accepting an invite, application, or joining an open clan. -Default is aiobungie.ClanMemberType.BEGINNER
  • +Default is aiobungie.ClanMemberType.BEGINNER
    @@ -9692,7 +9158,7 @@
    Other Parameters
    A locale language to filter the used language in that fireteam. Defaults to aiobungie.crates.FireteamLanguage.ALL
  • date_range (aiobungie.typedefs.IntAnd[aiobungie.FireteamDate]): -An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • +An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • page (int): The page number. By default its 0 which returns all available activities.
  • public_only (bool): @@ -9904,7 +9370,7 @@
    Parameters
    Other parameters
    -

    name: aiobungie.UndefinedOr[str] +

    name: aiobungie.UndefinedOr[str] The chat name. Default to UNDEFINED security: typing.Literal[0, 1] The security level of the chat.

    @@ -9922,7 +9388,7 @@
    Other parameters
    async def - fetch_members( self, *, name: Optional[str] = None, type: aiobungie.internal.enums.MembershipType = <MembershipType.NONE: 0>) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.ClanMember]: + fetch_members( self, *, name: Optional[str] = None, type: aiobungie.internal.enums.MembershipType = <MembershipType.NONE: 0>) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.ClanMember]: @@ -9933,7 +9399,7 @@
    Other parameters
    732 *, 733 name: typing.Optional[str] = None, 734 type: enums.MembershipType = enums.MembershipType.NONE, -735 ) -> iterators.FlatIterator[ClanMember]: +735 ) -> iterators.Iterator[ClanMember]: 736 """Fetch the members of the clan. 737 738 Parameters @@ -9946,7 +9412,7 @@
    Other parameters
    745 746 Returns 747 -------- -748 `aiobungie.FlatIterator[ClanMember]` +748 `aiobungie.Iterator[ClanMember]` 749 An iterator over the clan members found in this clan. 750 751 Raises @@ -9967,13 +9433,13 @@
    Parameters
    If provided, Only players matching this name will be returned.
  • type (aiobungie.MembershipType): Filters the membership types of the players to return. -Default is aiobungie.MembershipType.NONE which returns all membership types.
  • +Default is aiobungie.MembershipType.NONE which returns all membership types.
    Returns
    Raises
    @@ -10042,7 +9508,7 @@
    Parameters
    Other Parameters
      -
    • message (aiobungie.UndefinedOr[str]): +
    • message (aiobungie.UndefinedOr[str]): A message to send with the request. Defaults to UNDEFINED
    @@ -10106,7 +9572,7 @@
    Parameters
    Other Parameters
      -
    • message (aiobungie.UndefinedOr[str]): +
    • message (aiobungie.UndefinedOr[str]): A message to send with the request. Defaults to UNDEFINED
    @@ -10249,17 +9715,6 @@
    Returns
    -
    -
    -
    - url: str - - -
    - - - -
    @@ -10681,7 +10136,7 @@
    Other Parameters
    • length (int): An optional ban length. Default is 0
    • -
    • comment (aiobungie.UndefinedOr[str]): +
    • comment (aiobungie.UndefinedOr[str]): An optional comment to this ban. Default is UNDEFINED
    @@ -10969,17 +10424,6 @@
    Inherited Members
    -
    -
    -
    - update_culture_permissions: bool - - -
    - - - -
    @@ -11255,7 +10699,7 @@
    Parameters
    Other parameters
    -

    name: aiobungie.UndefinedOr[str] +

    name: aiobungie.UndefinedOr[str] The new chat name. Default to UNDEFINED security: typing.Literal[0, 1] The new security level of the chat.

    @@ -11822,17 +11266,18 @@
    Returns
    Example
    -
    import aiobungie
    +
    +
    import aiobungie
     
     # The components to get and return.
     components = [
    -    aiobungie.ComponentType.PROFILE,
    -    aiobungie.ComponentType.CHARACTERS,
    -    aiobungie.ComponentType.PROFILE_INVENTORIES,
    +    aiobungie.ComponentType.PROFILE,
    +    aiobungie.ComponentType.CHARACTERS,
    +    aiobungie.ComponentType.PROFILE_INVENTORIES,
     ]
     profile = await client.fetch_profile(
         id,
    -    aiobungie.MembershipType.STEAM,
    +    aiobungie.MembershipType.STEAM,
         components,
         # Assuming the component requires an auth token
         auth="Some Bearer access token"
    @@ -11841,7 +11286,8 @@ 
    Example
    for item in items: if item.hash == 1946491241: print(await item.fetch_self()) -
    +
    +
    Included Components
    @@ -11908,7 +11354,7 @@
    Included Components

    A mapping from character's id toaiobungie.crates.Character of the associated character within the character component.

    -

    This will be available when aiobungie.ComponentType.CHARACTERS is passed to the request. +

    This will be available when aiobungie.ComponentType.CHARACTERS is passed to the request. otherwise will be None.

    @@ -11930,7 +11376,7 @@
    Notes
    • This will always be None unless auth="access_token" is passed to the request.
    • -
    • This will always be None unless aiobungie.ComponentType.CHARACTER_INVENTORY +
    • This will always be None unless aiobungie.ComponentType.CHARACTER_INVENTORY is passed to the request components.
    @@ -12000,7 +11446,7 @@
    Notes

    A mapping from character's id to a sequence of their character equipment component.

    -

    This will always be None unless aiobungie.ComponentType.CHARACTER_EQUIPMENT +

    This will always be None unless aiobungie.ComponentType.CHARACTER_EQUIPMENT is passed to the request components.

    @@ -12016,7 +11462,7 @@
    Notes

    A mapping from each character ID to its collectibles component for this profile.

    -

    This will always be None unless aiobungie.ComponentType.COLLECTIBLES

    +

    This will always be None unless aiobungie.ComponentType.COLLECTIBLES

    @@ -12034,7 +11480,7 @@
    Notes
    Notes
      -
    • This will be available when aiobungie.ComponentType.CRAFTABLES is passed to the request component.
    • +
    • This will be available when aiobungie.ComponentType.CRAFTABLES is passed to the request component.
    @@ -12053,7 +11499,7 @@
    Notes

    This component is used to show minimal information about the player's current fireteam party along with the its members and the activity.

    -

    This will always be None unless aiobungie.ComponentType.TRANSITORY +

    This will always be None unless aiobungie.ComponentType.TRANSITORY is passed to the request components.

    @@ -12110,7 +11556,7 @@
    Notes

    A mapping from each character ID to a mapping of the node hash to a sequence of presentation nodes component.

    -

    This will always be None unless aiobungie.ComponentType.PRESENTATION_NODES +

    This will always be None unless aiobungie.ComponentType.PRESENTATION_NODES is passed to the request components.

    @@ -12130,7 +11576,7 @@
    Notes
    • This will always be None unless auth="access_token" is passed to the request.
    • -
    • This will always be None unless aiobungie.ComponentType.PLATFORM_SILVER +
    • This will always be None unless aiobungie.ComponentType.PLATFORM_SILVER is passed to the request components.
    @@ -12147,7 +11593,7 @@
    Notes

    A mapping from the profile presentation node hash to a node object.

    -

    This will always be None unless aiobungie.ComponentType.PRESENTATION_NODES +

    This will always be None unless aiobungie.ComponentType.PRESENTATION_NODES is passed to the request components.

    @@ -12167,7 +11613,7 @@
    Notes
    • This will always be None unless auth="access_token" is passed to the request.
    • -
    • This will always be None unless aiobungie.ComponentType.CURRENCY_LOOKUPS +
    • This will always be None unless aiobungie.ComponentType.CURRENCY_LOOKUPS is passed to the request components.
    @@ -12184,7 +11630,7 @@
    Notes

    Represents this profile's collectibles component.

    -

    This will always be None unless aiobungie.ComponentType.COLLECTIBLES

    +

    This will always be None unless aiobungie.ComponentType.COLLECTIBLES

    @@ -12387,7 +11833,7 @@
    Included Components

    The character component.

    -

    This will be available when aiobungie.ComponentType.CHARACTERS is passed to the request. +

    This will be available when aiobungie.ComponentType.CHARACTERS is passed to the request. otherwise will be None.

    @@ -12409,7 +11855,7 @@
    Notes
    • This will always be None unless auth="access_token" is passed to the request.
    • -
    • This will always be None unless aiobungie.ComponentType.CHARACTER_INVENTORY +
    • This will always be None unless aiobungie.ComponentType.CHARACTER_INVENTORY is passed to the request components.
    @@ -12479,7 +11925,7 @@
    Notes

    A sequence of the character equipment component.

    -

    This will always be None unless aiobungie.ComponentType.CHARACTER_EQUIPMENT +

    This will always be None unless aiobungie.ComponentType.CHARACTER_EQUIPMENT is passed to the request components.

    @@ -12508,7 +11954,7 @@
    Notes

    A mapping from the presentation node hash to a node object.

    -

    This will always be None unless aiobungie.ComponentType.PRESENTATION_NODES +

    This will always be None unless aiobungie.ComponentType.PRESENTATION_NODES is passed to the request components.

    @@ -12528,7 +11974,7 @@
    Notes
    • This will always be None unless auth="access_token" is passed to the request.
    • -
    • This will always be None unless aiobungie.ComponentType.CURRENCY_LOOKUPS +
    • This will always be None unless aiobungie.ComponentType.CURRENCY_LOOKUPS is passed to the request components.
    @@ -12545,7 +11991,7 @@
    Notes

    The character's collectibles component.

    -

    This will always be None unless aiobungie.ComponentType.COLLECTIBLES

    +

    This will always be None unless aiobungie.ComponentType.COLLECTIBLES

    @@ -12672,7 +12118,7 @@
    Included Components

    The profile component.

    -

    This will be available when aiobungie.ComponentType.PROFILE is passed to the request components. +

    This will be available when aiobungie.ComponentType.PROFILE is passed to the request components. otherwise will be None.

    @@ -12688,7 +12134,7 @@
    Included Components

    The profile progression component.

    -

    This will be available when aiobungie.ComponentType.PROFILE_PROGRESSION +

    This will be available when aiobungie.ComponentType.PROFILE_PROGRESSION is passed to the request components. otherwise will be None.

    @@ -12709,7 +12155,7 @@
    Notes
    • This will always be None unless auth="access_token" is passed to the request.
    • -
    • This will always be None unless aiobungie.ComponentType.PROFILE_CURRENCIES +
    • This will always be None unless aiobungie.ComponentType.PROFILE_CURRENCIES is passed to the request components.
    @@ -12730,7 +12176,7 @@
    Notes
    • This will always be None unless auth="access_token" is passed to the request.
    • -
    • This will always be None unless aiobungie.ComponentType.PROFILE_INVENTORIES +
    • This will always be None unless aiobungie.ComponentType.PROFILE_INVENTORIES is passed to the request components.
    @@ -12846,7 +12292,7 @@
    Included Components
    Notes
      -
    • This will be available when aiobungie.ComponentType.RECORDS +
    • This will be available when aiobungie.ComponentType.RECORDS is passed to the request components. otherwise will be None.
    • This will always be None if it's a character component.
    @@ -12864,7 +12310,7 @@
    Notes

    A mapping from character record ids to a character record component.

    -

    This will be available when aiobungie.ComponentType.RECORDS +

    This will be available when aiobungie.ComponentType.RECORDS is passed to the request components. otherwise will be None.

    @@ -12995,8 +12441,8 @@
    Notes
    Note
    -

    Some fields will always be None until either aiobungie.ComponentType.CHARACTER_INVENTORY -or aiobungie.ComponentType.CHARACTER_EQUIPMENT is passed to the request.

    +

    Some fields will always be None until either aiobungie.ComponentType.CHARACTER_INVENTORY +or aiobungie.ComponentType.CHARACTER_EQUIPMENT is passed to the request.

    @@ -13038,7 +12484,7 @@
    Note

    A sequence from the item instance id to an item object bound to this instance.

    -

    This will be available when aiobungie.ComponentType.ITEM_INSTANCES is passed to the request. +

    This will be available when aiobungie.ComponentType.ITEM_INSTANCES is passed to the request. otherwise will be None.

    @@ -13059,7 +12505,7 @@
    Note
  • Second one is dict that holds int key that mapps to int value of the art regions.
  • -

    This will be available when aiobungie.ComponentType.ITEM_RENDER_DATA is passed to the request. +

    This will be available when aiobungie.ComponentType.ITEM_RENDER_DATA is passed to the request. otherwise will be None.

    @@ -13075,7 +12521,7 @@
    Note

    A mapping of the item instance id to a view of its stats.

    -

    This will be available when aiobungie.ComponentType.ITEM_STATS is passed to the request. +

    This will be available when aiobungie.ComponentType.ITEM_STATS is passed to the request. otherwise will be None.

    @@ -13091,7 +12537,7 @@
    Note

    A mapping from the item instance id to a sequence of inserted sockets into it.

    -

    This will be available when aiobungie.ComponentType.ITEM_SOCKETS is passed to the request. +

    This will be available when aiobungie.ComponentType.ITEM_SOCKETS is passed to the request. otherwise will be None.

    @@ -13108,7 +12554,7 @@
    Note

    If the item supports reusable plugs, this is the mapping from the item instance id to a sequence of plugs that are allowed to be used for the socket.

    -

    This will be available when aiobungie.ComponentType.ITEM_SOCKETS is passed to the request. +

    This will be available when aiobungie.ComponentType.ITEM_SOCKETS is passed to the request. otherwise will be None.

    @@ -13125,7 +12571,7 @@
    Note

    A mapping from the item instance id to a mapping of the plug hash to a collections of the plug objectives being returned.

    -

    This will be available when aiobungie.ComponentType.ITEM_OBJECTIVES is passed to the request. +

    This will be available when aiobungie.ComponentType.ITEM_OBJECTIVES is passed to the request. otherwise will be None.

    @@ -13141,7 +12587,7 @@
    Note

    A sequence of the plug states.

    -

    This will be available when aiobungie.ComponentType.ITEM_SOCKETS is passed to the request. +

    This will be available when aiobungie.ComponentType.ITEM_SOCKETS is passed to the request. otherwise will be None.

    @@ -13361,7 +12807,7 @@
    Inherited Members

    Represents the profile string variable component.

    -

    This component will be available when aiobungie.ComponentType.STRING_VARIABLES +

    This component will be available when aiobungie.ComponentType.STRING_VARIABLES is passed to the request components. otherwise attributes will be None.

    Included Components
    @@ -13891,28 +13337,6 @@
    Returns
    - -
    -
    - trait_ids: list[str] - - -
    - - - - -
    -
    -
    - trait_hashes: list[int] - - -
    - - - -
    @@ -13968,17 +13392,6 @@
    Returns
    -
    -
    -
    - damagetype_hashes: Optional[collections.abc.Sequence[int]] - - -
    - - - -
    @@ -13992,28 +13405,6 @@
    Returns
    -
    -
    -
    - default_damagetype: int - - -
    - - - - -
    -
    -
    - default_damagetype_hash: Optional[int] - - -
    - - - -
    @@ -14120,17 +13511,6 @@
    Returns
    -
    -
    -
    - ui_display_style: Union[aiobungie.undefined.UndefinedType, str] - - -
    - - - -
    @@ -14249,17 +13629,6 @@
    Returns
    -
    -
    -
    - tooltip_notifications: list[str] - - -
    - - - -
    @@ -14325,17 +13694,6 @@
    Returns
    -
    -
    -
    - suppress_expiration: Optional[bool] - - -
    - - - -
    @@ -14375,17 +13733,6 @@
    Returns
    -
    -
    -
    - allow_actions: bool - - -
    - - - -
    @@ -14412,28 +13759,6 @@
    Returns
    -
    -
    -
    - category_hashes: collections.abc.Sequence[int] - - -
    - - - - -
    -
    -
    - season_hash: Optional[int] - - -
    - - - -
    Inherited Members
    @@ -14482,13 +13807,13 @@
    Inherited Members
    527 light_level: int 528 """Activity's light level.""" 529 -530 place: typedefs.IntAnd[enums.Place] +530 place: enums.Place 531 """The place of this activity.""" 532 533 type_hash: int 534 """The activity's type hash. This bounds to activity types such as Strikes, Crucible, Raids, etc.""" 535 -536 tier: typedefs.IntAnd[activity.Difficulty] +536 tier: activity.Difficulty 537 """Activity's difficulty tier.""" 538 539 image: assets.Image @@ -14523,39 +13848,35 @@
    Inherited Members
    568 guided_game: typing.Optional[activity.GuidedGame] 569 """Information about activity's guided game mode, If exists otherwise `None`.""" 570 -571 mode: typing.Optional[typedefs.IntAnd[enums.GameMode]] +571 mode: typing.Optional[enums.GameMode] 572 """If this activity had an activity mode directly defined on it, this will be the hash of that mode.""" 573 574 mode_hash: typing.Optional[int] 575 """If the activity had an activity mode directly defined on it, this will be the enum value of that mode.""" 576 -577 mode_hashes: collections.Sequence[typedefs.IntAnd[enums.GameMode]] = attrs.field( -578 repr=False -579 ) -580 """The hash identifiers for Activity Modes relevant to this entry.""" -581 -582 mode_types: collections.Sequence[typedefs.IntAnd[enums.GameMode]] = attrs.field( -583 repr=False -584 ) -585 """A sequence of the activity gamemode types.""" -586 -587 loadouts: collections.Sequence[int] -588 """The set of all possible loadout requirements that could be active for this activity. +577 mode_hashes: collections.Sequence[enums.GameMode] = attrs.field(repr=False) +578 """The hash identifiers for Activity Modes relevant to this entry.""" +579 +580 mode_types: collections.Sequence[enums.GameMode] = attrs.field(repr=False) +581 """A sequence of the activity gamemode types.""" +582 +583 loadouts: collections.Sequence[int] +584 """The set of all possible loadout requirements that could be active for this activity. +585 +586 Only one will be active at any given time. and you can discover which one through +587 activity-associated data such as Milestones that have activity info on them. +588 """ 589 -590 Only one will be active at any given time. and you can discover which one through -591 activity-associated data such as Milestones that have activity info on them. -592 """ -593 -594 is_pvp: bool -595 """Whether the activity is PvP or not.""" -596 -597 phase_hashes: collections.Sequence[int] -598 """The list of phases or points of entry into an activity, -599 along with information we can use to determine their gating and availability. -600 """ -601 -602 locations: collections.Collection[activity.Location] -603 """A collection of location mappings affected by this activity.""" +590 is_pvp: bool +591 """Whether the activity is PvP or not.""" +592 +593 phase_hashes: collections.Sequence[int] +594 """The list of phases or points of entry into an activity, +595 along with information we can use to determine their gating and availability. +596 """ +597 +598 locations: collections.Collection[activity.Location] +599 """A collection of location mappings affected by this activity."""
    @@ -14569,7 +13890,7 @@
    Inherited Members
    - ActivityEntity( *, net: aiobungie.traits.Netrunner, hash: int, index: int, name: Union[aiobungie.undefined.UndefinedType, str], description: Union[aiobungie.undefined.UndefinedType, str], icon: aiobungie.internal.assets.Image, has_icon: bool, release_icon: aiobungie.internal.assets.Image, release_time: int, unlock_hash: int, light_level: int, place: Union[int, aiobungie.internal.enums.Place], type_hash: int, tier: Union[int, aiobungie.crates.activity.Difficulty], image: aiobungie.internal.assets.Image, rewards: Optional[collections.abc.Sequence[aiobungie.crates.Rewards]], modifiers: Optional[collections.abc.Sequence[int]], challenges: Optional[collections.abc.Sequence[aiobungie.crates.Challenges]], is_playlist: bool, unlock_strings: Optional[collections.abc.Sequence[str]], inherits_free_room: bool, playlist_activities: Optional[collections.abc.Sequence[aiobungie.crates.PlaylistActivityEntity]], matchmaking: aiobungie.crates.Matchmaking, guided_game: Optional[aiobungie.crates.GuidedGame], mode: Union[int, aiobungie.internal.enums.GameMode, NoneType], mode_hash: Optional[int], mode_hashes: collections.abc.Sequence[typing.Union[int, aiobungie.internal.enums.GameMode]], mode_types: collections.abc.Sequence[typing.Union[int, aiobungie.internal.enums.GameMode]], loadouts: collections.abc.Sequence[int], is_pvp: bool, phase_hashes: collections.abc.Sequence[int], locations: collections.abc.Collection[aiobungie.crates.Location]) + ActivityEntity( *, net: aiobungie.traits.Netrunner, hash: int, index: int, name: Union[aiobungie.undefined.UndefinedType, str], description: Union[aiobungie.undefined.UndefinedType, str], icon: aiobungie.internal.assets.Image, has_icon: bool, release_icon: aiobungie.internal.assets.Image, release_time: int, unlock_hash: int, light_level: int, place: aiobungie.internal.enums.Place, type_hash: int, tier: aiobungie.crates.activity.Difficulty, image: aiobungie.internal.assets.Image, rewards: Optional[collections.abc.Sequence[aiobungie.crates.Rewards]], modifiers: Optional[collections.abc.Sequence[int]], challenges: Optional[collections.abc.Sequence[aiobungie.crates.Challenges]], is_playlist: bool, unlock_strings: Optional[collections.abc.Sequence[str]], inherits_free_room: bool, playlist_activities: Optional[collections.abc.Sequence[aiobungie.crates.PlaylistActivityEntity]], matchmaking: aiobungie.crates.Matchmaking, guided_game: Optional[aiobungie.crates.GuidedGame], mode: Optional[aiobungie.internal.enums.GameMode], mode_hash: Optional[int], mode_hashes: collections.abc.Sequence[aiobungie.internal.enums.GameMode], mode_types: collections.abc.Sequence[aiobungie.internal.enums.GameMode], loadouts: collections.abc.Sequence[int], is_pvp: bool, phase_hashes: collections.abc.Sequence[int], locations: collections.abc.Collection[aiobungie.crates.Location]) @@ -14670,7 +13991,7 @@
    Inherited Members
    @@ -14696,7 +14017,7 @@
    Inherited Members
    - tier: Union[int, aiobungie.crates.activity.Difficulty] + tier: aiobungie.crates.activity.Difficulty
    @@ -14784,17 +14105,6 @@
    Inherited Members
    - -
    -
    - inherits_free_room: bool - - -
    - - - -
    @@ -14838,7 +14148,7 @@
    Inherited Members
    - mode: Union[int, aiobungie.internal.enums.GameMode, NoneType] + mode: Optional[aiobungie.internal.enums.GameMode]
    @@ -14864,7 +14174,7 @@
    Inherited Members
    - mode_hashes: collections.abc.Sequence[typing.Union[int, aiobungie.internal.enums.GameMode]] + mode_hashes: collections.abc.Sequence[aiobungie.internal.enums.GameMode]
    @@ -14877,7 +14187,7 @@
    Inherited Members
    - mode_types: collections.abc.Sequence[typing.Union[int, aiobungie.internal.enums.GameMode]] + mode_types: collections.abc.Sequence[aiobungie.internal.enums.GameMode]
    @@ -14972,32 +14282,32 @@
    Inherited Members
    -
    606@attrs.define(kw_only=True, hash=True, weakref_slot=False)
    -607class PlaylistActivityEntity:
    -608    """Represents an activity playlists definition/entity.
    -609
    -610    Derives `DestinyActivityPlaylistItemDefinition`
    -611    """
    -612
    -613    hash: int
    -614    """The hash identifier of the Activity that can be played."""
    -615
    -616    mode_hash: typing.Optional[int]
    -617    """If this activity had an activity mode directly defined on it, this will be the hash of that mode."""
    -618
    -619    mode: typing.Optional[typedefs.IntAnd[enums.GameMode]]
    -620    """If the activity had an activity mode directly defined on it, this will be the enum value of that mode."""
    -621
    -622    mode_hashes: collections.Sequence[int]
    -623    """The hash identifiers for Activity Modes relevant to this entry."""
    -624
    -625    mode_types: collections.Sequence[typedefs.IntAnd[enums.GameMode]]
    -626    """A sequence of the activity gamemode types."""
    -627
    -628    @helpers.unimplemented(available_in="0.2.7")
    -629    async def fetch_self(self) -> ActivityEntity:
    -630        """Fetch the definition of this activity."""
    -631        ...
    +            
    602@attrs.define(kw_only=True, hash=True, weakref_slot=False)
    +603class PlaylistActivityEntity:
    +604    """Represents an activity playlists definition/entity.
    +605
    +606    Derives `DestinyActivityPlaylistItemDefinition`
    +607    """
    +608
    +609    hash: int
    +610    """The hash identifier of the Activity that can be played."""
    +611
    +612    mode_hash: typing.Optional[int]
    +613    """If this activity had an activity mode directly defined on it, this will be the hash of that mode."""
    +614
    +615    mode: typing.Optional[enums.GameMode]
    +616    """If the activity had an activity mode directly defined on it, this will be the enum value of that mode."""
    +617
    +618    mode_hashes: collections.Sequence[int]
    +619    """The hash identifiers for Activity Modes relevant to this entry."""
    +620
    +621    mode_types: collections.Sequence[enums.GameMode]
    +622    """A sequence of the activity gamemode types."""
    +623
    +624    @helpers.unimplemented()
    +625    async def fetch_self(self) -> ActivityEntity:
    +626        """Fetch the definition of this activity."""
    +627        ...
     
    @@ -15011,7 +14321,7 @@
    Inherited Members
    - PlaylistActivityEntity( *, hash: int, mode_hash: Optional[int], mode: Union[int, aiobungie.internal.enums.GameMode, NoneType], mode_hashes: collections.abc.Sequence[int], mode_types: collections.abc.Sequence[typing.Union[int, aiobungie.internal.enums.GameMode]]) + PlaylistActivityEntity( *, hash: int, mode_hash: Optional[int], mode: Optional[aiobungie.internal.enums.GameMode], mode_hashes: collections.abc.Sequence[int], mode_types: collections.abc.Sequence[aiobungie.internal.enums.GameMode]) @@ -15059,7 +14369,7 @@
    Inherited Members
    - mode: Union[int, aiobungie.internal.enums.GameMode, NoneType] + mode: Optional[aiobungie.internal.enums.GameMode]
    @@ -15085,7 +14395,7 @@
    Inherited Members
    - mode_types: collections.abc.Sequence[typing.Union[int, aiobungie.internal.enums.GameMode]] + mode_types: collections.abc.Sequence[aiobungie.internal.enums.GameMode]
    @@ -15099,7 +14409,7 @@
    Inherited Members
    -
    @helpers.unimplemented(available_in='0.2.7')
    +
    @helpers.unimplemented()
    def fetch_self(self) -> aiobungie.crates.ActivityEntity: @@ -15108,10 +14418,10 @@
    Inherited Members
    -
    628    @helpers.unimplemented(available_in="0.2.7")
    -629    async def fetch_self(self) -> ActivityEntity:
    -630        """Fetch the definition of this activity."""
    -631        ...
    +            
    624    @helpers.unimplemented()
    +625    async def fetch_self(self) -> ActivityEntity:
    +626        """Fetch the definition of this activity."""
    +627        ...
     
    @@ -15148,7 +14458,7 @@
    Inherited Members
    475 476 completion_value: int 477 -478 scope: typedefs.IntAnd[GatingScope] +478 scope: GatingScope 479 480 location_hash: int 481 @@ -15160,15 +14470,15 @@
    Inherited Members
    487 488 display_only_objective: bool 489 -490 value_style: typedefs.IntAnd[ValueUIStyle] +490 value_style: ValueUIStyle 491 -492 complete_value_style: typedefs.IntAnd[ValueUIStyle] +492 complete_value_style: ValueUIStyle 493 -494 progress_value_style: typedefs.IntAnd[ValueUIStyle] +494 progress_value_style: ValueUIStyle 495 496 allow_over_completion: bool 497 -498 show_value_style: typedefs.IntAnd[ValueUIStyle] +498 show_value_style: ValueUIStyle 499 500 progress_description: str 501 @@ -15182,264 +14492,55 @@
    Inherited Members
    -

    Represents a bungie inventory item entity.

    - -

    This derives from DestinyObjectiveDefinition definition.

    -
    - - -
    - -
    - - ObjectiveEntity( *, net: aiobungie.traits.Netrunner, hash: int, index: int, name: Union[aiobungie.undefined.UndefinedType, str], description: Union[aiobungie.undefined.UndefinedType, str], icon: aiobungie.internal.assets.Image, has_icon: bool, unlock_value_hash: int, minimum_visibility: int, completion_value: int, scope: Union[int, aiobungie.crates.entity.GatingScope], location_hash: int, allowed_negative_value: bool, allowed_value_change: bool, counting_downward: bool, display_only_objective: bool, value_style: Union[int, aiobungie.crates.entity.ValueUIStyle], complete_value_style: Union[int, aiobungie.crates.entity.ValueUIStyle], progress_value_style: Union[int, aiobungie.crates.entity.ValueUIStyle], allow_over_completion: bool, show_value_style: Union[int, aiobungie.crates.entity.ValueUIStyle], progress_description: str, perks: dict[str, int], stats: dict[str, int], ui_label: str, ui_style: aiobungie.crates.entity.ObjectiveUIStyle) - - - -
    - -
     2def __init__(self, *, net, hash, index, name, description, icon, has_icon, unlock_value_hash, minimum_visibility, completion_value, scope, location_hash, allowed_negative_value, allowed_value_change, counting_downward, display_only_objective, value_style, complete_value_style, progress_value_style, allow_over_completion, show_value_style, progress_description, perks, stats, ui_label, ui_style):
    - 3    self.net = net
    - 4    self.hash = hash
    - 5    self.index = index
    - 6    self.name = name
    - 7    self.description = description
    - 8    self.icon = icon
    - 9    self.has_icon = has_icon
    -10    self.unlock_value_hash = unlock_value_hash
    -11    self.minimum_visibility = minimum_visibility
    -12    self.completion_value = completion_value
    -13    self.scope = scope
    -14    self.location_hash = location_hash
    -15    self.allowed_negative_value = allowed_negative_value
    -16    self.allowed_value_change = allowed_value_change
    -17    self.counting_downward = counting_downward
    -18    self.display_only_objective = display_only_objective
    -19    self.value_style = value_style
    -20    self.complete_value_style = complete_value_style
    -21    self.progress_value_style = progress_value_style
    -22    self.allow_over_completion = allow_over_completion
    -23    self.show_value_style = show_value_style
    -24    self.progress_description = progress_description
    -25    self.perks = perks
    -26    self.stats = stats
    -27    self.ui_label = ui_label
    -28    self.ui_style = ui_style
    -
    - - -

    Method generated by attrs for class ObjectiveEntity.

    -
    - - -
    -
    -
    - unlock_value_hash: int - - -
    - - - - -
    -
    -
    - minimum_visibility: int - - -
    - - - - -
    -
    -
    - completion_value: int - - -
    - - - - -
    -
    -
    - scope: Union[int, aiobungie.crates.entity.GatingScope] - - -
    - - - - -
    -
    -
    - location_hash: int - - -
    - - - - -
    -
    -
    - allowed_negative_value: bool - - -
    - - - - -
    -
    -
    - allowed_value_change: bool - - -
    - - - - -
    -
    -
    - counting_downward: bool - - -
    - - - - -
    -
    -
    - display_only_objective: bool - - -
    - - - - -
    -
    -
    - value_style: Union[int, aiobungie.crates.entity.ValueUIStyle] - - -
    - - - - -
    -
    -
    - complete_value_style: Union[int, aiobungie.crates.entity.ValueUIStyle] - - -
    - - - - -
    -
    -
    - progress_value_style: Union[int, aiobungie.crates.entity.ValueUIStyle] - - -
    - - - - -
    -
    -
    - allow_over_completion: bool - - -
    - - - - -
    -
    -
    - show_value_style: Union[int, aiobungie.crates.entity.ValueUIStyle] - - -
    - - - - -
    -
    -
    - progress_description: str - - -
    - - - - -
    -
    -
    - perks: dict[str, int] - - -
    - - - +

    Represents a bungie inventory item entity.

    -
    -
    -
    - stats: dict[str, int] +

    This derives from DestinyObjectiveDefinition definition.

    +
    - -
    - - - -
    -
    -
    - ui_label: str +
    + +
    + + ObjectiveEntity( *, net: aiobungie.traits.Netrunner, hash: int, index: int, name: Union[aiobungie.undefined.UndefinedType, str], description: Union[aiobungie.undefined.UndefinedType, str], icon: aiobungie.internal.assets.Image, has_icon: bool, unlock_value_hash: int, minimum_visibility: int, completion_value: int, scope: aiobungie.crates.entity.GatingScope, location_hash: int, allowed_negative_value: bool, allowed_value_change: bool, counting_downward: bool, display_only_objective: bool, value_style: aiobungie.crates.entity.ValueUIStyle, complete_value_style: aiobungie.crates.entity.ValueUIStyle, progress_value_style: aiobungie.crates.entity.ValueUIStyle, allow_over_completion: bool, show_value_style: aiobungie.crates.entity.ValueUIStyle, progress_description: str, perks: dict[str, int], stats: dict[str, int], ui_label: str, ui_style: aiobungie.crates.entity.ObjectiveUIStyle) + + -
    - - - + +
     2def __init__(self, *, net, hash, index, name, description, icon, has_icon, unlock_value_hash, minimum_visibility, completion_value, scope, location_hash, allowed_negative_value, allowed_value_change, counting_downward, display_only_objective, value_style, complete_value_style, progress_value_style, allow_over_completion, show_value_style, progress_description, perks, stats, ui_label, ui_style):
    + 3    self.net = net
    + 4    self.hash = hash
    + 5    self.index = index
    + 6    self.name = name
    + 7    self.description = description
    + 8    self.icon = icon
    + 9    self.has_icon = has_icon
    +10    self.unlock_value_hash = unlock_value_hash
    +11    self.minimum_visibility = minimum_visibility
    +12    self.completion_value = completion_value
    +13    self.scope = scope
    +14    self.location_hash = location_hash
    +15    self.allowed_negative_value = allowed_negative_value
    +16    self.allowed_value_change = allowed_value_change
    +17    self.counting_downward = counting_downward
    +18    self.display_only_objective = display_only_objective
    +19    self.value_style = value_style
    +20    self.complete_value_style = complete_value_style
    +21    self.progress_value_style = progress_value_style
    +22    self.allow_over_completion = allow_over_completion
    +23    self.show_value_style = show_value_style
    +24    self.progress_description = progress_description
    +25    self.perks = perks
    +26    self.stats = stats
    +27    self.ui_label = ui_label
    +28    self.ui_style = ui_style
    +
    -
    -
    -
    - ui_style: aiobungie.crates.entity.ObjectiveUIStyle - -
    - - - +

    Method generated by attrs for class ObjectiveEntity.

    +
    +
    @@ -15872,68 +14973,68 @@
    Raises
    -
    273@attrs.define(kw_only=True)
    -274class Fireteam:
    -275    """A representation of a Bungie fireteam."""
    -276
    -277    id: int
    -278    """The fireteam id."""
    -279
    -280    group_id: int
    -281    """The fireteam group id."""
    -282
    -283    platform: FireteamPlatform
    -284    """The fireteam platform."""
    -285
    -286    activity_type: FireteamActivity
    -287    """The activity this fireteam is planning to run."""
    -288
    -289    is_immediate: bool
    -290    """Whether the fireteam activity is immediate or not."""
    -291
    -292    owner_id: int
    -293    """The fireteam owner id."""
    -294
    -295    player_slot_count: int
    -296    """The needed player count in this fireteam."""
    -297
    -298    available_player_slots: int
    -299    """The available player slots in this fireteam."""
    -300
    -301    available_alternate_slots: int
    -302    """The alternate available player slots in this fireteam."""
    -303
    -304    title: undefined.UndefinedOr[str]
    -305    """The fireteam title. Could be `UNDEFINED` if not set."""
    -306
    -307    date_created: datetime.datetime
    -308    """A datetime of when was this fireteam created."""
    -309
    -310    is_public: bool
    -311    """Whether the fireteam is public or not."""
    -312
    -313    locale: FireteamLanguage
    -314    """The selected locale language for this fireteam."""
    -315
    -316    is_valid: bool
    -317    """Whether this fireteam is valid or not."""
    -318
    -319    last_modified: datetime.datetime
    -320    """A datetime of when was this fireteam created."""
    -321
    -322    total_results: int
    -323    """The total results of the found activities."""
    -324
    -325    @property
    -326    def url(self) -> str:
    -327        """The activity url at Bungie.net."""
    -328        return f"{url.BASE}/en/ClanV2/PublicFireteam?groupId={self.group_id}&fireteamId={self.id}"  # noqa: E501
    -329
    -330    def __int__(self) -> int:
    -331        return self.id
    -332
    -333    def __str__(self) -> str:
    -334        return str(self.title)
    +            
    272@attrs.define(kw_only=True)
    +273class Fireteam:
    +274    """A representation of a Bungie fireteam."""
    +275
    +276    id: int
    +277    """The fireteam id."""
    +278
    +279    group_id: int
    +280    """The fireteam group id."""
    +281
    +282    platform: FireteamPlatform
    +283    """The fireteam platform."""
    +284
    +285    activity_type: FireteamActivity
    +286    """The activity this fireteam is planning to run."""
    +287
    +288    is_immediate: bool
    +289    """Whether the fireteam activity is immediate or not."""
    +290
    +291    owner_id: int
    +292    """The fireteam owner id."""
    +293
    +294    player_slot_count: int
    +295    """The needed player count in this fireteam."""
    +296
    +297    available_player_slots: int
    +298    """The available player slots in this fireteam."""
    +299
    +300    available_alternate_slots: int
    +301    """The alternate available player slots in this fireteam."""
    +302
    +303    title: undefined.UndefinedOr[str]
    +304    """The fireteam title. Could be `UNDEFINED` if not set."""
    +305
    +306    date_created: datetime.datetime
    +307    """A datetime of when was this fireteam created."""
    +308
    +309    is_public: bool
    +310    """Whether the fireteam is public or not."""
    +311
    +312    locale: FireteamLanguage
    +313    """The selected locale language for this fireteam."""
    +314
    +315    is_valid: bool
    +316    """Whether this fireteam is valid or not."""
    +317
    +318    last_modified: datetime.datetime
    +319    """A datetime of when was this fireteam created."""
    +320
    +321    total_results: int
    +322    """The total results of the found activities."""
    +323
    +324    @property
    +325    def url(self) -> str:
    +326        """The activity url at Bungie.net."""
    +327        return f"{url.BASE}/en/ClanV2/PublicFireteam?groupId={self.group_id}&fireteamId={self.id}"  # noqa: E501
    +328
    +329    def __int__(self) -> int:
    +330        return self.id
    +331
    +332    def __str__(self) -> str:
    +333        return str(self.title)
     
    @@ -16210,15 +15311,15 @@
    Raises
    -
    337@attrs.define(kw_only=True)
    -338class AvailableFireteam(Fireteam):
    -339    """Represents an available clan fireteam. This includes the members and alternative members."""
    -340
    -341    members: typing.Optional[collections.Sequence[FireteamMember]]
    -342    """A sequence of the fireteam members."""
    -343
    -344    alternatives: typing.Optional[collections.Sequence[FireteamMember]]
    -345    """A sequence of the fireteam alternative members."""
    +            
    336@attrs.define(kw_only=True)
    +337class AvailableFireteam(Fireteam):
    +338    """Represents an available clan fireteam. This includes the members and alternative members."""
    +339
    +340    members: typing.Optional[collections.Sequence[FireteamMember]]
    +341    """A sequence of the fireteam members."""
    +342
    +343    alternatives: typing.Optional[collections.Sequence[FireteamMember]]
    +344    """A sequence of the fireteam alternative members."""
     
    @@ -16327,15 +15428,15 @@
    Inherited Members
    -
    239@attrs.define(kw_only=True)
    -240class FireteamUser(user.DestinyMembership):
    -241    """Represents a Bungie fireteam user info."""
    -242
    -243    fireteam_display_name: str
    -244    """The fireteam display name."""
    -245
    -246    fireteam_membership_id: enums.MembershipType
    -247    """The fireteam's membership type."""
    +            
    238@attrs.define(kw_only=True)
    +239class FireteamUser(user.DestinyMembership):
    +240    """Represents a Bungie fireteam user info."""
    +241
    +242    fireteam_display_name: str
    +243    """The fireteam display name."""
    +244
    +245    fireteam_membership_id: enums.MembershipType
    +246    """The fireteam's membership type."""
     
    @@ -16347,7 +15448,7 @@
    Inherited Members
    - FireteamUser( *, net: 'traits.Netrunner', id: int, name: Union[aiobungie.undefined.UndefinedType, str], last_seen_name: str, type: aiobungie.internal.enums.MembershipType, types: collections.abc.Sequence[aiobungie.internal.enums.MembershipType], icon: 'assets.Image', code: Optional[int], is_public: bool, crossave_override: Union[aiobungie.internal.enums.MembershipType, int], fireteam_display_name: str, fireteam_membership_id: aiobungie.internal.enums.MembershipType) + FireteamUser( *, net: 'traits.Netrunner', id: int, name: Union[aiobungie.undefined.UndefinedType, str], last_seen_name: str, type: aiobungie.internal.enums.MembershipType, types: collections.abc.Sequence[aiobungie.internal.enums.MembershipType], icon: 'assets.Image', code: 'typedefs.NoneOr[int]', is_public: bool, crossave_override: Union[aiobungie.internal.enums.MembershipType, int], fireteam_display_name: str, fireteam_membership_id: aiobungie.internal.enums.MembershipType) @@ -16437,27 +15538,27 @@
    Inherited Members
    -
    250@attrs.define(kw_only=True)
    -251class FireteamMember(user.PartialBungieUser):
    -252    """Represents a Bungie fireteam member."""
    -253
    -254    destiny_user: FireteamUser
    -255    """The destiny user info related to this fireteam member."""
    -256
    -257    character_id: int
    -258    """Fireteam member's character id."""
    -259
    -260    date_joined: datetime.datetime
    -261    """Fireteam member's join date."""
    -262
    -263    has_microphone: bool
    -264    """Whether the fireteam member has a mic or not."""
    -265
    -266    last_platform_invite_date: datetime.datetime
    -267    """"""
    -268
    -269    last_platform_invite_result: int
    -270    """"""
    +            
    249@attrs.define(kw_only=True)
    +250class FireteamMember(user.PartialBungieUser):
    +251    """Represents a Bungie fireteam member."""
    +252
    +253    destiny_user: FireteamUser
    +254    """The destiny user info related to this fireteam member."""
    +255
    +256    character_id: int
    +257    """Fireteam member's character id."""
    +258
    +259    date_joined: datetime.datetime
    +260    """Fireteam member's join date."""
    +261
    +262    has_microphone: bool
    +263    """Whether the fireteam member has a mic or not."""
    +264
    +265    last_platform_invite_date: datetime.datetime
    +266    """"""
    +267
    +268    last_platform_invite_result: int
    +269    """"""
     
    @@ -16549,28 +15650,6 @@
    Inherited Members
    -
    -
    -
    - last_platform_invite_date: datetime.datetime - - -
    - - - - -
    -
    -
    - last_platform_invite_result: int - - -
    - - - -
    Inherited Members
    @@ -16602,18 +15681,18 @@
    Inherited Members
    -
    205@attrs.define(kw_only=True)
    -206class FireteamPartySettings:
    -207    """Represents information about a fireteam's joinability settngs."""
    -208
    -209    open_slots: int
    -210    """The number of open slots this fireteam has."""
    -211
    -212    privacy_setting: enums.PrivacySetting
    -213    """Fireteam leader's fireteam privacy setting."""
    -214
    -215    closed_reasons: typedefs.IntAnd[enums.ClosedReasons]
    -216    """Reasons why a person can't join this person's fireteam."""
    +            
    204@attrs.define(kw_only=True)
    +205class FireteamPartySettings:
    +206    """Represents information about a fireteam's joinability settngs."""
    +207
    +208    open_slots: int
    +209    """The number of open slots this fireteam has."""
    +210
    +211    privacy_setting: enums.PrivacySetting
    +212    """Fireteam leader's fireteam privacy setting."""
    +213
    +214    closed_reasons: enums.ClosedReasons
    +215    """Reasons why a person can't join this person's fireteam."""
     
    @@ -16625,7 +15704,7 @@
    Inherited Members
    - FireteamPartySettings( *, open_slots: int, privacy_setting: aiobungie.internal.enums.PrivacySetting, closed_reasons: Union[int, aiobungie.internal.enums.ClosedReasons]) + FireteamPartySettings( *, open_slots: int, privacy_setting: aiobungie.internal.enums.PrivacySetting, closed_reasons: aiobungie.internal.enums.ClosedReasons) @@ -16671,7 +15750,7 @@
    Inherited Members
    - closed_reasons: Union[int, aiobungie.internal.enums.ClosedReasons] + closed_reasons: aiobungie.internal.enums.ClosedReasons
    @@ -16695,27 +15774,27 @@
    Inherited Members
    -
    159@attrs.define(kw_only=True)
    -160class FireteamPartyMember:
    -161    """Minimal information about a party member in a fireteam."""
    -162
    -163    membership_id: int
    -164    """Party member's membership id."""
    -165
    -166    emblem_hash: int
    -167    """Party member's emblem hash."""
    -168
    -169    display_name: undefined.UndefinedOr[str]
    -170    """Party member's display name. `UNDEFINED` if not set."""
    -171
    -172    status: typedefs.IntAnd[FireteamPartyMemberState]
    -173    """A Flags Enumeration value indicating the states that the player is in relevant to being on a fireteam."""
    -174
    -175    def __str__(self) -> str:
    -176        return str(self.display_name)
    -177
    -178    def __int__(self) -> int:
    -179        return self.membership_id
    +            
    158@attrs.define(kw_only=True)
    +159class FireteamPartyMember:
    +160    """Minimal information about a party member in a fireteam."""
    +161
    +162    membership_id: int
    +163    """Party member's membership id."""
    +164
    +165    emblem_hash: int
    +166    """Party member's emblem hash."""
    +167
    +168    display_name: undefined.UndefinedOr[str]
    +169    """Party member's display name. `UNDEFINED` if not set."""
    +170
    +171    status: FireteamPartyMemberState
    +172    """A Flags Enumeration value indicating the states that the player is in relevant to being on a fireteam."""
    +173
    +174    def __str__(self) -> str:
    +175        return str(self.display_name)
    +176
    +177    def __int__(self) -> int:
    +178        return self.membership_id
     
    @@ -16727,7 +15806,7 @@
    Inherited Members
    - FireteamPartyMember( *, membership_id: int, emblem_hash: int, display_name: Union[aiobungie.undefined.UndefinedType, str], status: Union[int, aiobungie.crates.fireteams.FireteamPartyMemberState]) + FireteamPartyMember( *, membership_id: int, emblem_hash: int, display_name: Union[aiobungie.undefined.UndefinedType, str], status: aiobungie.crates.fireteams.FireteamPartyMemberState) @@ -16787,7 +15866,7 @@
    Inherited Members
    - status: Union[int, aiobungie.crates.fireteams.FireteamPartyMemberState] + status: aiobungie.crates.fireteams.FireteamPartyMemberState
    @@ -16811,27 +15890,27 @@
    Inherited Members
    -
    182@attrs.define(kw_only=True)
    -183class FireteamPartyCurrentActivity:
    -184    """Represents information about a fireteam party's current activity."""
    -185
    -186    start_time: typing.Optional[datetime.datetime]
    -187    """An optional datetime of when was this activity started."""
    -188
    -189    end_time: typing.Optional[datetime.datetime]
    -190    """An optional datetime of when was this activity ended."""
    -191
    -192    score: float
    -193    """This is the total score of the activity."""
    -194
    -195    highest_opposing_score: float
    -196    """If the activity was against humans, This will be their highest score."""
    -197
    -198    opponenst_count: int
    -199    """How many human opponents were playing against this fireteam."""
    -200
    -201    player_count: int
    -202    """How many human players were playing in this fireteam."""
    +            
    181@attrs.define(kw_only=True)
    +182class FireteamPartyCurrentActivity:
    +183    """Represents information about a fireteam party's current activity."""
    +184
    +185    start_time: typing.Optional[datetime.datetime]
    +186    """An optional datetime of when was this activity started."""
    +187
    +188    end_time: typing.Optional[datetime.datetime]
    +189    """An optional datetime of when was this activity ended."""
    +190
    +191    score: float
    +192    """This is the total score of the activity."""
    +193
    +194    highest_opposing_score: float
    +195    """If the activity was against humans, This will be their highest score."""
    +196
    +197    opponenst_count: int
    +198    """How many human opponents were playing against this fireteam."""
    +199
    +200    player_count: int
    +201    """How many human players were playing in this fireteam."""
     
    @@ -16955,24 +16034,24 @@
    Inherited Members
    -
    219@attrs.define(kw_only=True)
    -220class FireteamParty:
    -221    """Represents a fireteam party. This information found in profile transitory component."""
    -222
    -223    members: collections.Sequence[FireteamPartyMember]
    -224    """The party members currently in this fireteam."""
    -225
    -226    activity: FireteamPartyCurrentActivity
    -227    """The current activity this fireteam is in."""
    -228
    -229    settings: FireteamPartySettings
    -230    """Information about the fireteam joinability settings, e.g. Privacy, Open slots."""
    -231
    -232    last_destination_hash: typing.Optional[int]
    -233    """The hash identifier for the destination of the last location you were orbiting when in orbit."""
    -234
    -235    tracking: list[dict[str, typing.Any]]
    -236    """???"""
    +            
    218@attrs.define(kw_only=True)
    +219class FireteamParty:
    +220    """Represents a fireteam party. This information found in profile transitory component."""
    +221
    +222    members: collections.Sequence[FireteamPartyMember]
    +223    """The party members currently in this fireteam."""
    +224
    +225    activity: FireteamPartyCurrentActivity
    +226    """The current activity this fireteam is in."""
    +227
    +228    settings: FireteamPartySettings
    +229    """Information about the fireteam joinability settings, e.g. Privacy, Open slots."""
    +230
    +231    last_destination_hash: typing.Optional[int]
    +232    """The hash identifier for the destination of the last location you were orbiting when in orbit."""
    +233
    +234    tracking: list[dict[str, typing.Any]]
    +235    """???"""
     
    @@ -18028,17 +17107,6 @@
    Raises
    -
    -
    -
    - order: int - - -
    - - - -
    @@ -18224,28 +17292,6 @@
    Raises
    -
    -
    -
    - item_hash: int - - -
    - - - - -
    -
    - - - - -
    @@ -18294,28 +17340,6 @@
    Raises
    -
    -
    -
    - vendor_hash: int - - -
    - - - - -
    -
    -
    - preview_itemhash: Optional[int] - - -
    - - - -
    @@ -18498,17 +17522,6 @@
    Raises
    -
    -
    - - - - -
    @@ -18746,17 +17759,6 @@
    Returns
    -
    -
    -
    - category_hash: int - - -
    - - - -
    @@ -18877,78 +17879,73 @@
    Returns
    -
    157@attrs.define(kw_only=True)
    -158class Profile:
    -159    """Represents a Bungie member profile-only component.
    -160
    -161    This is only a `PROFILE` component and not the profile itself.
    -162    See `aiobungie.crates.Component` for other components.
    -163    """
    -164
    -165    id: int
    -166    """Profile's id"""
    -167
    -168    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    -169    """A network state used for making external requests."""
    -170
    -171    name: str
    -172    """Profile's name."""
    -173
    -174    type: enums.MembershipType
    -175    """Profile's type."""
    -176
    -177    is_public: bool
    -178    """Profile's privacy status."""
    -179
    -180    last_played: datetime.datetime
    -181    """Profile's last played Destiny 2 played date."""
    -182
    -183    character_ids: list[int]
    -184    """A list of the profile's character ids."""
    -185
    -186    power_cap: int
    -187    """The profile's current season power cap."""
    -188
    -189    async def _await_all_chars(
    -190        self, components: list[enums.ComponentType], auth: typing.Optional[str] = None
    -191    ) -> collections.Sequence[components.CharacterComponent]:
    -192        return await helpers.awaits(
    -193            *[
    -194                self.net.request.fetch_character(
    -195                    self.id, self.type, char_id, components, auth
    -196                )
    -197                for char_id in self.character_ids
    -198            ]
    -199        )
    -200
    -201    async def collect_characters(
    -202        self, components: list[enums.ComponentType], auth: typing.Optional[str] = None
    -203    ) -> collections.Sequence[components.CharacterComponent]:
    -204        """Fetch this profile's characters.
    -205
    -206        Parameters
    -207        ----------
    -208        components: `list[aiobungie.ComponentType]`
    -209            Multiple arguments of character components to collect and return.
    -210
    -211        Other Parameters
    -212        ----------------
    -213        auth : `typing.Optional[str]`
    -214            A passed kwarg Bearer access_token to make the request with.
    -215            This is optional and limited to components that only requires an Authorization token.
    -216
    -217        Returns
    -218        -------
    -219        `collections.Sequence[aiobungie.crates.CharacterComponent]`
    -220            A sequence of the characters components.
    -221        """
    -222        return await self._await_all_chars(components, auth)
    -223
    -224    def __str__(self) -> str:
    -225        return self.name
    -226
    -227    def __int__(self) -> int:
    -228        return int(self.id)
    +            
    156@attrs.define(kw_only=True)
    +157class Profile:
    +158    """Represents a Bungie member profile-only component.
    +159
    +160    This is only a `PROFILE` component and not the profile itself.
    +161    See `aiobungie.crates.Component` for other components.
    +162    """
    +163
    +164    id: int
    +165    """Profile's id"""
    +166
    +167    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    +168    """A network state used for making external requests."""
    +169
    +170    name: str
    +171    """Profile's name."""
    +172
    +173    type: enums.MembershipType
    +174    """Profile's type."""
    +175
    +176    is_public: bool
    +177    """Profile's privacy status."""
    +178
    +179    last_played: datetime.datetime
    +180    """Profile's last played Destiny 2 played date."""
    +181
    +182    character_ids: list[int]
    +183    """A list of the profile's character ids."""
    +184
    +185    power_cap: int
    +186    """The profile's current season power cap."""
    +187
    +188    async def collect_characters(
    +189        self, components: list[enums.ComponentType], auth: typing.Optional[str] = None
    +190    ) -> collections.Sequence[components.CharacterComponent]:
    +191        """Fetch this profile's characters.
    +192
    +193        Parameters
    +194        ----------
    +195        components: `list[aiobungie.ComponentType]`
    +196            A sequence of character components to collect and return.
    +197
    +198        Other Parameters
    +199        ----------------
    +200        auth : `typing.Optional[str]`
    +201            A Bearer access_token to make the request with.
    +202            This is optional and limited to components that only requires an Authorization token.
    +203
    +204        Returns
    +205        -------
    +206        `collections.Sequence[aiobungie.crates.CharacterComponent]`
    +207            A sequence of the characters components.
    +208        """
    +209        return await helpers.awaits(
    +210            *[
    +211                self.net.request.fetch_character(
    +212                    self.id, self.type, char_id, components, auth
    +213                )
    +214                for char_id in self.character_ids
    +215            ]
    +216        )
    +217
    +218    def __str__(self) -> str:
    +219        return self.name
    +220
    +221    def __int__(self) -> int:
    +222        return int(self.id)
     
    @@ -19101,28 +18098,35 @@
    Returns
    -
    201    async def collect_characters(
    -202        self, components: list[enums.ComponentType], auth: typing.Optional[str] = None
    -203    ) -> collections.Sequence[components.CharacterComponent]:
    -204        """Fetch this profile's characters.
    -205
    -206        Parameters
    -207        ----------
    -208        components: `list[aiobungie.ComponentType]`
    -209            Multiple arguments of character components to collect and return.
    -210
    -211        Other Parameters
    -212        ----------------
    -213        auth : `typing.Optional[str]`
    -214            A passed kwarg Bearer access_token to make the request with.
    -215            This is optional and limited to components that only requires an Authorization token.
    -216
    -217        Returns
    -218        -------
    -219        `collections.Sequence[aiobungie.crates.CharacterComponent]`
    -220            A sequence of the characters components.
    -221        """
    -222        return await self._await_all_chars(components, auth)
    +            
    188    async def collect_characters(
    +189        self, components: list[enums.ComponentType], auth: typing.Optional[str] = None
    +190    ) -> collections.Sequence[components.CharacterComponent]:
    +191        """Fetch this profile's characters.
    +192
    +193        Parameters
    +194        ----------
    +195        components: `list[aiobungie.ComponentType]`
    +196            A sequence of character components to collect and return.
    +197
    +198        Other Parameters
    +199        ----------------
    +200        auth : `typing.Optional[str]`
    +201            A Bearer access_token to make the request with.
    +202            This is optional and limited to components that only requires an Authorization token.
    +203
    +204        Returns
    +205        -------
    +206        `collections.Sequence[aiobungie.crates.CharacterComponent]`
    +207            A sequence of the characters components.
    +208        """
    +209        return await helpers.awaits(
    +210            *[
    +211                self.net.request.fetch_character(
    +212                    self.id, self.type, char_id, components, auth
    +213                )
    +214                for char_id in self.character_ids
    +215            ]
    +216        )
     
    @@ -19132,14 +18136,14 @@
    Parameters
    • components (list[aiobungie.ComponentType]): -Multiple arguments of character components to collect and return.
    • +A sequence of character components to collect and return.
    Other Parameters
    • auth (typing.Optional[str]): -A passed kwarg Bearer access_token to make the request with. +A Bearer access_token to make the request with. This is optional and limited to components that only requires an Authorization token.
    @@ -19165,24 +18169,24 @@
    Returns
    -
    54@attrs.define(kw_only=True)
    -55class LinkedProfile:
    -56    """Represents a membership linked profile information summary."""
    -57
    -58    net: traits.Netrunner = attrs.field(repr=False, eq=False, hash=False)
    -59    """A network state used for making external requests."""
    -60
    -61    profiles: collections.Sequence[user.DestinyMembership]
    -62    """A sequence of destiny memberships for this profile."""
    -63
    -64    bungie: user.PartialBungieUser
    -65    """The profile's bungie membership."""
    -66
    -67    profiles_with_errors: typing.Optional[collections.Sequence[user.DestinyMembership]]
    -68    """A sequence of optional destiny memberships with errors.
    -69
    -70    These profiles exists because they have missing fields. Otherwise this will be an empty array.
    -71    """
    +            
    53@attrs.define(kw_only=True)
    +54class LinkedProfile:
    +55    """Represents a membership linked profile information summary."""
    +56
    +57    net: traits.Netrunner = attrs.field(repr=False, eq=False, hash=False)
    +58    """A network state used for making external requests."""
    +59
    +60    profiles: collections.Sequence[user.DestinyMembership]
    +61    """A sequence of destiny memberships for this profile."""
    +62
    +63    bungie: user.PartialBungieUser
    +64    """The profile's bungie membership."""
    +65
    +66    profiles_with_errors: typing.Optional[collections.Sequence[user.DestinyMembership]]
    +67    """A sequence of optional destiny memberships with errors.
    +68
    +69    These profiles exists because they have missing fields. Otherwise this will be an empty array.
    +70    """
     
    @@ -19280,16 +18284,16 @@
    Returns
    -
    74@attrs.define(kw_only=True)
    -75class ProfileProgression:
    -76    """Represents a profile progression component details."""
    -77
    -78    artifact: season.Artifact
    -79    """The profile progression seasonal artifact."""
    -80
    -81    # No repr for this since its kinda huge dict.
    -82    checklist: collections.Mapping[int, collections.Mapping[int, bool]]
    -83    """A mapping of int to another mapping of int to bool for the profile progression checklist."""
    +            
    73@attrs.define(kw_only=True)
    +74class ProfileProgression:
    +75    """Represents a profile progression component details."""
    +76
    +77    artifact: season.Artifact
    +78    """The profile progression seasonal artifact."""
    +79
    +80    # No repr for this since its kinda huge dict.
    +81    checklist: collections.Mapping[int, collections.Mapping[int, bool]]
    +82    """A mapping of int to another mapping of int to bool for the profile progression checklist."""
     
    @@ -19357,75 +18361,75 @@
    Returns
    -
     86@attrs.mutable(kw_only=True)
    - 87class ProfileItemImpl:
    - 88    """Concrete implementation of any profile component item.
    - 89
    - 90    This also can be a character equipment i.e. Weapons, Armor, Ships, etc.
    - 91    """
    - 92
    - 93    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    - 94    """A network state used for making external requests."""
    - 95
    - 96    hash: int
    - 97    """The item type hash."""
    - 98
    - 99    quantity: int
    -100    """The item quantity."""
    -101
    -102    bind_status: enums.ItemBindStatus
    -103    """The item binding status."""
    -104
    -105    location: enums.ItemLocation
    -106    """The item location."""
    -107
    -108    bucket: int
    -109    """The item bucket hash."""
    -110
    -111    transfer_status: typedefs.IntAnd[enums.TransferStatus]
    -112    """The item's transfer status."""
    -113
    -114    lockable: bool
    -115    """Whether the item can be locked or not."""
    -116
    -117    state: enums.ItemState
    -118    """The item's state."""
    -119
    -120    dismantel_permissions: int
    -121    """The item's dismantel permission."""
    -122
    -123    is_wrapper: bool
    -124    """Whether the item is a wrapper or not."""
    -125
    -126    instance_id: typing.Optional[int]
    -127    """An inventory item instance id if available, otherwise will be `None`."""
    -128
    -129    ornament_id: typing.Optional[int]
    -130    """The ornament id of this item if it has one. Will be `None` otherwise."""
    -131
    -132    version_number: typing.Optional[int]
    -133    """The item version number of available, other wise will be `None`."""
    -134
    -135    @property
    -136    def is_transferable(self) -> bool:
    -137        """Check whether this item can be transferred or not."""
    -138        return (
    -139            self.transfer_status is enums.TransferStatus.CAN_TRANSFER
    -140            and self.instance_id is not None  # noqa: W503
    -141        )
    -142
    -143    async def fetch_self(self) -> entity.InventoryEntity:
    -144        """Fetch this profile item.
    -145
    -146        Returns
    -147        -------
    -148        `aiobungie.crates.InventoryEntity`
    -149            An inventory item definition entity.
    -150        """
    -151        return await self.net.request.fetch_inventory_item(self.hash)
    -152
    -153    def __int__(self) -> int:
    -154        return self.hash
    +            
     85@attrs.mutable(kw_only=True)
    + 86class ProfileItemImpl:
    + 87    """Concrete implementation of any profile component item.
    + 88
    + 89    This also can be a character equipment i.e. Weapons, Armor, Ships, etc.
    + 90    """
    + 91
    + 92    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    + 93    """A network state used for making external requests."""
    + 94
    + 95    hash: int
    + 96    """The item type hash."""
    + 97
    + 98    quantity: int
    + 99    """The item quantity."""
    +100
    +101    bind_status: enums.ItemBindStatus
    +102    """The item binding status."""
    +103
    +104    location: enums.ItemLocation
    +105    """The item location."""
    +106
    +107    bucket: int
    +108    """The item bucket hash."""
    +109
    +110    transfer_status: enums.TransferStatus
    +111    """The item's transfer status."""
    +112
    +113    lockable: bool
    +114    """Whether the item can be locked or not."""
    +115
    +116    state: enums.ItemState
    +117    """The item's state."""
    +118
    +119    dismantel_permissions: int
    +120    """The item's dismantel permission."""
    +121
    +122    is_wrapper: bool
    +123    """Whether the item is a wrapper or not."""
    +124
    +125    instance_id: typing.Optional[int]
    +126    """An inventory item instance id if available, otherwise will be `None`."""
    +127
    +128    ornament_id: typing.Optional[int]
    +129    """The ornament id of this item if it has one. Will be `None` otherwise."""
    +130
    +131    version_number: typing.Optional[int]
    +132    """The item version number of available, other wise will be `None`."""
    +133
    +134    @property
    +135    def is_transferable(self) -> bool:
    +136        """Check whether this item can be transferred or not."""
    +137        return (
    +138            self.transfer_status is enums.TransferStatus.CAN_TRANSFER
    +139            and self.instance_id is not None  # noqa: W503
    +140        )
    +141
    +142    async def fetch_self(self) -> entity.InventoryEntity:
    +143        """Fetch this profile item.
    +144
    +145        Returns
    +146        -------
    +147        `aiobungie.crates.InventoryEntity`
    +148            An inventory item definition entity.
    +149        """
    +150        return await self.net.request.fetch_inventory_item(self.hash)
    +151
    +152    def __int__(self) -> int:
    +153        return self.hash
     
    @@ -19439,7 +18443,7 @@
    Returns
    - ProfileItemImpl( *, net: aiobungie.traits.Netrunner, hash: int, quantity: int, bind_status: aiobungie.internal.enums.ItemBindStatus, location: aiobungie.internal.enums.ItemLocation, bucket: int, transfer_status: Union[int, aiobungie.internal.enums.TransferStatus], lockable: bool, state: aiobungie.internal.enums.ItemState, dismantel_permissions: int, is_wrapper: bool, instance_id: Optional[int], ornament_id: Optional[int], version_number: Optional[int]) + ProfileItemImpl( *, net: aiobungie.traits.Netrunner, hash: int, quantity: int, bind_status: aiobungie.internal.enums.ItemBindStatus, location: aiobungie.internal.enums.ItemLocation, bucket: int, transfer_status: aiobungie.internal.enums.TransferStatus, lockable: bool, state: aiobungie.internal.enums.ItemState, dismantel_permissions: int, is_wrapper: bool, instance_id: Optional[int], ornament_id: Optional[int], version_number: Optional[int]) @@ -19548,7 +18552,7 @@
    Returns
    - transfer_status: Union[int, aiobungie.internal.enums.TransferStatus] + transfer_status: aiobungie.internal.enums.TransferStatus
    @@ -19674,15 +18678,15 @@
    Returns
    -
    143    async def fetch_self(self) -> entity.InventoryEntity:
    -144        """Fetch this profile item.
    -145
    -146        Returns
    -147        -------
    -148        `aiobungie.crates.InventoryEntity`
    -149            An inventory item definition entity.
    -150        """
    -151        return await self.net.request.fetch_inventory_item(self.hash)
    +            
    142    async def fetch_self(self) -> entity.InventoryEntity:
    +143        """Fetch this profile item.
    +144
    +145        Returns
    +146        -------
    +147        `aiobungie.crates.InventoryEntity`
    +148            An inventory item definition entity.
    +149        """
    +150        return await self.net.request.fetch_inventory_item(self.hash)
     
    @@ -20016,45 +19020,45 @@
    Inherited Members
    -
     82@attrs.mutable(kw_only=True)
    - 83class Objective:
    - 84    """Represents a Destiny 2 record objective."""
    - 85
    - 86    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    - 87
    - 88    hash: int
    - 89    """The objective hash."""
    - 90
    - 91    visible: bool
    - 92    """Whether the objective is visible or not."""
    - 93
    - 94    complete: bool
    - 95    """Whether the objective is completed or not."""
    - 96
    - 97    completion_value: int
    - 98    """An integer represents the objective completion value."""
    - 99
    -100    progress: typing.Optional[int]
    -101    """If progress has been made, and the progress can be measured numerically,
    -102    this will be the value of that progress."""
    -103
    -104    destination_hash: typing.Optional[int]
    -105    """The hash of the Destiny 2 objective destination. If it has one."""
    -106
    -107    activity_hash: typing.Optional[int]
    -108    """If the Objective has an Activity associated with it,
    -109    this is the unique identifier of the Activity being referred to.
    -110    """
    -111
    -112    async def fetch_self(self) -> entity.ObjectiveEntity:
    -113        """Perform an HTTP request fetching this objective entity definition.
    -114
    -115        Returns
    -116        -------
    -117        `aiobungie.crates.ObjectiveEntity`
    -118            An objective entity definition.
    -119        """
    -120        return await self.net.request.fetch_objective_entity(self.hash)
    +            
     81@attrs.mutable(kw_only=True)
    + 82class Objective:
    + 83    """Represents a Destiny 2 record objective."""
    + 84
    + 85    net: traits.Netrunner = attrs.field(repr=False, hash=False, eq=False)
    + 86
    + 87    hash: int
    + 88    """The objective hash."""
    + 89
    + 90    visible: bool
    + 91    """Whether the objective is visible or not."""
    + 92
    + 93    complete: bool
    + 94    """Whether the objective is completed or not."""
    + 95
    + 96    completion_value: int
    + 97    """An integer represents the objective completion value."""
    + 98
    + 99    progress: typing.Optional[int]
    +100    """If progress has been made, and the progress can be measured numerically,
    +101    this will be the value of that progress."""
    +102
    +103    destination_hash: typing.Optional[int]
    +104    """The hash of the Destiny 2 objective destination. If it has one."""
    +105
    +106    activity_hash: typing.Optional[int]
    +107    """If the Objective has an Activity associated with it,
    +108    this is the unique identifier of the Activity being referred to.
    +109    """
    +110
    +111    async def fetch_self(self) -> entity.ObjectiveEntity:
    +112        """Perform an HTTP request fetching this objective entity definition.
    +113
    +114        Returns
    +115        -------
    +116        `aiobungie.crates.ObjectiveEntity`
    +117            An objective entity definition.
    +118        """
    +119        return await self.net.request.fetch_objective_entity(self.hash)
     
    @@ -20088,17 +19092,6 @@
    Inherited Members
    -
    -
    - - - - -
    @@ -20204,15 +19197,15 @@
    Inherited Members
    -
    112    async def fetch_self(self) -> entity.ObjectiveEntity:
    -113        """Perform an HTTP request fetching this objective entity definition.
    -114
    -115        Returns
    -116        -------
    -117        `aiobungie.crates.ObjectiveEntity`
    -118            An objective entity definition.
    -119        """
    -120        return await self.net.request.fetch_objective_entity(self.hash)
    +            
    111    async def fetch_self(self) -> entity.ObjectiveEntity:
    +112        """Perform an HTTP request fetching this objective entity definition.
    +113
    +114        Returns
    +115        -------
    +116        `aiobungie.crates.ObjectiveEntity`
    +117            An objective entity definition.
    +118        """
    +119        return await self.net.request.fetch_objective_entity(self.hash)
     
    @@ -20240,42 +19233,42 @@
    Returns
    -
    140@attrs.define(kw_only=True)
    -141class Record:
    -142    """Represents a Bungie profile records/triumphs component."""
    -143
    -144    scores: typing.Optional[RecordScores]
    -145    """Information about the global records score."""
    -146
    -147    categories_node_hash: undefined.UndefinedOr[int]
    -148    """ The hash for the root presentation node definition of Triumph categories.
    -149
    -150    This will be `UNDEFINED` if not found.
    -151    """
    -152
    -153    seals_node_hash: undefined.UndefinedOr[int]
    -154    """The hash for the root presentation node definition of Triumph Seals.
    -155
    -156    This will be `UNDEFINED` if not found.
    -157    """
    -158
    -159    state: typedefs.IntAnd[RecordState]
    -160    """Record's state. This will be an int if the state is a sum of multiple states."""
    -161
    -162    objectives: typing.Optional[list[Objective]]
    -163    """A list of the record objectives. The objectives are optional and may be `None` if not found."""
    -164
    -165    interval_objectives: typing.Optional[list[Objective]]
    -166    """A list of the interval record objectives. The objectives are optional and may be `None` if not found."""
    -167
    -168    redeemed_count: int
    -169    """The number of times this record has been redeemed."""
    -170
    -171    completion_times: typing.Optional[int]
    -172    """An optional number of time this record has been completed, `None` if not found."""
    -173
    -174    reward_visibility: typing.Optional[list[bool]]
    -175    """An optional list of bool for the record reward visibility."""
    +            
    139@attrs.define(kw_only=True)
    +140class Record:
    +141    """Represents a Bungie profile records/triumphs component."""
    +142
    +143    scores: typing.Optional[RecordScores]
    +144    """Information about the global records score."""
    +145
    +146    categories_node_hash: undefined.UndefinedOr[int]
    +147    """ The hash for the root presentation node definition of Triumph categories.
    +148
    +149    This will be `UNDEFINED` if not found.
    +150    """
    +151
    +152    seals_node_hash: undefined.UndefinedOr[int]
    +153    """The hash for the root presentation node definition of Triumph Seals.
    +154
    +155    This will be `UNDEFINED` if not found.
    +156    """
    +157
    +158    state: RecordState
    +159    """Record's state. This will be an int if the state is a sum of multiple states."""
    +160
    +161    objectives: typing.Optional[list[Objective]]
    +162    """A list of the record objectives. The objectives are optional and may be `None` if not found."""
    +163
    +164    interval_objectives: typing.Optional[list[Objective]]
    +165    """A list of the interval record objectives. The objectives are optional and may be `None` if not found."""
    +166
    +167    redeemed_count: int
    +168    """The number of times this record has been redeemed."""
    +169
    +170    completion_times: typing.Optional[int]
    +171    """An optional number of time this record has been completed, `None` if not found."""
    +172
    +173    reward_visibility: typing.Optional[list[bool]]
    +174    """An optional list of bool for the record reward visibility."""
     
    @@ -20287,7 +19280,7 @@
    Returns
    - Record( *, scores: Optional[aiobungie.crates.RecordScores], categories_node_hash: Union[aiobungie.undefined.UndefinedType, int], seals_node_hash: Union[aiobungie.undefined.UndefinedType, int], state: Union[int, aiobungie.crates.records.RecordState], objectives: Optional[list[aiobungie.crates.Objective]], interval_objectives: Optional[list[aiobungie.crates.Objective]], redeemed_count: int, completion_times: Optional[int], reward_visibility: Optional[list[bool]]) + Record( *, scores: Optional[aiobungie.crates.RecordScores], categories_node_hash: Union[aiobungie.undefined.UndefinedType, int], seals_node_hash: Union[aiobungie.undefined.UndefinedType, int], state: aiobungie.crates.records.RecordState, objectives: Optional[list[aiobungie.crates.Objective]], interval_objectives: Optional[list[aiobungie.crates.Objective]], redeemed_count: int, completion_times: Optional[int], reward_visibility: Optional[list[bool]]) @@ -20356,7 +19349,7 @@
    Returns
    - state: Union[int, aiobungie.crates.records.RecordState] + state: aiobungie.crates.records.RecordState
    @@ -20445,15 +19438,15 @@
    Returns
    -
    178@attrs.define(kw_only=True)
    -179class CharacterRecord(Record):
    -180    """Represents a character focused records component.
    -181
    -182    This derives from `Record` but returns a character focused's records.
    -183    """
    -184
    -185    record_hashes: list[int]
    -186    """A list of int of the featured record hashes."""
    +            
    177@attrs.define(kw_only=True)
    +178class CharacterRecord(Record):
    +179    """Represents a character focused records component.
    +180
    +181    This derives from `Record` but returns a character focused's records.
    +182    """
    +183
    +184    record_hashes: list[int]
    +185    """A list of int of the featured record hashes."""
     
    @@ -20467,7 +19460,7 @@
    Returns
    - CharacterRecord( *, scores: Optional[aiobungie.crates.RecordScores], categories_node_hash: Union[aiobungie.undefined.UndefinedType, int], seals_node_hash: Union[aiobungie.undefined.UndefinedType, int], state: Union[int, aiobungie.crates.records.RecordState], objectives: Optional[list[aiobungie.crates.Objective]], interval_objectives: Optional[list[aiobungie.crates.Objective]], redeemed_count: int, completion_times: Optional[int], reward_visibility: Optional[list[bool]], record_hashes: list[int]) + CharacterRecord( *, scores: Optional[aiobungie.crates.RecordScores], categories_node_hash: Union[aiobungie.undefined.UndefinedType, int], seals_node_hash: Union[aiobungie.undefined.UndefinedType, int], state: aiobungie.crates.records.RecordState, objectives: Optional[list[aiobungie.crates.Objective]], interval_objectives: Optional[list[aiobungie.crates.Objective]], redeemed_count: int, completion_times: Optional[int], reward_visibility: Optional[list[bool]], record_hashes: list[int]) @@ -20535,21 +19528,21 @@
    Inherited Members
    -
    123@attrs.mutable(kw_only=True)
    -124class RecordScores:
    -125    """Represents the records scores.
    -126
    -127    This includes active, lifetime and legacy scores.
    -128    """
    -129
    -130    current_score: int
    -131    """The active triumphs score."""
    -132
    -133    legacy_score: int
    -134    """The legacy triumphs score."""
    -135
    -136    lifetime_score: int
    -137    """The lifetime triumphs score. This includes both legacy and current scores."""
    +            
    122@attrs.mutable(kw_only=True)
    +123class RecordScores:
    +124    """Represents the records scores.
    +125
    +126    This includes active, lifetime and legacy scores.
    +127    """
    +128
    +129    current_score: int
    +130    """The active triumphs score."""
    +131
    +132    legacy_score: int
    +133    """The legacy triumphs score."""
    +134
    +135    lifetime_score: int
    +136    """The lifetime triumphs score. This includes both legacy and current scores."""
     
    @@ -20633,23 +19626,23 @@
    Inherited Members
    -
    63@attrs.define(kw_only=True)
    -64class Node:
    -65    """Represent a Destiny 2 presentation node."""
    -66
    -67    state: int
    -68    """The state of this node."""
    -69
    -70    objective: typing.Optional[Objective]
    -71
    -72    progress_value: int
    -73    """How much of the presentation node is considered to be completed so far by the given character/profile."""
    -74
    -75    completion_value: int
    -76    """The value at which the presenation node is considered to be completed."""
    -77
    -78    record_category_score: typing.Optional[int]
    -79    """If available, this is the current score for the record category that this node represents."""
    +            
    62@attrs.define(kw_only=True)
    +63class Node:
    +64    """Represent a Destiny 2 presentation node."""
    +65
    +66    state: int
    +67    """The state of this node."""
    +68
    +69    objective: typing.Optional[Objective]
    +70
    +71    progress_value: int
    +72    """How much of the presentation node is considered to be completed so far by the given character/profile."""
    +73
    +74    completion_value: int
    +75    """The value at which the presenation node is considered to be completed."""
    +76
    +77    record_category_score: typing.Optional[int]
    +78    """If available, this is the current score for the record category that this node represents."""
     
    @@ -20693,17 +19686,6 @@
    Inherited Members
    -
    -
    -
    - objective: Optional[aiobungie.crates.Objective] - - -
    - - - -
    @@ -20938,50 +19920,6 @@
    Inherited Members
    -
    -
    -
    - hash: int - - -
    - - - - -
    -
    -
    - is_unlocked: bool - - -
    - - - - -
    -
    -
    - points_to_unlock: int - - -
    - - - - -
    -
    -
    - items: collections.abc.Sequence[aiobungie.crates.ArtifactTierItem] - - -
    - - - -
    @@ -21027,28 +19965,6 @@
    Inherited Members
    -
    -
    -
    - hash: int - - -
    - - - - -
    -
    -
    - is_active: bool - - -
    - - - -
    @@ -21103,50 +20019,6 @@
    Inherited Members
    -
    -
    -
    - hash: int - - -
    - - - - -
    -
    -
    - points_used: int - - -
    - - - - -
    -
    -
    - reset_count: int - - -
    - - - - -
    -
    -
    - tiers: collections.abc.Sequence[aiobungie.crates.ArtifactTier] - - -
    - - - -
    @@ -22448,7 +21320,7 @@
    Inherited Members
    358 Those credentials should be the linked profiles such as Twitch, Steam, Blizzard, etc. 359 """ 360 -361 type: typedefs.IntAnd[enums.CredentialType] +361 type: enums.CredentialType 362 """The credential type.""" 363 364 display_name: str @@ -22478,7 +21350,7 @@
    Inherited Members
    - UserCredentials( *, type: Union[int, aiobungie.internal.enums.CredentialType], display_name: str, is_public: bool, self_as_string: Union[aiobungie.undefined.UndefinedType, str]) + UserCredentials( *, type: aiobungie.internal.enums.CredentialType, display_name: str, is_public: bool, self_as_string: Union[aiobungie.undefined.UndefinedType, str]) @@ -22499,7 +21371,7 @@
    Inherited Members
    @@ -23022,17 +21894,6 @@
    Inherited Members
    -
    -
    -
    - energy: Optional[aiobungie.crates.ItemEnergy] - - -
    - - - -
    @@ -23338,17 +22199,6 @@
    Inherited Members
    - -
    -
    - insert_fail_indexes: Optional[list[int]] - - -
    - - - -
    @@ -23767,7 +22617,11 @@
    Inherited Members
    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/error.html b/docs/aiobungie/error.html index 7650d74b..b3ac2148 100644 --- a/docs/aiobungie/error.html +++ b/docs/aiobungie/error.html @@ -3,7 +3,7 @@ - + aiobungie.error API documentation @@ -232,9 +232,9 @@

    aiobungie Exceptions.

    - + - +
      1# MIT License
       2#
    @@ -680,7 +680,6 @@ 
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -770,7 +769,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -992,7 +990,6 @@

    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -1128,7 +1125,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -1218,7 +1214,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -1308,7 +1303,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -1382,7 +1376,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -1529,7 +1522,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -1603,7 +1595,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -1690,7 +1681,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -1815,7 +1805,6 @@
    Inherited Members
    builtins.BaseException
    with_traceback
    -
    args
    @@ -2124,7 +2113,11 @@
    Inherited Members
    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/interfaces.html b/docs/aiobungie/interfaces.html index dfa238a8..31d1cced 100644 --- a/docs/aiobungie/interfaces.html +++ b/docs/aiobungie/interfaces.html @@ -3,7 +3,7 @@ - + aiobungie.interfaces API documentation @@ -586,9 +586,9 @@

    Aiobungie Interfaces provides abstracted objects for implementations.

    - + - +
     1# MIT License
      2#
    @@ -3548,7 +3548,7 @@ 
    Returns

    Gets any hard linked membership given a credential.

    -

    Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now. +

    Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now. Cross Save aware.

    Parameters
    @@ -4379,7 +4379,7 @@
    Other Parameters
    Filter apply to list of joined groups. This Default to 0
  • group_type (aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. -This is always set to aiobungie.GroupType.CLAN and should not be changed.
  • +This is always set to aiobungie.GroupType.CLAN and should not be changed.
    Returns
    @@ -4456,7 +4456,7 @@
    Other Parameters
    Filter apply to list of joined groups. This Default to 0
  • group_type (aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. -This is always set to aiobungie.GroupType.CLAN and should not be changed.
  • +This is always set to aiobungie.GroupType.CLAN and should not be changed.
    Returns
    @@ -4534,7 +4534,7 @@
    Other Parameters
    If provided, Only players matching this name will be returned.
  • type (aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): An optional clan member's membership type. -Default is set to aiobungie.MembershipType.NONE +Default is set to aiobungie.MembershipType.NONE Which returns the first matched clan member by their name.
  • @@ -5228,7 +5228,7 @@
    Other Parameters
    • length (int): An optional ban length.
    • -
    • comment (aiobungie.UndefinedOr[str]): +
    • comment (aiobungie.UndefinedOr[str]): An optional comment to this ban. Default is UNDEFINED
    @@ -5487,7 +5487,7 @@
    Other Parameters
    Default is False for clans, True for groups.
  • join_level (aiobungie.ClanMemberType): Level to join a member at when accepting an invite, application, or joining an open clan. -Default is aiobungie.ClanMemberType.BEGINNER
  • +Default is aiobungie.ClanMemberType.BEGINNER
    @@ -6071,7 +6071,7 @@

    Parameters
    Other Parameters
      -
    • message (aiobungie.UndefinedOr[str]): +
    • message (aiobungie.UndefinedOr[str]): An optional message to send with the request. Default is UNDEFINED.
    @@ -6139,7 +6139,7 @@
    Parameters
    Other Parameters
      -
    • message (aiobungie.UndefinedOr[str]): +
    • message (aiobungie.UndefinedOr[str]): An optional message to send with the request. Default is UNDEFINED.
    @@ -6213,7 +6213,7 @@
    Parameters
    Other parameters
    -

    name: aiobungie.UndefinedOr[str] +

    name: aiobungie.UndefinedOr[str] The chat name. Default to UNDEFINED security: typing.Literal[0, 1] The security level of the chat.

    @@ -6302,7 +6302,7 @@
    Parameters
    Other parameters
    -

    name: aiobungie.UndefinedOr[str] +

    name: aiobungie.UndefinedOr[str] The new chat name. Default to UNDEFINED security: typing.Literal[0, 1] The new security level of the chat.

    @@ -6573,7 +6573,7 @@
    Other Parameters
    A locale language to filter the used language in that fireteam. Defaults to aiobungie.crates.FireteamLanguage.ALL
  • date_range (aiobungie.typedefs.IntAnd[aiobungie.FireteamDate]): -An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • +An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • page (int): The page number. By default its 0 which returns all available activities.
  • slots_filter (int): @@ -6683,7 +6683,7 @@
    Other Parameters
    A locale language to filter the used language in that fireteam. Defaults to aiobungie.crates.FireteamLanguage.ALL
  • date_range (aiobungie.typedefs.IntAnd[aiobungie.FireteamDate]): -An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • +An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • page (int): The page number. By default its 0 which returns all available activities.
  • public_only (bool): @@ -7202,7 +7202,8 @@
    Parameters
    Example
    -
    plug = (
    +
    +
    plug = (
         aiobungie.PlugSocketBuilder()
         .set_socket_array(0)
         .set_socket_index(0)
    @@ -7210,7 +7211,8 @@ 
    Example
    .collect() ) await insert_socket_plug_free(..., plug=plug) -
    +
    +

    character_id : int The character's id. @@ -7315,7 +7317,8 @@

    Parameters
    Example
    -
    plug = (
    +
    +
    plug = (
         aiobungie.PlugSocketBuilder()
         .set_socket_array(0)
         .set_socket_index(0)
    @@ -7323,7 +7326,8 @@ 
    Example
    .collect() ) await insert_socket_plug_free(..., plug=plug) -
    +
    +

    character_id : int The character's id. @@ -8443,13 +8447,15 @@

    Other Parameters
    Example
    -
    import datetime
    +
    +
    import datetime
     
     # Fetch data from 2021 Dec 10th to 2021 Dec 20th
     await fetch_application_api_usage(
         start=datetime.datetime(2021, 12, 10), end=datetime.datetime(2021, 12, 20)
     )
    -
    +
    +
    Returns
    @@ -9532,7 +9538,7 @@
    Inherited Members
    253 @abc.abstractmethod 254 def deserialize_clan_members( 255 self, data: typedefs.JSONObject, / - 256 ) -> iterators.FlatIterator[clans.ClanMember]: + 256 ) -> iterators.Iterator[clans.ClanMember]: 257 """Deserialize a JSON payload of a clan members information. 258 259 Parameters @@ -9542,7 +9548,7 @@
    Inherited Members
    263 264 Returns 265 ------- - 266 `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]` + 266 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 267 An iterator of clan members of the deserialized payload. 268 """ 269 @@ -9959,7 +9965,7 @@
    Inherited Members
    680 @abc.abstractmethod 681 def deserialize_inventory_results( 682 self, payload: typedefs.JSONObject - 683 ) -> iterators.FlatIterator[entity.SearchableEntity]: + 683 ) -> iterators.Iterator[entity.SearchableEntity]: 684 """Deserialize results of searched Destiny2 entities. 685 686 Parameters @@ -9969,7 +9975,7 @@
    Inherited Members
    690 691 Returns 692 ------- - 693 `aiobungie.iterators.FlatIterator[aiobungie.crates.SearchableEntity]` + 693 `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]` 694 An iterator over the found searched entities. 695 """ 696 @@ -10012,7 +10018,7 @@
    Inherited Members
    733 @abc.abstractmethod 734 def deserialize_activities( 735 self, payload: typedefs.JSONObject, / - 736 ) -> iterators.FlatIterator[activity.Activity]: + 736 ) -> iterators.Iterator[activity.Activity]: 737 """Deserialize a JSON payload of an array of activity history information. 738 739 Parameters @@ -10022,7 +10028,7 @@
    Inherited Members
    743 744 Returns 745 ------- - 746 `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]` + 746 `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` 747 Am iterator over activity objects of the deserialized payload. 748 """ 749 @@ -10099,7 +10105,7 @@
    Inherited Members
    820 @abc.abstractmethod 821 def deserialize_aggregated_activities( 822 self, payload: typedefs.JSONObject - 823 ) -> iterators.FlatIterator[activity.AggregatedActivity]: + 823 ) -> iterators.Iterator[activity.AggregatedActivity]: 824 """Deserialize a JSON payload of an array of aggregated activities. 825 826 Parameters @@ -10109,7 +10115,7 @@
    Inherited Members
    830 831 Returns 832 ------- - 833 `aiobungie.iterators.FlatIterator[aiobungie.crates.AggregatedActivity]` + 833 `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]` 834 An iterator over aggregated activities objects. 835 """ 836 @@ -10942,7 +10948,7 @@
    Returns
    @abc.abstractmethod
    def - deserialize_clan_members( self, data: dict[str, typing.Any], /) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.clans.ClanMember]: + deserialize_clan_members( self, data: dict[str, typing.Any], /) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.clans.ClanMember]: @@ -10951,7 +10957,7 @@
    Returns
    253    @abc.abstractmethod
     254    def deserialize_clan_members(
     255        self, data: typedefs.JSONObject, /
    -256    ) -> iterators.FlatIterator[clans.ClanMember]:
    +256    ) -> iterators.Iterator[clans.ClanMember]:
     257        """Deserialize a JSON payload of a clan members information.
     258
     259        Parameters
    @@ -10961,7 +10967,7 @@ 
    Returns
    263 264 Returns 265 ------- -266 `aiobungie.iterators.FlatIterator[aiobungie.crates.ClanMember]` +266 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 267 An iterator of clan members of the deserialized payload. 268 """
    @@ -10979,7 +10985,7 @@
    Parameters
    Returns
    @@ -12185,7 +12191,7 @@
    Returns
    @abc.abstractmethod
    def - deserialize_inventory_results( self, payload: dict[str, typing.Any]) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.entity.SearchableEntity]: + deserialize_inventory_results( self, payload: dict[str, typing.Any]) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.entity.SearchableEntity]: @@ -12194,7 +12200,7 @@
    Returns
    680    @abc.abstractmethod
     681    def deserialize_inventory_results(
     682        self, payload: typedefs.JSONObject
    -683    ) -> iterators.FlatIterator[entity.SearchableEntity]:
    +683    ) -> iterators.Iterator[entity.SearchableEntity]:
     684        """Deserialize results of searched Destiny2 entities.
     685
     686        Parameters
    @@ -12204,7 +12210,7 @@ 
    Returns
    690 691 Returns 692 ------- -693 `aiobungie.iterators.FlatIterator[aiobungie.crates.SearchableEntity]` +693 `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]` 694 An iterator over the found searched entities. 695 """
    @@ -12222,7 +12228,7 @@
    Parameters
    Returns
    @@ -12332,7 +12338,7 @@
    Returns
    @abc.abstractmethod
    def - deserialize_activities( self, payload: dict[str, typing.Any], /) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.activity.Activity]: + deserialize_activities( self, payload: dict[str, typing.Any], /) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.activity.Activity]: @@ -12341,7 +12347,7 @@
    Returns
    733    @abc.abstractmethod
     734    def deserialize_activities(
     735        self, payload: typedefs.JSONObject, /
    -736    ) -> iterators.FlatIterator[activity.Activity]:
    +736    ) -> iterators.Iterator[activity.Activity]:
     737        """Deserialize a JSON payload of an array of activity history information.
     738
     739        Parameters
    @@ -12351,7 +12357,7 @@ 
    Returns
    743 744 Returns 745 ------- -746 `aiobungie.iterators.FlatIterator[aiobungie.crates.Activity]` +746 `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` 747 Am iterator over activity objects of the deserialized payload. 748 """
    @@ -12369,7 +12375,7 @@
    Parameters
    Returns
    @@ -12581,7 +12587,7 @@
    Returns
    @abc.abstractmethod
    def - deserialize_aggregated_activities( self, payload: dict[str, typing.Any]) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.activity.AggregatedActivity]: + deserialize_aggregated_activities( self, payload: dict[str, typing.Any]) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.activity.AggregatedActivity]: @@ -12590,7 +12596,7 @@
    Returns
    820    @abc.abstractmethod
     821    def deserialize_aggregated_activities(
     822        self, payload: typedefs.JSONObject
    -823    ) -> iterators.FlatIterator[activity.AggregatedActivity]:
    +823    ) -> iterators.Iterator[activity.AggregatedActivity]:
     824        """Deserialize a JSON payload of an array of aggregated activities.
     825
     826        Parameters
    @@ -12600,7 +12606,7 @@ 
    Returns
    830 831 Returns 832 ------- -833 `aiobungie.iterators.FlatIterator[aiobungie.crates.AggregatedActivity]` +833 `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]` 834 An iterator over aggregated activities objects. 835 """
    @@ -12618,7 +12624,7 @@
    Parameters
    Returns
    @@ -13516,7 +13522,11 @@
    Returns
    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/internal.html b/docs/aiobungie/internal.html index 4ff02b94..6d1f428a 100644 --- a/docs/aiobungie/internal.html +++ b/docs/aiobungie/internal.html @@ -3,7 +3,7 @@ - + aiobungie.internal API documentation @@ -54,9 +54,9 @@

    Package contains internal helpers for aiobungie.

    - + - +
     1# MIT License
      2#
    @@ -190,7 +190,11 @@ 

    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/internal/_backoff.html b/docs/aiobungie/internal/_backoff.html index 23683d04..744a84af 100644 --- a/docs/aiobungie/internal/_backoff.html +++ b/docs/aiobungie/internal/_backoff.html @@ -3,7 +3,7 @@ - + aiobungie.internal._backoff API documentation @@ -73,9 +73,9 @@

    Basic lazy ratelimit systems for asyncio.

    - + - +
      1# -*- coding: utf-8 -*-
       2# cython: language_level=3
    @@ -602,7 +602,11 @@ 
    Raises
    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/internal/assets.html b/docs/aiobungie/internal/assets.html index ae3fd3af..f7c1348d 100644 --- a/docs/aiobungie/internal/assets.html +++ b/docs/aiobungie/internal/assets.html @@ -3,7 +3,7 @@ - + aiobungie.internal.assets API documentation @@ -36,9 +36,6 @@

    API Documentation

  • Image
  • -
  • - is_missing -
  • url
  • @@ -63,21 +60,6 @@

    API Documentation

  • MimeType
  • @@ -100,9 +82,9 @@

    aiobungie assets module for API Image hash and path linking.

    - + - +
      1# MIT License
       2#
    @@ -530,7 +512,8 @@ 

    Example
    -
    from aiobungie import Image
    +
    +
    from aiobungie import Image
     img = Image("img/destiny_content/pgcr/raid_eclipse.jpg")
     print(img)
     # https://www.bungie.net/img/destiny_content/pgcr/raid_eclipse.jpg
    @@ -542,7 +525,8 @@ 
    Example
    # Save the image to a file. await img.save("file_name", "/my/path/to/save/to", "jpeg") -
    +
    +
    Parameters
    @@ -570,17 +554,6 @@
    Parameters
    -
    -
    -
    - is_missing: bool - - -
    - - - -
    @@ -879,61 +852,6 @@
    Returns
    -
    -
    - JPEG = <MimeType.JPEG: jpeg> - - -
    - - - - -
    -
    -
    - PNG = <MimeType.PNG: png> - - -
    - - - - -
    -
    -
    - WEBP = <MimeType.WEBP: webp> - - -
    - - - - -
    -
    -
    - JPG = <MimeType.JPG: jpg> - - -
    - - - - -
    -
    -
    - GIF = <MimeType.GIF: gif> - - -
    - - - - -
    Inherited Members
    @@ -1098,7 +1016,11 @@
    Inherited Members
    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/internal/enums.html b/docs/aiobungie/internal/enums.html index ddb65707..6334b066 100644 --- a/docs/aiobungie/internal/enums.html +++ b/docs/aiobungie/internal/enums.html @@ -3,7 +3,7 @@ - + aiobungie.internal.enums API documentation @@ -57,405 +57,51 @@

    API Documentation

  • GameMode
  • MembershipType
  • Class
  • MilestoneType
  • Race
  • Vendor
  • @@ -516,15 +162,6 @@

    API Documentation

  • Gender
  • @@ -532,136 +169,31 @@

    API Documentation

    ComponentType + +

  • +
  • + Planet + - -
  • -
  • - Planet -
      -
    • - UNKNOWN -
    • -
    • - EARTH + EARTH
    • DREAMING_CITY @@ -693,387 +225,93 @@

      API Documentation

    • Stat
    • WeaponType
    • DamageType
    • ItemType
    • Place
    • ItemTier
    • AmmoType
    • GroupType
    • CredentialType
    • Presence
    • Relationship
    • ClanMemberType
    • MembershipOption
    • ItemBindStatus
    • ItemLocation
    • @@ -1098,18 +336,6 @@

      API Documentation

    • ItemState
        -
      • - NONE -
      • -
      • - LOCKED -
      • -
      • - TRACKED -
      • -
      • - MASTERWORKED -
      • CRAFTED
      • @@ -1122,36 +348,12 @@

        API Documentation

      • PrivacySetting
      • ClosedReasons
          -
        • - NONE -
        • -
        • - MATCHMAKING -
        • -
        • - LOADING -
        • SOLO
        • @@ -1170,111 +372,12 @@

          API Documentation

        • ItemSubType
        • TierType
        • @@ -1297,9 +400,9 @@

          Bungie enums implementation used within aiobungie.

          - + - +
            1# MIT License
             2#
          @@ -1370,765 +473,762 @@ 

          67 68_ITERABLE = (set, list, tuple) 69 - 70if typing.TYPE_CHECKING: - 71 _T = typing.TypeVar("_T") - 72 - 73# TODO = Use Flags for bitwised fields? - 74 - 75 - 76class Enum(__enum.Enum): - 77 """Builtin Python enum with extra handlings.""" - 78 - 79 @property - 80 def name(self) -> str: # type: ignore[override] - 81 return self._name_ - 82 - 83 @property - 84 def value(self) -> typing.Any: # type: ignore[override] - 85 return self._value_ - 86 - 87 def __str__(self) -> str: - 88 return self._name_ - 89 - 90 def __repr__(self) -> str: - 91 return f"<{type(self).__name__}.{self._name_}: {self._value_!s}>" - 92 - 93 def __int__(self) -> int: - 94 if isinstance(self.value, _ITERABLE): - 95 raise TypeError( - 96 f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.", - 97 ) - 98 return int(self.value) - 99 -100 -101class Flag(__enum.Flag): -102 """Builtin Python enum flag with extra handlings.""" -103 -104 # Needs to type this here for mypy -105 _value_: int + 70 + 71class Enum(__enum.Enum): + 72 """Builtin Python enum with extra handlings.""" + 73 + 74 @property + 75 def name(self) -> str: # type: ignore[override] + 76 return self._name_ + 77 + 78 @property + 79 def value(self) -> typing.Any: # type: ignore[override] + 80 return self._value_ + 81 + 82 def __str__(self) -> str: + 83 return self._name_ + 84 + 85 def __repr__(self) -> str: + 86 return f"<{type(self).__name__}.{self._name_}: {self._value_!s}>" + 87 + 88 def __int__(self) -> int: + 89 if isinstance(self.value, _ITERABLE): + 90 raise TypeError( + 91 f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.", + 92 ) + 93 return int(self.value) + 94 + 95 + 96class Flag(__enum.Flag): + 97 """Builtin Python enum flag with extra handlings.""" + 98 + 99 # Needs to type this here for mypy +100 _value_: int +101 +102 @property +103 def name(self) -> str: # type: ignore[override] +104 if self._name_ is None: +105 self._name_ = f"UNKNOWN {self._value_}" 106 -107 @property -108 def name(self) -> str: # type: ignore[override] -109 if self._name_ is None: -110 self._name_ = f"UNKNOWN {self._value_}" -111 -112 return self._name_ -113 -114 @property -115 def value(self) -> int: # type: ignore[override] -116 return self._value_ -117 -118 def __str__(self) -> str: -119 return self.name -120 -121 def __repr__(self) -> str: -122 return f"<{type(self).__name__}.{self.name}: {self._value_!s}>" -123 -124 def __int__(self) -> int: -125 if isinstance(self.value, _ITERABLE): -126 raise TypeError( -127 f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.", -128 ) -129 return int(self.value) -130 -131 def __or__(self, other: typing.Union[Flag, int]) -> Flag: -132 return self.__class__(self._value_ | int(other)) -133 -134 def __xor__(self, other: typing.Union[Flag, int]) -> Flag: -135 return self.__class__(self._value_ ^ int(other)) -136 -137 def __and__(self, other: typing.Union[Flag, int]) -> Flag: -138 return self.__class__(other & int(other)) -139 -140 def __invert__(self) -> Flag: -141 return self.__class__(~self._value_) -142 -143 def __contains__(self, other: typing.Union[Flag, int]) -> bool: -144 return self.value & int(other) == int(other) +107 return self._name_ +108 +109 @property +110 def value(self) -> int: # type: ignore[override] +111 return self._value_ +112 +113 def __str__(self) -> str: +114 return self.name +115 +116 def __repr__(self) -> str: +117 return f"<{type(self).__name__}.{self.name}: {self._value_!s}>" +118 +119 def __int__(self) -> int: +120 if isinstance(self.value, _ITERABLE): +121 raise TypeError( +122 f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.", +123 ) +124 return int(self.value) +125 +126 def __or__(self, other: typing.Union[Flag, int]) -> Flag: +127 return self.__class__(self._value_ | int(other)) +128 +129 def __xor__(self, other: typing.Union[Flag, int]) -> Flag: +130 return self.__class__(self._value_ ^ int(other)) +131 +132 def __and__(self, other: typing.Union[Flag, int]) -> Flag: +133 return self.__class__(other & int(other)) +134 +135 def __invert__(self) -> Flag: +136 return self.__class__(~self._value_) +137 +138 def __contains__(self, other: typing.Union[Flag, int]) -> bool: +139 return self.value & int(other) == int(other) +140 +141 +142@typing.final +143class Raid(int, Enum): +144 """An Enum for all available raids in Destiny 2.""" 145 -146 -147@typing.final -148class Raid(int, Enum): -149 """An Enum for all available raids in Destiny 2.""" -150 -151 DSC = 910380154 -152 """Deep Stone Crypt""" -153 -154 LW = 2122313384 -155 """Last Wish""" -156 -157 VOG = 3881495763 -158 """Normal Valut of Glass""" -159 -160 GOS = 3458480158 -161 """Garden Of Salvation""" +146 DSC = 910380154 +147 """Deep Stone Crypt""" +148 +149 LW = 2122313384 +150 """Last Wish""" +151 +152 VOG = 3881495763 +153 """Normal Valut of Glass""" +154 +155 GOS = 3458480158 +156 """Garden Of Salvation""" +157 +158 +159@typing.final +160class Dungeon(int, Enum): +161 """An Enum for all available Dungeon/Like missions in Destiny 2.""" 162 -163 -164@typing.final -165class Dungeon(int, Enum): -166 """An Enum for all available Dungeon/Like missions in Destiny 2.""" -167 -168 NORMAL_PRESAGE = 2124066889 -169 """Normal Presage""" -170 -171 MASTER_PRESAGE = 4212753278 -172 """Master Presage""" -173 -174 HARBINGER = 1738383283 -175 """Harbinger""" -176 -177 PROPHECY = 4148187374 -178 """Prophecy""" -179 -180 MASTER_POH = 785700673 -181 """Master Pit of Heresy?""" -182 -183 LEGEND_POH = 785700678 -184 """Legend Pit of Heresy?""" -185 -186 POH = 1375089621 -187 """Normal Pit of Heresy.""" -188 -189 SHATTERED = 2032534090 -190 """Shattered Throne""" -191 -192 GOA_LEGEND = 4078656646 -193 """Grasp of Avarice legend.""" -194 -195 GOA_MASTER = 3774021532 -196 """Grasp of Avarice master.""" +163 NORMAL_PRESAGE = 2124066889 +164 """Normal Presage""" +165 +166 MASTER_PRESAGE = 4212753278 +167 """Master Presage""" +168 +169 HARBINGER = 1738383283 +170 """Harbinger""" +171 +172 PROPHECY = 4148187374 +173 """Prophecy""" +174 +175 MASTER_POH = 785700673 +176 """Master Pit of Heresy?""" +177 +178 LEGEND_POH = 785700678 +179 """Legend Pit of Heresy?""" +180 +181 POH = 1375089621 +182 """Normal Pit of Heresy.""" +183 +184 SHATTERED = 2032534090 +185 """Shattered Throne""" +186 +187 GOA_LEGEND = 4078656646 +188 """Grasp of Avarice legend.""" +189 +190 GOA_MASTER = 3774021532 +191 """Grasp of Avarice master.""" +192 +193 +194@typing.final +195class Planet(int, Enum): +196 """An Enum for all available planets in Destiny 2.""" 197 -198 -199@typing.final -200class Planet(int, Enum): -201 """An Enum for all available planets in Destiny 2.""" -202 -203 UNKNOWN = 0 -204 """Unknown space""" -205 -206 EARTH = 3747705955 -207 """Earth""" -208 -209 DREAMING_CITY = 2877881518 -210 """The Dreaming city.""" -211 -212 NESSUS = 3526908984 -213 """Nessus""" -214 -215 MOON = 3325508439 -216 """The Moon""" -217 -218 COSMODROME = 3990611421 -219 """The Cosmodrome""" -220 -221 TANGLED_SHORE = 3821439926 -222 """The Tangled Shore""" -223 -224 VENUS = 3871070152 -225 """Venus""" -226 -227 EAZ = 541863059 # Exclusive event. -228 """European Aerial Zone""" -229 -230 EUROPA = 1729879943 -231 """Europa""" +198 UNKNOWN = 0 +199 """Unknown space""" +200 +201 EARTH = 3747705955 +202 """Earth""" +203 +204 DREAMING_CITY = 2877881518 +205 """The Dreaming city.""" +206 +207 NESSUS = 3526908984 +208 """Nessus""" +209 +210 MOON = 3325508439 +211 """The Moon""" +212 +213 COSMODROME = 3990611421 +214 """The Cosmodrome""" +215 +216 TANGLED_SHORE = 3821439926 +217 """The Tangled Shore""" +218 +219 VENUS = 3871070152 +220 """Venus""" +221 +222 EAZ = 541863059 # Exclusive event. +223 """European Aerial Zone""" +224 +225 EUROPA = 1729879943 +226 """Europa""" +227 +228 +229@typing.final +230class Place(int, Enum): +231 """An Enum for Destiny 2 Places and NOT Planets""" 232 -233 -234@typing.final -235class Place(int, Enum): -236 """An Enum for Destiny 2 Places and NOT Planets""" +233 ORBIT = 2961497387 +234 SOCIAL = 4151112093 +235 LIGHT_HOUSE = 4276116472 +236 EXPLORE = 3497767639 237 -238 ORBIT = 2961497387 -239 SOCIAL = 4151112093 -240 LIGHT_HOUSE = 4276116472 -241 EXPLORE = 3497767639 +238 +239@typing.final +240class Vendor(int, Enum): +241 """An Enum for all available vendors in Destiny 2.""" 242 -243 -244@typing.final -245class Vendor(int, Enum): -246 """An Enum for all available vendors in Destiny 2.""" -247 -248 ZAVALA = 69482069 -249 XUR = 2190858386 -250 BANSHE = 672118013 -251 SPIDER = 863940356 -252 SHAXX = 3603221665 -253 KADI = 529635856 -254 """Postmaster exo.""" -255 YUNA = 1796504621 -256 """Asia servers only.""" -257 EVERVERSE = 3361454721 -258 AMANDA = 460529231 -259 """Amanda holiday""" -260 CROW = 3611983588 -261 HAWTHORNE = 3347378076 -262 ADA1 = 350061650 -263 DRIFTER = 248695599 -264 IKORA = 1976548992 -265 SAINT = 765357505 -266 """Saint-14""" -267 ERIS_MORN = 1616085565 -268 SHAW_HAWN = 1816541247 -269 """COSMODROME Guy""" -270 VARIKS = 2531198101 +243 ZAVALA = 69482069 +244 XUR = 2190858386 +245 BANSHE = 672118013 +246 SPIDER = 863940356 +247 SHAXX = 3603221665 +248 KADI = 529635856 +249 """Postmaster exo.""" +250 YUNA = 1796504621 +251 """Asia servers only.""" +252 EVERVERSE = 3361454721 +253 AMANDA = 460529231 +254 """Amanda holiday""" +255 CROW = 3611983588 +256 HAWTHORNE = 3347378076 +257 ADA1 = 350061650 +258 DRIFTER = 248695599 +259 IKORA = 1976548992 +260 SAINT = 765357505 +261 """Saint-14""" +262 ERIS_MORN = 1616085565 +263 SHAW_HAWN = 1816541247 +264 """COSMODROME Guy""" +265 VARIKS = 2531198101 +266 +267 +268@typing.final +269class GameMode(int, Enum): +270 """An Enum for all available gamemodes in Destiny 2.""" 271 -272 -273@typing.final -274class GameMode(int, Enum): -275 """An Enum for all available gamemodes in Destiny 2.""" -276 -277 NONE = 0 -278 STORY = 2 -279 STRIKE = 3 -280 RAID = 4 -281 ALLPVP = 5 -282 PATROL = 6 -283 ALLPVE = 7 -284 RESERVED9 = 9 -285 CONTROL = 10 -286 RESERVED11 = 11 -287 CLASH = 12 -288 RESERVED13 = 13 -289 CRIMSONDOUBLES = 15 -290 NIGHTFALL = 16 -291 HEROICNIGHTFALL = 17 -292 ALLSTRIKES = 18 -293 IRONBANNER = 19 -294 RESERVED20 = 20 -295 RESERVED21 = 21 -296 RESERVED22 = 22 -297 RESERVED24 = 24 -298 ALLMAYHEM = 25 -299 RESERVED26 = 26 -300 RESERVED27 = 27 -301 RESERVED28 = 28 -302 RESERVED29 = 29 -303 RESERVED30 = 30 -304 SUPREMACY = 31 -305 PRIVATEMATCHESALL = 32 -306 SURVIVAL = 37 -307 COUNTDOWN = 38 -308 TRIALSOFTHENINE = 39 -309 SOCIAL = 40 -310 TRIALSCOUNTDOWN = 41 -311 TRIALSSURVIVAL = 42 -312 IRONBANNERCONTROL = 43 -313 IRONBANNERCLASH = 44 -314 IRONBANNERSUPREMACY = 45 -315 SCOREDNIGHTFALL = 46 -316 SCOREDHEROICNIGHTFALL = 47 -317 RUMBLE = 48 -318 ALLDOUBLES = 49 -319 DOUBLES = 50 -320 PRIVATEMATCHESCLASH = 51 -321 PRIVATEMATCHESCONTROL = 52 -322 PRIVATEMATCHESSUPREMACY = 53 -323 PRIVATEMATCHESCOUNTDOWN = 54 -324 PRIVATEMATCHESSURVIVAL = 55 -325 PRIVATEMATCHESMAYHEM = 56 -326 PRIVATEMATCHESRUMBLE = 57 -327 HEROICADVENTURE = 58 -328 SHOWDOWN = 59 -329 LOCKDOWN = 60 -330 SCORCHED = 61 -331 SCORCHEDTEAM = 62 -332 GAMBIT = 63 -333 ALLPVECOMPETITIVE = 64 -334 BREAKTHROUGH = 65 -335 BLACKARMORYRUN = 66 -336 SALVAGE = 67 -337 IRONBANNERSALVAGE = 68 -338 PVPCOMPETITIVE = 69 -339 PVPQUICKPLAY = 70 -340 CLASHQUICKPLAY = 71 -341 CLASHCOMPETITIVE = 72 -342 CONTROLQUICKPLAY = 73 -343 CONTROLCOMPETITIVE = 74 -344 GAMBITPRIME = 75 -345 RECKONING = 76 -346 MENAGERIE = 77 -347 VEXOFFENSIVE = 78 -348 NIGHTMAREHUNT = 79 -349 ELIMINATION = 80 -350 MOMENTUM = 81 -351 DUNGEON = 82 -352 SUNDIAL = 83 -353 TRIALS_OF_OSIRIS = 84 -354 DARES = 85 -355 OFFENSIVE = 86 -356 LOSTSECTOR = 87 -357 RIFT = 88 -358 ZONECONTROL = 89 -359 IRONBANNERRIFT = 90 +272 NONE = 0 +273 STORY = 2 +274 STRIKE = 3 +275 RAID = 4 +276 ALLPVP = 5 +277 PATROL = 6 +278 ALLPVE = 7 +279 RESERVED9 = 9 +280 CONTROL = 10 +281 RESERVED11 = 11 +282 CLASH = 12 +283 RESERVED13 = 13 +284 CRIMSONDOUBLES = 15 +285 NIGHTFALL = 16 +286 HEROICNIGHTFALL = 17 +287 ALLSTRIKES = 18 +288 IRONBANNER = 19 +289 RESERVED20 = 20 +290 RESERVED21 = 21 +291 RESERVED22 = 22 +292 RESERVED24 = 24 +293 ALLMAYHEM = 25 +294 RESERVED26 = 26 +295 RESERVED27 = 27 +296 RESERVED28 = 28 +297 RESERVED29 = 29 +298 RESERVED30 = 30 +299 SUPREMACY = 31 +300 PRIVATEMATCHESALL = 32 +301 SURVIVAL = 37 +302 COUNTDOWN = 38 +303 TRIALSOFTHENINE = 39 +304 SOCIAL = 40 +305 TRIALSCOUNTDOWN = 41 +306 TRIALSSURVIVAL = 42 +307 IRONBANNERCONTROL = 43 +308 IRONBANNERCLASH = 44 +309 IRONBANNERSUPREMACY = 45 +310 SCOREDNIGHTFALL = 46 +311 SCOREDHEROICNIGHTFALL = 47 +312 RUMBLE = 48 +313 ALLDOUBLES = 49 +314 DOUBLES = 50 +315 PRIVATEMATCHESCLASH = 51 +316 PRIVATEMATCHESCONTROL = 52 +317 PRIVATEMATCHESSUPREMACY = 53 +318 PRIVATEMATCHESCOUNTDOWN = 54 +319 PRIVATEMATCHESSURVIVAL = 55 +320 PRIVATEMATCHESMAYHEM = 56 +321 PRIVATEMATCHESRUMBLE = 57 +322 HEROICADVENTURE = 58 +323 SHOWDOWN = 59 +324 LOCKDOWN = 60 +325 SCORCHED = 61 +326 SCORCHEDTEAM = 62 +327 GAMBIT = 63 +328 ALLPVECOMPETITIVE = 64 +329 BREAKTHROUGH = 65 +330 BLACKARMORYRUN = 66 +331 SALVAGE = 67 +332 IRONBANNERSALVAGE = 68 +333 PVPCOMPETITIVE = 69 +334 PVPQUICKPLAY = 70 +335 CLASHQUICKPLAY = 71 +336 CLASHCOMPETITIVE = 72 +337 CONTROLQUICKPLAY = 73 +338 CONTROLCOMPETITIVE = 74 +339 GAMBITPRIME = 75 +340 RECKONING = 76 +341 MENAGERIE = 77 +342 VEXOFFENSIVE = 78 +343 NIGHTMAREHUNT = 79 +344 ELIMINATION = 80 +345 MOMENTUM = 81 +346 DUNGEON = 82 +347 SUNDIAL = 83 +348 TRIALS_OF_OSIRIS = 84 +349 DARES = 85 +350 OFFENSIVE = 86 +351 LOSTSECTOR = 87 +352 RIFT = 88 +353 ZONECONTROL = 89 +354 IRONBANNERRIFT = 90 +355 +356 +357@typing.final +358class ComponentType(Enum): +359 """An Enum for Destiny 2 profile Components.""" 360 -361 -362@typing.final -363class ComponentType(Enum): -364 """An Enum for Destiny 2 profile Components.""" -365 -366 NONE = 0 -367 -368 PROFILE = 100 -369 PROFILE_INVENTORIES = 102 -370 PROFILE_CURRENCIES = 103 -371 PROFILE_PROGRESSION = 104 -372 ALL_PROFILES = ( -373 PROFILE, -374 PROFILE_INVENTORIES, -375 PROFILE_CURRENCIES, -376 PROFILE_PROGRESSION, -377 ) -378 """All profile components.""" -379 -380 VENDORS = 400 -381 VENDOR_SALES = 402 -382 VENDOR_RECEIPTS = 101 -383 ALL_VENDORS = (VENDORS, VENDOR_RECEIPTS, VENDOR_SALES) -384 """All vendor components.""" -385 -386 # Items -387 ITEM_INSTANCES = 300 -388 ITEM_OBJECTIVES = 301 -389 ITEM_PERKS = 302 -390 ITEM_RENDER_DATA = 303 -391 ITEM_STATS = 304 -392 ITEM_SOCKETS = 305 -393 ITEM_TALENT_GRINDS = 306 -394 ITEM_PLUG_STATES = 308 -395 ITEM_PLUG_OBJECTIVES = 309 -396 ITEM_REUSABLE_PLUGS = 310 -397 -398 ALL_ITEMS = ( -399 ITEM_PLUG_OBJECTIVES, -400 ITEM_PLUG_STATES, -401 ITEM_SOCKETS, -402 ITEM_INSTANCES, -403 ITEM_OBJECTIVES, -404 ITEM_PERKS, -405 ITEM_RENDER_DATA, -406 ITEM_STATS, -407 ITEM_TALENT_GRINDS, -408 ITEM_REUSABLE_PLUGS, -409 ) -410 """All item components.""" -411 -412 PLATFORM_SILVER = 105 -413 KIOSKS = 500 -414 CURRENCY_LOOKUPS = 600 -415 PRESENTATION_NODES = 700 -416 COLLECTIBLES = 800 -417 RECORDS = 900 -418 TRANSITORY = 1000 -419 METRICS = 1100 -420 INVENTORIES = 102 -421 STRING_VARIABLES = 1200 -422 CRAFTABLES = 1300 -423 -424 CHARACTERS = 200 -425 CHARACTER_INVENTORY = 201 -426 CHARECTER_PROGRESSION = 202 -427 CHARACTER_RENDER_DATA = 203 -428 CHARACTER_ACTIVITIES = 204 -429 CHARACTER_EQUIPMENT = 205 -430 -431 ALL_CHARACTERS = ( -432 CHARACTERS, -433 CHARACTER_INVENTORY, -434 CHARECTER_PROGRESSION, -435 CHARACTER_RENDER_DATA, -436 CHARACTER_ACTIVITIES, -437 CHARACTER_EQUIPMENT, -438 RECORDS, -439 ) -440 """All character components.""" -441 -442 ALL = ( -443 *ALL_PROFILES, # type: ignore -444 *ALL_CHARACTERS, # type: ignore -445 *ALL_VENDORS, # type: ignore -446 *ALL_ITEMS, # type: ignore -447 RECORDS, -448 CURRENCY_LOOKUPS, -449 PRESENTATION_NODES, -450 COLLECTIBLES, -451 KIOSKS, -452 METRICS, -453 PLATFORM_SILVER, -454 INVENTORIES, -455 STRING_VARIABLES, -456 TRANSITORY, -457 CRAFTABLES, -458 ) -459 """ALl components included.""" +361 NONE = 0 +362 +363 PROFILE = 100 +364 PROFILE_INVENTORIES = 102 +365 PROFILE_CURRENCIES = 103 +366 PROFILE_PROGRESSION = 104 +367 ALL_PROFILES = ( +368 PROFILE, +369 PROFILE_INVENTORIES, +370 PROFILE_CURRENCIES, +371 PROFILE_PROGRESSION, +372 ) +373 """All profile components.""" +374 +375 VENDORS = 400 +376 VENDOR_SALES = 402 +377 VENDOR_RECEIPTS = 101 +378 ALL_VENDORS = (VENDORS, VENDOR_RECEIPTS, VENDOR_SALES) +379 """All vendor components.""" +380 +381 # Items +382 ITEM_INSTANCES = 300 +383 ITEM_OBJECTIVES = 301 +384 ITEM_PERKS = 302 +385 ITEM_RENDER_DATA = 303 +386 ITEM_STATS = 304 +387 ITEM_SOCKETS = 305 +388 ITEM_TALENT_GRINDS = 306 +389 ITEM_PLUG_STATES = 308 +390 ITEM_PLUG_OBJECTIVES = 309 +391 ITEM_REUSABLE_PLUGS = 310 +392 +393 ALL_ITEMS = ( +394 ITEM_PLUG_OBJECTIVES, +395 ITEM_PLUG_STATES, +396 ITEM_SOCKETS, +397 ITEM_INSTANCES, +398 ITEM_OBJECTIVES, +399 ITEM_PERKS, +400 ITEM_RENDER_DATA, +401 ITEM_STATS, +402 ITEM_TALENT_GRINDS, +403 ITEM_REUSABLE_PLUGS, +404 ) +405 """All item components.""" +406 +407 PLATFORM_SILVER = 105 +408 KIOSKS = 500 +409 CURRENCY_LOOKUPS = 600 +410 PRESENTATION_NODES = 700 +411 COLLECTIBLES = 800 +412 RECORDS = 900 +413 TRANSITORY = 1000 +414 METRICS = 1100 +415 INVENTORIES = 102 +416 STRING_VARIABLES = 1200 +417 CRAFTABLES = 1300 +418 +419 CHARACTERS = 200 +420 CHARACTER_INVENTORY = 201 +421 CHARECTER_PROGRESSION = 202 +422 CHARACTER_RENDER_DATA = 203 +423 CHARACTER_ACTIVITIES = 204 +424 CHARACTER_EQUIPMENT = 205 +425 +426 ALL_CHARACTERS = ( +427 CHARACTERS, +428 CHARACTER_INVENTORY, +429 CHARECTER_PROGRESSION, +430 CHARACTER_RENDER_DATA, +431 CHARACTER_ACTIVITIES, +432 CHARACTER_EQUIPMENT, +433 RECORDS, +434 ) +435 """All character components.""" +436 +437 ALL = ( +438 *ALL_PROFILES, # type: ignore +439 *ALL_CHARACTERS, # type: ignore +440 *ALL_VENDORS, # type: ignore +441 *ALL_ITEMS, # type: ignore +442 RECORDS, +443 CURRENCY_LOOKUPS, +444 PRESENTATION_NODES, +445 COLLECTIBLES, +446 KIOSKS, +447 METRICS, +448 PLATFORM_SILVER, +449 INVENTORIES, +450 STRING_VARIABLES, +451 TRANSITORY, +452 CRAFTABLES, +453 ) +454 """ALl components included.""" +455 +456 +457@typing.final +458class MembershipType(int, Enum): +459 """An Enum for Bungie membership types.""" 460 -461 -462@typing.final -463class MembershipType(int, Enum): -464 """An Enum for Bungie membership types.""" -465 -466 NONE = 0 -467 XBOX = 1 -468 PSN = 2 -469 STEAM = 3 -470 BLIZZARD = 4 -471 STADIA = 5 -472 BUNGIE = 254 -473 ALL = -1 -474 -475 -476@typing.final -477class Class(int, Enum): -478 """An Enum for Destiny character classes.""" -479 -480 TITAN = 0 -481 HUNTER = 1 -482 WARLOCK = 2 -483 UNKNOWN = 3 -484 -485 -486@typing.final -487class Gender(int, Enum): -488 """An Enum for Destiny Genders.""" -489 -490 MALE = 0 -491 FEMALE = 1 -492 UNKNOWN = 2 -493 -494 -495@typing.final -496class Race(int, Enum): -497 """An Enum for Destiny races.""" -498 -499 HUMAN = 0 -500 AWOKEN = 1 -501 EXO = 2 -502 UNKNOWN = 3 -503 -504 -505@typing.final -506class MilestoneType(int, Enum): -507 """An Enum for Destiny 2 milestone types.""" -508 -509 UNKNOWN = 0 -510 TUTORIAL = 1 -511 ONETIME = 2 -512 WEEKLY = 3 -513 DAILY = 4 -514 SPECIAL = 5 -515 -516 -517@typing.final -518class Stat(int, Enum): -519 """An Enum for Destiny 2 character stats.""" -520 -521 NONE = 0 -522 MOBILITY = 2996146975 -523 RESILIENCE = 392767087 -524 RECOVERY = 1943323491 -525 DISCIPLINE = 1735777505 -526 INTELLECT = 144602215 -527 STRENGTH = 4244567218 -528 LIGHT_POWER = 1935470627 -529 -530 -531@typing.final -532class WeaponType(int, Enum): -533 """Enums for The three Destiny Weapon Types""" -534 -535 NONE = 0 -536 KINETIC = 1498876634 -537 ENERGY = 2465295065 -538 POWER = 953998645 -539 -540 -541@typing.final -542class DamageType(int, Enum): -543 """Enums for Destiny Damage types""" -544 -545 NONE = 0 -546 KINETIC = 1 -547 ARC = 2 -548 SOLAR = 3 -549 VOID = 4 -550 RAID = 5 -551 """This is a special damage type reserved for some raid activity encounters.""" -552 STASIS = 6 -553 -554 -555@typing.final -556class ItemType(int, Enum): -557 """Enums for Destiny2's item types.""" -558 -559 NONE = 0 -560 CURRENCY = 1 -561 ARMOR = 2 -562 WEAPON = 3 -563 MESSAGE = 7 -564 ENGRAM = 8 -565 CONSUMABLE = 9 -566 EXCHANGEMATERIAL = 10 -567 MISSIONREWARD = 11 -568 QUESTSTEP = 12 -569 QUESTSTEPCOMPLETE = 13 -570 EMBLEM = 14 -571 QUEST = 15 -572 SUBCLASS = 16 -573 CLANBANNER = 17 -574 AURA = 18 -575 MOD = 19 -576 DUMMY = 20 -577 SHIP = 21 -578 VEHICLE = 22 -579 EMOTE = 23 -580 GHOST = 24 -581 PACKAGE = 25 -582 BOUNTY = 26 -583 WRAPPER = 27 -584 SEASONALARTIFACT = 28 -585 FINISHER = 29 -586 -587 -588@typing.final -589class ItemSubType(int, Enum): -590 """An enum for Destiny 2 inventory items subtype.""" -591 -592 NONE = 0 -593 AUTORIFLE = 6 -594 SHOTGUN = 7 -595 MACHINEGUN = 8 -596 HANDCANNON = 9 -597 ROCKETLAUNCHER = 10 -598 FUSIONRIFLE = 11 -599 SNIPERRIFLE = 12 -600 PULSERIFLE = 13 -601 SCOUTRIFLE = 14 -602 SIDEARM = 17 -603 SWORD = 18 -604 MASK = 19 -605 SHADER = 20 -606 ORNAMENT = 21 -607 FUSIONRIFLELINE = 22 -608 GRENADELAUNCHER = 23 -609 SUBMACHINEGUN = 24 -610 TRACERIFLE = 25 -611 HELMETARMOR = 26 -612 GAUNTLETSARMOR = 27 -613 CHESTARMOR = 28 -614 LEGARMOR = 29 -615 CLASSARMOR = 30 -616 BOW = 31 -617 DUMMYREPEATABLEBOUNTY = 32 -618 -619 -620@typing.final -621class ItemTier(int, Enum): -622 """An enum for a Destiny 2 item tier.""" -623 -624 NONE = 0 -625 BASIC = 3340296461 -626 COMMON = 2395677314 -627 RARE = 2127292149 -628 LEGENDERY = 4008398120 -629 EXOTIC = 2759499571 -630 -631 -632@typing.final -633class TierType(int, Enum): -634 """An enum for a Destiny 2 item tier type.""" -635 -636 UNKNOWN = 0 -637 CURRENCY = 1 -638 BASIC = 2 -639 COMMON = 3 -640 RARE = 4 -641 SUPERIOR = 5 -642 EXOTIC = 6 -643 -644 -645@typing.final -646class AmmoType(int, Enum): -647 """AN enum for Detyiny 2 ammo types.""" -648 -649 NONE = 0 -650 PRIMARY = 1 -651 SPECIAL = 2 -652 HEAVY = 3 -653 -654 -655@typing.final -656class GroupType(int, Enum): -657 """An enums for the known bungie group types.""" +461 NONE = 0 +462 XBOX = 1 +463 PSN = 2 +464 STEAM = 3 +465 BLIZZARD = 4 +466 STADIA = 5 +467 EPIC_GAMES_STORE = 6 +468 DEMON = 10 +469 BUNGIE = 254 +470 ALL = -1 +471 +472 +473@typing.final +474class Class(int, Enum): +475 """An Enum for Destiny character classes.""" +476 +477 TITAN = 0 +478 HUNTER = 1 +479 WARLOCK = 2 +480 UNKNOWN = 3 +481 +482 +483@typing.final +484class Gender(int, Enum): +485 """An Enum for Destiny Genders.""" +486 +487 MALE = 0 +488 FEMALE = 1 +489 UNKNOWN = 2 +490 +491 +492@typing.final +493class Race(int, Enum): +494 """An Enum for Destiny races.""" +495 +496 HUMAN = 0 +497 AWOKEN = 1 +498 EXO = 2 +499 UNKNOWN = 3 +500 +501 +502@typing.final +503class MilestoneType(int, Enum): +504 """An Enum for Destiny 2 milestone types.""" +505 +506 UNKNOWN = 0 +507 TUTORIAL = 1 +508 ONETIME = 2 +509 WEEKLY = 3 +510 DAILY = 4 +511 SPECIAL = 5 +512 +513 +514@typing.final +515class Stat(int, Enum): +516 """An Enum for Destiny 2 character stats.""" +517 +518 NONE = 0 +519 MOBILITY = 2996146975 +520 RESILIENCE = 392767087 +521 RECOVERY = 1943323491 +522 DISCIPLINE = 1735777505 +523 INTELLECT = 144602215 +524 STRENGTH = 4244567218 +525 LIGHT_POWER = 1935470627 +526 +527 +528@typing.final +529class WeaponType(int, Enum): +530 """Enums for The three Destiny Weapon Types""" +531 +532 NONE = 0 +533 KINETIC = 1498876634 +534 ENERGY = 2465295065 +535 POWER = 953998645 +536 +537 +538@typing.final +539class DamageType(int, Enum): +540 """Enums for Destiny Damage types""" +541 +542 NONE = 0 +543 KINETIC = 1 +544 ARC = 2 +545 SOLAR = 3 +546 VOID = 4 +547 RAID = 5 +548 """This is a special damage type reserved for some raid activity encounters.""" +549 STASIS = 6 +550 +551 +552@typing.final +553class ItemType(int, Enum): +554 """Enums for Destiny2's item types.""" +555 +556 NONE = 0 +557 CURRENCY = 1 +558 ARMOR = 2 +559 WEAPON = 3 +560 MESSAGE = 7 +561 ENGRAM = 8 +562 CONSUMABLE = 9 +563 EXCHANGEMATERIAL = 10 +564 MISSIONREWARD = 11 +565 QUESTSTEP = 12 +566 QUESTSTEPCOMPLETE = 13 +567 EMBLEM = 14 +568 QUEST = 15 +569 SUBCLASS = 16 +570 CLANBANNER = 17 +571 AURA = 18 +572 MOD = 19 +573 DUMMY = 20 +574 SHIP = 21 +575 VEHICLE = 22 +576 EMOTE = 23 +577 GHOST = 24 +578 PACKAGE = 25 +579 BOUNTY = 26 +580 WRAPPER = 27 +581 SEASONALARTIFACT = 28 +582 FINISHER = 29 +583 +584 +585@typing.final +586class ItemSubType(int, Enum): +587 """An enum for Destiny 2 inventory items subtype.""" +588 +589 NONE = 0 +590 AUTORIFLE = 6 +591 SHOTGUN = 7 +592 MACHINEGUN = 8 +593 HANDCANNON = 9 +594 ROCKETLAUNCHER = 10 +595 FUSIONRIFLE = 11 +596 SNIPERRIFLE = 12 +597 PULSERIFLE = 13 +598 SCOUTRIFLE = 14 +599 SIDEARM = 17 +600 SWORD = 18 +601 MASK = 19 +602 SHADER = 20 +603 ORNAMENT = 21 +604 FUSIONRIFLELINE = 22 +605 GRENADELAUNCHER = 23 +606 SUBMACHINEGUN = 24 +607 TRACERIFLE = 25 +608 HELMETARMOR = 26 +609 GAUNTLETSARMOR = 27 +610 CHESTARMOR = 28 +611 LEGARMOR = 29 +612 CLASSARMOR = 30 +613 BOW = 31 +614 DUMMYREPEATABLEBOUNTY = 32 +615 +616 +617@typing.final +618class ItemTier(int, Enum): +619 """An enum for a Destiny 2 item tier.""" +620 +621 NONE = 0 +622 BASIC = 3340296461 +623 COMMON = 2395677314 +624 RARE = 2127292149 +625 LEGENDERY = 4008398120 +626 EXOTIC = 2759499571 +627 +628 +629@typing.final +630class TierType(int, Enum): +631 """An enum for a Destiny 2 item tier type.""" +632 +633 UNKNOWN = 0 +634 CURRENCY = 1 +635 BASIC = 2 +636 COMMON = 3 +637 RARE = 4 +638 SUPERIOR = 5 +639 EXOTIC = 6 +640 +641 +642@typing.final +643class AmmoType(int, Enum): +644 """AN enum for Detyiny 2 ammo types.""" +645 +646 NONE = 0 +647 PRIMARY = 1 +648 SPECIAL = 2 +649 HEAVY = 3 +650 +651 +652@typing.final +653class GroupType(int, Enum): +654 """An enums for the known bungie group types.""" +655 +656 GENERAL = 0 +657 CLAN = 1 658 -659 GENERAL = 0 -660 CLAN = 1 -661 -662 -663@typing.final -664class CredentialType(int, Enum): -665 """The types of the accounts system supports at bungie.""" -666 -667 NONE = 0 -668 XUID = 1 -669 PSNID = 2 -670 WILD = 3 -671 FAKE = 4 -672 FACEBOOK = 5 -673 GOOGLE = 8 -674 WINDOWS = 9 -675 DEMONID = 10 -676 STEAMID = 12 -677 BATTLENETID = 14 -678 STADIAID = 16 -679 TWITCHID = 18 -680 -681 -682@typing.final -683class Presence(int, Enum): -684 """An enum for a bungie friend status.""" +659 +660@typing.final +661class CredentialType(int, Enum): +662 """The types of the accounts system supports at bungie.""" +663 +664 NONE = 0 +665 XUID = 1 +666 PSNID = 2 +667 WILD = 3 +668 FAKE = 4 +669 FACEBOOK = 5 +670 GOOGLE = 8 +671 WINDOWS = 9 +672 DEMONID = 10 +673 STEAMID = 12 +674 BATTLENETID = 14 +675 STADIAID = 16 +676 TWITCHID = 18 +677 +678 +679@typing.final +680class Presence(int, Enum): +681 """An enum for a bungie friend status.""" +682 +683 OFFLINE_OR_UNKNOWN = 0 +684 ONLINE = 1 685 -686 OFFLINE_OR_UNKNOWN = 0 -687 ONLINE = 1 -688 -689 -690@typing.final -691class Relationship(int, Enum): -692 """An enum for bungie friends relationship types.""" -693 -694 UNKNOWN = 0 -695 FRIEND = 1 -696 INCOMING_REQUEST = 2 -697 OUTGOING_REQUEST = 3 -698 -699 -700@typing.final -701class ClanMemberType(int, Enum): -702 """An enum for bungie clan member types.""" -703 -704 NONE = 0 -705 BEGINNER = 1 -706 MEMBER = 2 -707 ADMIN = 3 -708 ACTING_FOUNDER = 4 -709 FOUNDER = 5 -710 -711 -712@typing.final -713class MembershipOption(int, Enum): -714 """A enum for GroupV2 membership options.""" -715 -716 REVIEWD = 0 -717 OPEN = 1 -718 CLOSED = 2 -719 -720 -721@typing.final -722class ItemBindStatus(int, Enum): -723 """An enum for Destiny 2 items bind status.""" -724 -725 NOT_BOUND = 0 -726 BOUND_TO_CHARACTER = 1 -727 BOUND_TO_ACCOUNT = 2 -728 BOUNT_TO_GUILD = 3 -729 -730 -731@typing.final -732class ItemLocation(int, Enum): -733 """An enum for Destiny 2 items location.""" -734 -735 UNKNOWN = 0 -736 INVENTORY = 1 -737 VAULT = 2 -738 VENDOR = 3 -739 POSTMASTER = 4 -740 -741 -742@typing.final -743class TransferStatus(Flag): -744 """An enum for items transfer statuses.""" -745 -746 CAN_TRANSFER = 0 -747 """The item can be transferred.""" -748 IS_EQUIPPED = 1 -749 """You can't transfer since the item is equipped.""" -750 NOT_TRASNFERRABLE = 2 -751 """This item can not be transferred.""" -752 COULD_BE_TRANSFERRED = 4 -753 """You can trasnfer the item. But the place you're trying to put it at has no space for it.""" -754 -755 -756@typing.final -757class ItemState(Flag): -758 """An enum for Destiny 2 item states.""" -759 -760 NONE = 0 -761 LOCKED = 1 -762 TRACKED = 2 -763 MASTERWORKED = 4 -764 CRAFTED = 8 -765 """If this bit is set, the item has been 'crafted' by the player.""" -766 HIGHLITED_OBJECTIVE = 16 -767 """If this bit is set, the item is a 'highlighted' objective.""" -768 -769 -770@typing.final -771class PrivacySetting(int, Enum): -772 """An enum for players's privacy settings.""" -773 -774 OPEN = 0 -775 CLAN_AND_FRIENDS = 1 -776 FRIENDS_ONLY = 2 -777 INVITE_ONLY = 3 -778 CLOSED = 4 -779 -780 -781@typing.final -782class ClosedReasons(Flag): -783 """A Flags enumeration representing the reasons why a person can't join this user's fireteam.""" -784 -785 NONE = 0 -786 MATCHMAKING = 1 -787 LOADING = 2 -788 SOLO = 4 -789 """The activity is required to be played solo.""" -790 INTERNAL_REASONS = 8 -791 """ -792 The user can't be joined for one of a variety of internal reasons. -793 Basically, the game can't let you join at this time, -794 but for reasons that aren't under the control of this user -795 """ -796 DISALLOWED_BY_GAME_STATE = 16 -797 """The user's current activity/quest/other transitory game state is preventing joining.""" -798 OFFLINE = 32768 -799 """The user appears offline.""" -800 -801 -802@typing.final -803class StatsGroupType(int, Enum): -804 """Bungie historical group stats type enum.""" -805 -806 NONE = 0 -807 GENERAL = 1 -808 WEAPONS = 2 -809 MEDALS = 3 -810 REVERSED_GROUPS = 100 -811 """This is purely to serve as the dividing line between filterable and un-filterable groups. -812 Below this number is a group you can pass as a filter. -813 Above it are groups used in very specific circumstances and not relevant for filtering. -814 """ -815 LEADERBOARDS = 101 -816 ACTIVITY = 102 -817 UNIQUE_WEAPON = 103 -818 INTERNAL = 104 -819 -820 -821@typing.final -822class PeriodType(int, Enum): -823 """Bungie historical group stats period type enum.""" -824 -825 NONE = 0 -826 DAILY = 1 -827 ALL_TIME = 2 -828 ACTIVITY = 3 +686 +687@typing.final +688class Relationship(int, Enum): +689 """An enum for bungie friends relationship types.""" +690 +691 UNKNOWN = 0 +692 FRIEND = 1 +693 INCOMING_REQUEST = 2 +694 OUTGOING_REQUEST = 3 +695 +696 +697@typing.final +698class ClanMemberType(int, Enum): +699 """An enum for bungie clan member types.""" +700 +701 NONE = 0 +702 BEGINNER = 1 +703 MEMBER = 2 +704 ADMIN = 3 +705 ACTING_FOUNDER = 4 +706 FOUNDER = 5 +707 +708 +709@typing.final +710class MembershipOption(int, Enum): +711 """A enum for GroupV2 membership options.""" +712 +713 REVIEWD = 0 +714 OPEN = 1 +715 CLOSED = 2 +716 +717 +718@typing.final +719class ItemBindStatus(int, Enum): +720 """An enum for Destiny 2 items bind status.""" +721 +722 NOT_BOUND = 0 +723 BOUND_TO_CHARACTER = 1 +724 BOUND_TO_ACCOUNT = 2 +725 BOUNT_TO_GUILD = 3 +726 +727 +728@typing.final +729class ItemLocation(int, Enum): +730 """An enum for Destiny 2 items location.""" +731 +732 UNKNOWN = 0 +733 INVENTORY = 1 +734 VAULT = 2 +735 VENDOR = 3 +736 POSTMASTER = 4 +737 +738 +739@typing.final +740class TransferStatus(Flag): +741 """An enum for items transfer statuses.""" +742 +743 CAN_TRANSFER = 0 +744 """The item can be transferred.""" +745 IS_EQUIPPED = 1 << 0 +746 """You can't transfer since the item is equipped.""" +747 NOT_TRASNFERRABLE = 1 << 1 +748 """This item can not be transferred.""" +749 COULD_BE_TRANSFERRED = 1 << 2 +750 """You can trasnfer the item. But the place you're trying to put it at has no space for it.""" +751 +752 +753@typing.final +754class ItemState(Flag): +755 """An enum for Destiny 2 item states.""" +756 +757 NONE = 0 +758 LOCKED = 1 << 0 +759 TRACKED = 1 << 1 +760 MASTERWORKED = 1 << 2 +761 CRAFTED = 1 << 3 +762 """If this bit is set, the item has been 'crafted' by the player.""" +763 HIGHLITED_OBJECTIVE = 1 << 4 +764 """If this bit is set, the item is a 'highlighted' objective.""" +765 +766 +767@typing.final +768class PrivacySetting(int, Enum): +769 """An enum for players's privacy settings.""" +770 +771 OPEN = 0 +772 CLAN_AND_FRIENDS = 1 +773 FRIENDS_ONLY = 2 +774 INVITE_ONLY = 3 +775 CLOSED = 4 +776 +777 +778@typing.final +779class ClosedReasons(Flag): +780 """A Flags enumeration representing the reasons why a person can't join this user's fireteam.""" +781 +782 NONE = 0 +783 MATCHMAKING = 1 << 0 +784 LOADING = 1 << 1 +785 SOLO = 1 << 2 +786 """The activity is required to be played solo.""" +787 INTERNAL_REASONS = 1 << 3 +788 """ +789 The user can't be joined for one of a variety of internal reasons. +790 Basically, the game can't let you join at this time, +791 but for reasons that aren't under the control of this user +792 """ +793 DISALLOWED_BY_GAME_STATE = 1 << 4 +794 """The user's current activity/quest/other transitory game state is preventing joining.""" +795 OFFLINE = 32768 +796 """The user appears offline.""" +797 +798 +799@typing.final +800class StatsGroupType(int, Enum): +801 """Bungie historical group stats type enum.""" +802 +803 NONE = 0 +804 GENERAL = 1 +805 WEAPONS = 2 +806 MEDALS = 3 +807 REVERSED_GROUPS = 100 +808 """This is purely to serve as the dividing line between filterable and un-filterable groups. +809 Below this number is a group you can pass as a filter. +810 Above it are groups used in very specific circumstances and not relevant for filtering. +811 """ +812 LEADERBOARDS = 101 +813 ACTIVITY = 102 +814 UNIQUE_WEAPON = 103 +815 INTERNAL = 104 +816 +817 +818@typing.final +819class PeriodType(int, Enum): +820 """Bungie historical group stats period type enum.""" +821 +822 NONE = 0 +823 DAILY = 1 +824 ALL_TIME = 2 +825 ACTIVITY = 3

          @@ -2144,29 +1244,29 @@

          -
          77class Enum(__enum.Enum):
          -78    """Builtin Python enum with extra handlings."""
          -79
          -80    @property
          -81    def name(self) -> str:  # type: ignore[override]
          -82        return self._name_
          -83
          -84    @property
          -85    def value(self) -> typing.Any:  # type: ignore[override]
          -86        return self._value_
          -87
          -88    def __str__(self) -> str:
          -89        return self._name_
          -90
          -91    def __repr__(self) -> str:
          -92        return f"<{type(self).__name__}.{self._name_}: {self._value_!s}>"
          -93
          -94    def __int__(self) -> int:
          -95        if isinstance(self.value, _ITERABLE):
          -96            raise TypeError(
          -97                f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.",
          -98            )
          -99        return int(self.value)
          +            
          72class Enum(__enum.Enum):
          +73    """Builtin Python enum with extra handlings."""
          +74
          +75    @property
          +76    def name(self) -> str:  # type: ignore[override]
          +77        return self._name_
          +78
          +79    @property
          +80    def value(self) -> typing.Any:  # type: ignore[override]
          +81        return self._value_
          +82
          +83    def __str__(self) -> str:
          +84        return self._name_
          +85
          +86    def __repr__(self) -> str:
          +87        return f"<{type(self).__name__}.{self._name_}: {self._value_!s}>"
          +88
          +89    def __int__(self) -> int:
          +90        if isinstance(self.value, _ITERABLE):
          +91            raise TypeError(
          +92                f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.",
          +93            )
          +94        return int(self.value)
           
          @@ -2182,7 +1282,9 @@

          - +

          The name of the Enum member.

          +
          +
          @@ -2193,7 +1295,9 @@

          - +

          The value of the Enum member.

          +
          + @@ -2208,50 +1312,50 @@

          -
          102class Flag(__enum.Flag):
          -103    """Builtin Python enum flag with extra handlings."""
          -104
          -105    # Needs to type this here for mypy
          -106    _value_: int
          +            
           97class Flag(__enum.Flag):
          + 98    """Builtin Python enum flag with extra handlings."""
          + 99
          +100    # Needs to type this here for mypy
          +101    _value_: int
          +102
          +103    @property
          +104    def name(self) -> str:  # type: ignore[override]
          +105        if self._name_ is None:
          +106            self._name_ = f"UNKNOWN {self._value_}"
           107
          -108    @property
          -109    def name(self) -> str:  # type: ignore[override]
          -110        if self._name_ is None:
          -111            self._name_ = f"UNKNOWN {self._value_}"
          -112
          -113        return self._name_
          -114
          -115    @property
          -116    def value(self) -> int:  # type: ignore[override]
          -117        return self._value_
          -118
          -119    def __str__(self) -> str:
          -120        return self.name
          -121
          -122    def __repr__(self) -> str:
          -123        return f"<{type(self).__name__}.{self.name}: {self._value_!s}>"
          -124
          -125    def __int__(self) -> int:
          -126        if isinstance(self.value, _ITERABLE):
          -127            raise TypeError(
          -128                f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.",
          -129            )
          -130        return int(self.value)
          -131
          -132    def __or__(self, other: typing.Union[Flag, int]) -> Flag:
          -133        return self.__class__(self._value_ | int(other))
          -134
          -135    def __xor__(self, other: typing.Union[Flag, int]) -> Flag:
          -136        return self.__class__(self._value_ ^ int(other))
          -137
          -138    def __and__(self, other: typing.Union[Flag, int]) -> Flag:
          -139        return self.__class__(other & int(other))
          -140
          -141    def __invert__(self) -> Flag:
          -142        return self.__class__(~self._value_)
          -143
          -144    def __contains__(self, other: typing.Union[Flag, int]) -> bool:
          -145        return self.value & int(other) == int(other)
          +108        return self._name_
          +109
          +110    @property
          +111    def value(self) -> int:  # type: ignore[override]
          +112        return self._value_
          +113
          +114    def __str__(self) -> str:
          +115        return self.name
          +116
          +117    def __repr__(self) -> str:
          +118        return f"<{type(self).__name__}.{self.name}: {self._value_!s}>"
          +119
          +120    def __int__(self) -> int:
          +121        if isinstance(self.value, _ITERABLE):
          +122            raise TypeError(
          +123                f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.",
          +124            )
          +125        return int(self.value)
          +126
          +127    def __or__(self, other: typing.Union[Flag, int]) -> Flag:
          +128        return self.__class__(self._value_ | int(other))
          +129
          +130    def __xor__(self, other: typing.Union[Flag, int]) -> Flag:
          +131        return self.__class__(self._value_ ^ int(other))
          +132
          +133    def __and__(self, other: typing.Union[Flag, int]) -> Flag:
          +134        return self.__class__(other & int(other))
          +135
          +136    def __invert__(self) -> Flag:
          +137        return self.__class__(~self._value_)
          +138
          +139    def __contains__(self, other: typing.Union[Flag, int]) -> bool:
          +140        return self.value & int(other) == int(other)
           
          @@ -2267,7 +1371,9 @@

          - +

          The name of the Enum member.

          +
          +
          @@ -2278,7 +1384,9 @@

          - +

          The value of the Enum member.

          +
          + @@ -2294,93 +1402,93 @@

          -
          274@typing.final
          -275class GameMode(int, Enum):
          -276    """An Enum for all available gamemodes in Destiny 2."""
          -277
          -278    NONE = 0
          -279    STORY = 2
          -280    STRIKE = 3
          -281    RAID = 4
          -282    ALLPVP = 5
          -283    PATROL = 6
          -284    ALLPVE = 7
          -285    RESERVED9 = 9
          -286    CONTROL = 10
          -287    RESERVED11 = 11
          -288    CLASH = 12
          -289    RESERVED13 = 13
          -290    CRIMSONDOUBLES = 15
          -291    NIGHTFALL = 16
          -292    HEROICNIGHTFALL = 17
          -293    ALLSTRIKES = 18
          -294    IRONBANNER = 19
          -295    RESERVED20 = 20
          -296    RESERVED21 = 21
          -297    RESERVED22 = 22
          -298    RESERVED24 = 24
          -299    ALLMAYHEM = 25
          -300    RESERVED26 = 26
          -301    RESERVED27 = 27
          -302    RESERVED28 = 28
          -303    RESERVED29 = 29
          -304    RESERVED30 = 30
          -305    SUPREMACY = 31
          -306    PRIVATEMATCHESALL = 32
          -307    SURVIVAL = 37
          -308    COUNTDOWN = 38
          -309    TRIALSOFTHENINE = 39
          -310    SOCIAL = 40
          -311    TRIALSCOUNTDOWN = 41
          -312    TRIALSSURVIVAL = 42
          -313    IRONBANNERCONTROL = 43
          -314    IRONBANNERCLASH = 44
          -315    IRONBANNERSUPREMACY = 45
          -316    SCOREDNIGHTFALL = 46
          -317    SCOREDHEROICNIGHTFALL = 47
          -318    RUMBLE = 48
          -319    ALLDOUBLES = 49
          -320    DOUBLES = 50
          -321    PRIVATEMATCHESCLASH = 51
          -322    PRIVATEMATCHESCONTROL = 52
          -323    PRIVATEMATCHESSUPREMACY = 53
          -324    PRIVATEMATCHESCOUNTDOWN = 54
          -325    PRIVATEMATCHESSURVIVAL = 55
          -326    PRIVATEMATCHESMAYHEM = 56
          -327    PRIVATEMATCHESRUMBLE = 57
          -328    HEROICADVENTURE = 58
          -329    SHOWDOWN = 59
          -330    LOCKDOWN = 60
          -331    SCORCHED = 61
          -332    SCORCHEDTEAM = 62
          -333    GAMBIT = 63
          -334    ALLPVECOMPETITIVE = 64
          -335    BREAKTHROUGH = 65
          -336    BLACKARMORYRUN = 66
          -337    SALVAGE = 67
          -338    IRONBANNERSALVAGE = 68
          -339    PVPCOMPETITIVE = 69
          -340    PVPQUICKPLAY = 70
          -341    CLASHQUICKPLAY = 71
          -342    CLASHCOMPETITIVE = 72
          -343    CONTROLQUICKPLAY = 73
          -344    CONTROLCOMPETITIVE = 74
          -345    GAMBITPRIME = 75
          -346    RECKONING = 76
          -347    MENAGERIE = 77
          -348    VEXOFFENSIVE = 78
          -349    NIGHTMAREHUNT = 79
          -350    ELIMINATION = 80
          -351    MOMENTUM = 81
          -352    DUNGEON = 82
          -353    SUNDIAL = 83
          -354    TRIALS_OF_OSIRIS = 84
          -355    DARES = 85
          -356    OFFENSIVE = 86
          -357    LOSTSECTOR = 87
          -358    RIFT = 88
          -359    ZONECONTROL = 89
          -360    IRONBANNERRIFT = 90
          +            
          269@typing.final
          +270class GameMode(int, Enum):
          +271    """An Enum for all available gamemodes in Destiny 2."""
          +272
          +273    NONE = 0
          +274    STORY = 2
          +275    STRIKE = 3
          +276    RAID = 4
          +277    ALLPVP = 5
          +278    PATROL = 6
          +279    ALLPVE = 7
          +280    RESERVED9 = 9
          +281    CONTROL = 10
          +282    RESERVED11 = 11
          +283    CLASH = 12
          +284    RESERVED13 = 13
          +285    CRIMSONDOUBLES = 15
          +286    NIGHTFALL = 16
          +287    HEROICNIGHTFALL = 17
          +288    ALLSTRIKES = 18
          +289    IRONBANNER = 19
          +290    RESERVED20 = 20
          +291    RESERVED21 = 21
          +292    RESERVED22 = 22
          +293    RESERVED24 = 24
          +294    ALLMAYHEM = 25
          +295    RESERVED26 = 26
          +296    RESERVED27 = 27
          +297    RESERVED28 = 28
          +298    RESERVED29 = 29
          +299    RESERVED30 = 30
          +300    SUPREMACY = 31
          +301    PRIVATEMATCHESALL = 32
          +302    SURVIVAL = 37
          +303    COUNTDOWN = 38
          +304    TRIALSOFTHENINE = 39
          +305    SOCIAL = 40
          +306    TRIALSCOUNTDOWN = 41
          +307    TRIALSSURVIVAL = 42
          +308    IRONBANNERCONTROL = 43
          +309    IRONBANNERCLASH = 44
          +310    IRONBANNERSUPREMACY = 45
          +311    SCOREDNIGHTFALL = 46
          +312    SCOREDHEROICNIGHTFALL = 47
          +313    RUMBLE = 48
          +314    ALLDOUBLES = 49
          +315    DOUBLES = 50
          +316    PRIVATEMATCHESCLASH = 51
          +317    PRIVATEMATCHESCONTROL = 52
          +318    PRIVATEMATCHESSUPREMACY = 53
          +319    PRIVATEMATCHESCOUNTDOWN = 54
          +320    PRIVATEMATCHESSURVIVAL = 55
          +321    PRIVATEMATCHESMAYHEM = 56
          +322    PRIVATEMATCHESRUMBLE = 57
          +323    HEROICADVENTURE = 58
          +324    SHOWDOWN = 59
          +325    LOCKDOWN = 60
          +326    SCORCHED = 61
          +327    SCORCHEDTEAM = 62
          +328    GAMBIT = 63
          +329    ALLPVECOMPETITIVE = 64
          +330    BREAKTHROUGH = 65
          +331    BLACKARMORYRUN = 66
          +332    SALVAGE = 67
          +333    IRONBANNERSALVAGE = 68
          +334    PVPCOMPETITIVE = 69
          +335    PVPQUICKPLAY = 70
          +336    CLASHQUICKPLAY = 71
          +337    CLASHCOMPETITIVE = 72
          +338    CONTROLQUICKPLAY = 73
          +339    CONTROLCOMPETITIVE = 74
          +340    GAMBITPRIME = 75
          +341    RECKONING = 76
          +342    MENAGERIE = 77
          +343    VEXOFFENSIVE = 78
          +344    NIGHTMAREHUNT = 79
          +345    ELIMINATION = 80
          +346    MOMENTUM = 81
          +347    DUNGEON = 82
          +348    SUNDIAL = 83
          +349    TRIALS_OF_OSIRIS = 84
          +350    DARES = 85
          +351    OFFENSIVE = 86
          +352    LOSTSECTOR = 87
          +353    RIFT = 88
          +354    ZONECONTROL = 89
          +355    IRONBANNERRIFT = 90
           
          @@ -2388,5186 +1496,2039 @@

          -
          -
          - NONE = <GameMode.NONE: 0> +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          - -
          - - - +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - STORY = <GameMode.STORY: 2> + +
          + +
          +
          @typing.final
          - -
          - - - + class + MembershipType(builtins.int, Enum): -
          -
          -
          - STRIKE = <GameMode.STRIKE: 3> + -
          - - - - -
          -
          -
          - RAID = <GameMode.RAID: 4> + +
          458@typing.final
          +459class MembershipType(int, Enum):
          +460    """An Enum for Bungie membership types."""
          +461
          +462    NONE = 0
          +463    XBOX = 1
          +464    PSN = 2
          +465    STEAM = 3
          +466    BLIZZARD = 4
          +467    STADIA = 5
          +468    EPIC_GAMES_STORE = 6
          +469    DEMON = 10
          +470    BUNGIE = 254
          +471    ALL = -1
          +
          - -
          - - - -
          -
          -
          - ALLPVP = <GameMode.ALLPVP: 5> +

          An Enum for Bungie membership types.

          +
          - -
          - - - -
          -
          -
          - PATROL = <GameMode.PATROL: 6> +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          - -
          - - - +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - ALLPVE = <GameMode.ALLPVE: 7> + +
          + +
          +
          @typing.final
          - -
          - - - + class + Class(builtins.int, Enum): -
          -
          -
          - RESERVED9 = <GameMode.RESERVED9: 9> + -
          - - - - -
          -
          -
          - CONTROL = <GameMode.CONTROL: 10> + +
          474@typing.final
          +475class Class(int, Enum):
          +476    """An Enum for Destiny character classes."""
          +477
          +478    TITAN = 0
          +479    HUNTER = 1
          +480    WARLOCK = 2
          +481    UNKNOWN = 3
          +
          - -
          - - - -
          -
          -
          - RESERVED11 = <GameMode.RESERVED11: 11> +

          An Enum for Destiny character classes.

          +
          - -
          - - - -
          -
          -
          - CLASH = <GameMode.CLASH: 12> +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          - -
          - - - +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - RESERVED13 = <GameMode.RESERVED13: 13> + +
          + +
          +
          @typing.final
          - -
          - - - + class + MilestoneType(builtins.int, Enum): -
          -
          -
          - CRIMSONDOUBLES = <GameMode.CRIMSONDOUBLES: 15> + -
          - - - + +
          503@typing.final
          +504class MilestoneType(int, Enum):
          +505    """An Enum for Destiny 2 milestone types."""
          +506
          +507    UNKNOWN = 0
          +508    TUTORIAL = 1
          +509    ONETIME = 2
          +510    WEEKLY = 3
          +511    DAILY = 4
          +512    SPECIAL = 5
          +
          -
          -
          -
          - NIGHTFALL = <GameMode.NIGHTFALL: 16> - -
          - - - +

          An Enum for Destiny 2 milestone types.

          +
          -
          -
          -
          - HEROICNIGHTFALL = <GameMode.HEROICNIGHTFALL: 17> - -
          - - - +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          + +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - ALLSTRIKES = <GameMode.ALLSTRIKES: 18> + +
          + +
          +
          @typing.final
          - -
          - - - + class + Race(builtins.int, Enum): -
          -
          -
          - IRONBANNER = <GameMode.IRONBANNER: 19> + -
          - - - + +
          493@typing.final
          +494class Race(int, Enum):
          +495    """An Enum for Destiny races."""
          +496
          +497    HUMAN = 0
          +498    AWOKEN = 1
          +499    EXO = 2
          +500    UNKNOWN = 3
          +
          -
          -
          -
          - RESERVED20 = <GameMode.RESERVED20: 20> - -
          - - - +

          An Enum for Destiny races.

          +
          -
          -
          -
          - RESERVED21 = <GameMode.RESERVED21: 21> - -
          - - - +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          + +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - RESERVED22 = <GameMode.RESERVED22: 22> + +
          + +
          +
          @typing.final
          - -
          - - - + class + Vendor(builtins.int, Enum): -
          -
          -
          - RESERVED24 = <GameMode.RESERVED24: 24> + -
          - - - + +
          240@typing.final
          +241class Vendor(int, Enum):
          +242    """An Enum for all available vendors in Destiny 2."""
          +243
          +244    ZAVALA = 69482069
          +245    XUR = 2190858386
          +246    BANSHE = 672118013
          +247    SPIDER = 863940356
          +248    SHAXX = 3603221665
          +249    KADI = 529635856
          +250    """Postmaster exo."""
          +251    YUNA = 1796504621
          +252    """Asia servers only."""
          +253    EVERVERSE = 3361454721
          +254    AMANDA = 460529231
          +255    """Amanda holiday"""
          +256    CROW = 3611983588
          +257    HAWTHORNE = 3347378076
          +258    ADA1 = 350061650
          +259    DRIFTER = 248695599
          +260    IKORA = 1976548992
          +261    SAINT = 765357505
          +262    """Saint-14"""
          +263    ERIS_MORN = 1616085565
          +264    SHAW_HAWN = 1816541247
          +265    """COSMODROME Guy"""
          +266    VARIKS = 2531198101
          +
          -
          -
          + +

          An Enum for all available vendors in Destiny 2.

          +
          + + +
          - ALLMAYHEM = <GameMode.ALLMAYHEM: 25> + KADI = <Vendor.KADI: 529635856>
          - - + +

          Postmaster exo.

          +
          +
          -
          +
          - RESERVED26 = <GameMode.RESERVED26: 26> + YUNA = <Vendor.YUNA: 1796504621>
          - - + +

          Asia servers only.

          +
          +
          -
          +
          - RESERVED27 = <GameMode.RESERVED27: 27> + AMANDA = <Vendor.AMANDA: 460529231>
          - - + +

          Amanda holiday

          +
          +
          -
          +
          - RESERVED28 = <GameMode.RESERVED28: 28> + SAINT = <Vendor.SAINT: 765357505>
          - - + +

          Saint-14

          +
          +
          -
          +
          - RESERVED29 = <GameMode.RESERVED29: 29> + SHAW_HAWN = <Vendor.SHAW_HAWN: 1816541247>
          - - + +

          COSMODROME Guy

          +
          +
          -
          -
          - RESERVED30 = <GameMode.RESERVED30: 30> +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          - -
          - - - +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - SUPREMACY = <GameMode.SUPREMACY: 31> + +
          + +
          +
          @typing.final
          + + class + Raid(builtins.int, Enum): + + -
          - - - + +
          143@typing.final
          +144class Raid(int, Enum):
          +145    """An Enum for all available raids in Destiny 2."""
          +146
          +147    DSC = 910380154
          +148    """Deep Stone Crypt"""
          +149
          +150    LW = 2122313384
          +151    """Last Wish"""
          +152
          +153    VOG = 3881495763
          +154    """Normal Valut of Glass"""
          +155
          +156    GOS = 3458480158
          +157    """Garden Of Salvation"""
          +
          -
          -
          + +

          An Enum for all available raids in Destiny 2.

          +
          + + +
          - PRIVATEMATCHESALL = <GameMode.PRIVATEMATCHESALL: 32> + DSC = <Raid.DSC: 910380154>
          - - + +

          Deep Stone Crypt

          +
          +
          -
          +
          - SURVIVAL = <GameMode.SURVIVAL: 37> + LW = <Raid.LW: 2122313384>
          - - + +

          Last Wish

          +
          +
          -
          +
          - COUNTDOWN = <GameMode.COUNTDOWN: 38> + VOG = <Raid.VOG: 3881495763>
          - - + +

          Normal Valut of Glass

          +
          +
          -
          +
          - TRIALSOFTHENINE = <GameMode.TRIALSOFTHENINE: 39> + GOS = <Raid.GOS: 3458480158>
          - - + +

          Garden Of Salvation

          +
          +
          -
          -
          - SOCIAL = <GameMode.SOCIAL: 40> +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          - -
          - - - +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - TRIALSCOUNTDOWN = <GameMode.TRIALSCOUNTDOWN: 41> + +
          + +
          +
          @typing.final
          - -
          - - - + class + Dungeon(builtins.int, Enum): -
          -
          -
          - TRIALSSURVIVAL = <GameMode.TRIALSSURVIVAL: 42> + -
          - - - + +
          160@typing.final
          +161class Dungeon(int, Enum):
          +162    """An Enum for all available Dungeon/Like missions in Destiny 2."""
          +163
          +164    NORMAL_PRESAGE = 2124066889
          +165    """Normal Presage"""
          +166
          +167    MASTER_PRESAGE = 4212753278
          +168    """Master Presage"""
          +169
          +170    HARBINGER = 1738383283
          +171    """Harbinger"""
          +172
          +173    PROPHECY = 4148187374
          +174    """Prophecy"""
          +175
          +176    MASTER_POH = 785700673
          +177    """Master Pit of Heresy?"""
          +178
          +179    LEGEND_POH = 785700678
          +180    """Legend Pit of Heresy?"""
          +181
          +182    POH = 1375089621
          +183    """Normal Pit of Heresy."""
          +184
          +185    SHATTERED = 2032534090
          +186    """Shattered Throne"""
          +187
          +188    GOA_LEGEND = 4078656646
          +189    """Grasp of Avarice legend."""
          +190
          +191    GOA_MASTER = 3774021532
          +192    """Grasp of Avarice master."""
          +
          -
          -
          -
          - IRONBANNERCONTROL = <GameMode.IRONBANNERCONTROL: 43> - -
          - - - +

          An Enum for all available Dungeon/Like missions in Destiny 2.

          +
          -
          -
          + +
          - IRONBANNERCLASH = <GameMode.IRONBANNERCLASH: 44> + NORMAL_PRESAGE = <Dungeon.NORMAL_PRESAGE: 2124066889>
          - - + +

          Normal Presage

          +
          +
          -
          +
          - IRONBANNERSUPREMACY = <GameMode.IRONBANNERSUPREMACY: 45> + MASTER_PRESAGE = <Dungeon.MASTER_PRESAGE: 4212753278>
          - - + +

          Master Presage

          +
          +
          -
          +
          - SCOREDNIGHTFALL = <GameMode.SCOREDNIGHTFALL: 46> + HARBINGER = <Dungeon.HARBINGER: 1738383283>
          - - + +

          Harbinger

          +
          +
          -
          +
          - SCOREDHEROICNIGHTFALL = <GameMode.SCOREDHEROICNIGHTFALL: 47> + PROPHECY = <Dungeon.PROPHECY: 4148187374>
          - - + +

          Prophecy

          +
          +
          -
          +
          - RUMBLE = <GameMode.RUMBLE: 48> + MASTER_POH = <Dungeon.MASTER_POH: 785700673>
          - - + +

          Master Pit of Heresy?

          +
          +
          -
          +
          - ALLDOUBLES = <GameMode.ALLDOUBLES: 49> + LEGEND_POH = <Dungeon.LEGEND_POH: 785700678>
          - - + +

          Legend Pit of Heresy?

          +
          +
          -
          +
          - DOUBLES = <GameMode.DOUBLES: 50> + POH = <Dungeon.POH: 1375089621>
          - - + +

          Normal Pit of Heresy.

          +
          +
          -
          +
          - PRIVATEMATCHESCLASH = <GameMode.PRIVATEMATCHESCLASH: 51> + SHATTERED = <Dungeon.SHATTERED: 2032534090>
          - - + +

          Shattered Throne

          +
          +
          -
          +
          - PRIVATEMATCHESCONTROL = <GameMode.PRIVATEMATCHESCONTROL: 52> + GOA_LEGEND = <Dungeon.GOA_LEGEND: 4078656646>
          - - + +

          Grasp of Avarice legend.

          +
          +
          -
          +
          - PRIVATEMATCHESSUPREMACY = <GameMode.PRIVATEMATCHESSUPREMACY: 53> + GOA_MASTER = <Dungeon.GOA_MASTER: 3774021532>
          - - + +

          Grasp of Avarice master.

          +
          +
          -
          -
          - PRIVATEMATCHESCOUNTDOWN = <GameMode.PRIVATEMATCHESCOUNTDOWN: 54> +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          - -
          - - - +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - PRIVATEMATCHESSURVIVAL = <GameMode.PRIVATEMATCHESSURVIVAL: 55> + +
          + +
          +
          @typing.final
          - -
          - - - + class + Gender(builtins.int, Enum): -
          -
          -
          - PRIVATEMATCHESMAYHEM = <GameMode.PRIVATEMATCHESMAYHEM: 56> + -
          - - - + +
          484@typing.final
          +485class Gender(int, Enum):
          +486    """An Enum for Destiny Genders."""
          +487
          +488    MALE = 0
          +489    FEMALE = 1
          +490    UNKNOWN = 2
          +
          + + +

          An Enum for Destiny Genders.

          +
          + + +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          + +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - PRIVATEMATCHESRUMBLE = <GameMode.PRIVATEMATCHESRUMBLE: 57> + +
          + +
          +
          @typing.final
          + + class + ComponentType(Enum): + + -
          - - - + +
          358@typing.final
          +359class ComponentType(Enum):
          +360    """An Enum for Destiny 2 profile Components."""
          +361
          +362    NONE = 0
          +363
          +364    PROFILE = 100
          +365    PROFILE_INVENTORIES = 102
          +366    PROFILE_CURRENCIES = 103
          +367    PROFILE_PROGRESSION = 104
          +368    ALL_PROFILES = (
          +369        PROFILE,
          +370        PROFILE_INVENTORIES,
          +371        PROFILE_CURRENCIES,
          +372        PROFILE_PROGRESSION,
          +373    )
          +374    """All profile components."""
          +375
          +376    VENDORS = 400
          +377    VENDOR_SALES = 402
          +378    VENDOR_RECEIPTS = 101
          +379    ALL_VENDORS = (VENDORS, VENDOR_RECEIPTS, VENDOR_SALES)
          +380    """All vendor components."""
          +381
          +382    # Items
          +383    ITEM_INSTANCES = 300
          +384    ITEM_OBJECTIVES = 301
          +385    ITEM_PERKS = 302
          +386    ITEM_RENDER_DATA = 303
          +387    ITEM_STATS = 304
          +388    ITEM_SOCKETS = 305
          +389    ITEM_TALENT_GRINDS = 306
          +390    ITEM_PLUG_STATES = 308
          +391    ITEM_PLUG_OBJECTIVES = 309
          +392    ITEM_REUSABLE_PLUGS = 310
          +393
          +394    ALL_ITEMS = (
          +395        ITEM_PLUG_OBJECTIVES,
          +396        ITEM_PLUG_STATES,
          +397        ITEM_SOCKETS,
          +398        ITEM_INSTANCES,
          +399        ITEM_OBJECTIVES,
          +400        ITEM_PERKS,
          +401        ITEM_RENDER_DATA,
          +402        ITEM_STATS,
          +403        ITEM_TALENT_GRINDS,
          +404        ITEM_REUSABLE_PLUGS,
          +405    )
          +406    """All item components."""
          +407
          +408    PLATFORM_SILVER = 105
          +409    KIOSKS = 500
          +410    CURRENCY_LOOKUPS = 600
          +411    PRESENTATION_NODES = 700
          +412    COLLECTIBLES = 800
          +413    RECORDS = 900
          +414    TRANSITORY = 1000
          +415    METRICS = 1100
          +416    INVENTORIES = 102
          +417    STRING_VARIABLES = 1200
          +418    CRAFTABLES = 1300
          +419
          +420    CHARACTERS = 200
          +421    CHARACTER_INVENTORY = 201
          +422    CHARECTER_PROGRESSION = 202
          +423    CHARACTER_RENDER_DATA = 203
          +424    CHARACTER_ACTIVITIES = 204
          +425    CHARACTER_EQUIPMENT = 205
          +426
          +427    ALL_CHARACTERS = (
          +428        CHARACTERS,
          +429        CHARACTER_INVENTORY,
          +430        CHARECTER_PROGRESSION,
          +431        CHARACTER_RENDER_DATA,
          +432        CHARACTER_ACTIVITIES,
          +433        CHARACTER_EQUIPMENT,
          +434        RECORDS,
          +435    )
          +436    """All character components."""
          +437
          +438    ALL = (
          +439        *ALL_PROFILES,  # type: ignore
          +440        *ALL_CHARACTERS,  # type: ignore
          +441        *ALL_VENDORS,  # type: ignore
          +442        *ALL_ITEMS,  # type: ignore
          +443        RECORDS,
          +444        CURRENCY_LOOKUPS,
          +445        PRESENTATION_NODES,
          +446        COLLECTIBLES,
          +447        KIOSKS,
          +448        METRICS,
          +449        PLATFORM_SILVER,
          +450        INVENTORIES,
          +451        STRING_VARIABLES,
          +452        TRANSITORY,
          +453        CRAFTABLES,
          +454    )
          +455    """ALl components included."""
          +
          -
          -
          + +

          An Enum for Destiny 2 profile Components.

          +
          + + +
          - HEROICADVENTURE = <GameMode.HEROICADVENTURE: 58> + ALL_PROFILES = <ComponentType.ALL_PROFILES: (100, 102, 103, 104)>
          - - + +

          All profile components.

          +
          +
          -
          +
          - SHOWDOWN = <GameMode.SHOWDOWN: 59> + ALL_VENDORS = <ComponentType.ALL_VENDORS: (400, 101, 402)>
          - - + +

          All vendor components.

          +
          +
          -
          +
          - LOCKDOWN = <GameMode.LOCKDOWN: 60> + ALL_ITEMS = <ComponentType.ALL_ITEMS: (309, 308, 305, 300, 301, 302, 303, 304, 306, 310)>
          - - + +

          All item components.

          +
          +
          -
          +
          - SCORCHED = <GameMode.SCORCHED: 61> + ALL_CHARACTERS = <ComponentType.ALL_CHARACTERS: (200, 201, 202, 203, 204, 205, 900)>
          - - + +

          All character components.

          +
          +
          -
          +
          - SCORCHEDTEAM = <GameMode.SCORCHEDTEAM: 62> + ALL = <ComponentType.ALL: (100, 102, 103, 104, 200, 201, 202, 203, 204, 205, 900, 400, 101, 402, 309, 308, 305, 300, 301, 302, 303, 304, 306, 310, 900, 600, 700, 800, 500, 1100, 105, 102, 1200, 1000, 1300)>
          - - + +

          ALl components included.

          +
          -
          -
          -
          - GAMBIT = <GameMode.GAMBIT: 63> - - -
          - - - - -
          -
          -
          - ALLPVECOMPETITIVE = <GameMode.ALLPVECOMPETITIVE: 64> - - -
          - - - - -
          -
          -
          - BREAKTHROUGH = <GameMode.BREAKTHROUGH: 65> - - -
          - - -
          -
          -
          - BLACKARMORYRUN = <GameMode.BLACKARMORYRUN: 66> - - -
          - - - +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          +
          +
          -
          -
          - SALVAGE = <GameMode.SALVAGE: 67> + +
          + +
          +
          @typing.final
          - -
          - - - + class + Planet(builtins.int, Enum): -
          -
          -
          - IRONBANNERSALVAGE = <GameMode.IRONBANNERSALVAGE: 68> + -
          - - - - -
          -
          -
          - PVPCOMPETITIVE = <GameMode.PVPCOMPETITIVE: 69> + +
          195@typing.final
          +196class Planet(int, Enum):
          +197    """An Enum for all available planets in Destiny 2."""
          +198
          +199    UNKNOWN = 0
          +200    """Unknown space"""
          +201
          +202    EARTH = 3747705955
          +203    """Earth"""
          +204
          +205    DREAMING_CITY = 2877881518
          +206    """The Dreaming city."""
          +207
          +208    NESSUS = 3526908984
          +209    """Nessus"""
          +210
          +211    MOON = 3325508439
          +212    """The Moon"""
          +213
          +214    COSMODROME = 3990611421
          +215    """The Cosmodrome"""
          +216
          +217    TANGLED_SHORE = 3821439926
          +218    """The Tangled Shore"""
          +219
          +220    VENUS = 3871070152
          +221    """Venus"""
          +222
          +223    EAZ = 541863059  # Exclusive event.
          +224    """European Aerial Zone"""
          +225
          +226    EUROPA = 1729879943
          +227    """Europa"""
          +
          - -
          - - - -
          -
          -
          - PVPQUICKPLAY = <GameMode.PVPQUICKPLAY: 70> +

          An Enum for all available planets in Destiny 2.

          +
          - -
          - - - -
          -
          +
          - CLASHQUICKPLAY = <GameMode.CLASHQUICKPLAY: 71> + UNKNOWN = <Planet.UNKNOWN: 0>
          - - + +

          Unknown space

          +
          -
          -
          -
          - CLASHCOMPETITIVE = <GameMode.CLASHCOMPETITIVE: 72> - - -
          - - -
          -
          +
          - CONTROLQUICKPLAY = <GameMode.CONTROLQUICKPLAY: 73> + EARTH = <Planet.EARTH: 3747705955>
          - - + +

          Earth

          +
          -
          -
          -
          - CONTROLCOMPETITIVE = <GameMode.CONTROLCOMPETITIVE: 74> - - -
          - - -
          -
          +
          - GAMBITPRIME = <GameMode.GAMBITPRIME: 75> + DREAMING_CITY = <Planet.DREAMING_CITY: 2877881518>
          - - + +

          The Dreaming city.

          +
          -
          -
          -
          - RECKONING = <GameMode.RECKONING: 76> - - -
          - - -
          -
          +
          - MENAGERIE = <GameMode.MENAGERIE: 77> + NESSUS = <Planet.NESSUS: 3526908984>
          - - + +

          Nessus

          +
          -
          -
          -
          - VEXOFFENSIVE = <GameMode.VEXOFFENSIVE: 78> - - -
          - - -
          -
          +
          - NIGHTMAREHUNT = <GameMode.NIGHTMAREHUNT: 79> + MOON = <Planet.MOON: 3325508439>
          - - + +

          The Moon

          +
          -
          -
          -
          - ELIMINATION = <GameMode.ELIMINATION: 80> - - -
          - - -
          -
          +
          - MOMENTUM = <GameMode.MOMENTUM: 81> + COSMODROME = <Planet.COSMODROME: 3990611421>
          - - + +

          The Cosmodrome

          +
          -
          -
          -
          - DUNGEON = <GameMode.DUNGEON: 82> - - -
          - - -
          -
          +
          - SUNDIAL = <GameMode.SUNDIAL: 83> + TANGLED_SHORE = <Planet.TANGLED_SHORE: 3821439926>
          - - + +

          The Tangled Shore

          +
          -
          -
          -
          - TRIALS_OF_OSIRIS = <GameMode.TRIALS_OF_OSIRIS: 84> - - -
          - - -
          -
          +
          - DARES = <GameMode.DARES: 85> + VENUS = <Planet.VENUS: 3871070152>
          - - + +

          Venus

          +
          -
          -
          -
          - OFFENSIVE = <GameMode.OFFENSIVE: 86> - - -
          - - -
          -
          +
          - LOSTSECTOR = <GameMode.LOSTSECTOR: 87> + EAZ = <Planet.EAZ: 541863059>
          - - + +

          European Aerial Zone

          +
          -
          -
          -
          - RIFT = <GameMode.RIFT: 88> - - -
          - - -
          -
          +
          - ZONECONTROL = <GameMode.ZONECONTROL: 89> + EUROPA = <Planet.EUROPA: 1729879943>
          - - + +

          Europa

          +
          -
          -
          -
          - IRONBANNERRIFT = <GameMode.IRONBANNERRIFT: 90> - - -
          - - -
          Inherited Members
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          -
          - +
          +
          @typing.final
          class - MembershipType(builtins.int, Enum): + Stat(builtins.int, Enum): - +
          - -
          463@typing.final
          -464class MembershipType(int, Enum):
          -465    """An Enum for Bungie membership types."""
          -466
          -467    NONE = 0
          -468    XBOX = 1
          -469    PSN = 2
          -470    STEAM = 3
          -471    BLIZZARD = 4
          -472    STADIA = 5
          -473    BUNGIE = 254
          -474    ALL = -1
          +    
          +            
          515@typing.final
          +516class Stat(int, Enum):
          +517    """An Enum for Destiny 2 character stats."""
          +518
          +519    NONE = 0
          +520    MOBILITY = 2996146975
          +521    RESILIENCE = 392767087
          +522    RECOVERY = 1943323491
          +523    DISCIPLINE = 1735777505
          +524    INTELLECT = 144602215
          +525    STRENGTH = 4244567218
          +526    LIGHT_POWER = 1935470627
           
          -

          An Enum for Bungie membership types.

          +

          An Enum for Destiny 2 character stats.

          -
          -
          - NONE = <MembershipType.NONE: 0> - - -
          - - - - -
          -
          -
          - XBOX = <MembershipType.XBOX: 1> +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          - -
          - - - - -
          -
          -
          - PSN = <MembershipType.PSN: 2> - - -
          - - - - -
          -
          -
          - STEAM = <MembershipType.STEAM: 3> - - -
          - - - +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - BLIZZARD = <MembershipType.BLIZZARD: 4> +
          +
          + +
          +
          @typing.final
          - -
          - - - + class + WeaponType(builtins.int, Enum): -
          -
          -
          - STADIA = <MembershipType.STADIA: 5> + -
          - - - - -
          -
          -
          - BUNGIE = <MembershipType.BUNGIE: 254> + +
          529@typing.final
          +530class WeaponType(int, Enum):
          +531    """Enums for The three Destiny Weapon Types"""
          +532
          +533    NONE = 0
          +534    KINETIC = 1498876634
          +535    ENERGY = 2465295065
          +536    POWER = 953998645
          +
          - -
          - - - -
          -
          -
          - ALL = <MembershipType.ALL: -1> +

          Enums for The three Destiny Weapon Types

          +
          - -
          - - - -
          Inherited Members
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          -
          - +
          +
          @typing.final
          class - Class(builtins.int, Enum): + DamageType(builtins.int, Enum): - +
          - -
          477@typing.final
          -478class Class(int, Enum):
          -479    """An Enum for Destiny character classes."""
          -480
          -481    TITAN = 0
          -482    HUNTER = 1
          -483    WARLOCK = 2
          -484    UNKNOWN = 3
          +    
          +            
          539@typing.final
          +540class DamageType(int, Enum):
          +541    """Enums for Destiny Damage types"""
          +542
          +543    NONE = 0
          +544    KINETIC = 1
          +545    ARC = 2
          +546    SOLAR = 3
          +547    VOID = 4
          +548    RAID = 5
          +549    """This is a special damage type reserved for some raid activity encounters."""
          +550    STASIS = 6
           
          -

          An Enum for Destiny character classes.

          +

          Enums for Destiny Damage types

          -
          -
          - TITAN = <Class.TITAN: 0> - - -
          - - - - -
          -
          -
          - HUNTER = <Class.HUNTER: 1> - - -
          - - - - -
          -
          +
          - WARLOCK = <Class.WARLOCK: 2> + RAID = <DamageType.RAID: 5>
          - - + +

          This is a special damage type reserved for some raid activity encounters.

          +
          -
          -
          -
          - UNKNOWN = <Class.UNKNOWN: 3> - - -
          - - -
          Inherited Members
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          -
          - +
          +
          @typing.final
          class - MilestoneType(builtins.int, Enum): + ItemType(builtins.int, Enum): - +
          - -
          506@typing.final
          -507class MilestoneType(int, Enum):
          -508    """An Enum for Destiny 2 milestone types."""
          -509
          -510    UNKNOWN = 0
          -511    TUTORIAL = 1
          -512    ONETIME = 2
          -513    WEEKLY = 3
          -514    DAILY = 4
          -515    SPECIAL = 5
          +    
          +            
          553@typing.final
          +554class ItemType(int, Enum):
          +555    """Enums for Destiny2's item types."""
          +556
          +557    NONE = 0
          +558    CURRENCY = 1
          +559    ARMOR = 2
          +560    WEAPON = 3
          +561    MESSAGE = 7
          +562    ENGRAM = 8
          +563    CONSUMABLE = 9
          +564    EXCHANGEMATERIAL = 10
          +565    MISSIONREWARD = 11
          +566    QUESTSTEP = 12
          +567    QUESTSTEPCOMPLETE = 13
          +568    EMBLEM = 14
          +569    QUEST = 15
          +570    SUBCLASS = 16
          +571    CLANBANNER = 17
          +572    AURA = 18
          +573    MOD = 19
          +574    DUMMY = 20
          +575    SHIP = 21
          +576    VEHICLE = 22
          +577    EMOTE = 23
          +578    GHOST = 24
          +579    PACKAGE = 25
          +580    BOUNTY = 26
          +581    WRAPPER = 27
          +582    SEASONALARTIFACT = 28
          +583    FINISHER = 29
           
          -

          An Enum for Destiny 2 milestone types.

          +

          Enums for Destiny2's item types.

          -
          -
          - UNKNOWN = <MilestoneType.UNKNOWN: 0> - - -
          - - - - -
          -
          -
          - TUTORIAL = <MilestoneType.TUTORIAL: 1> - - -
          - - - - -
          -
          -
          - ONETIME = <MilestoneType.ONETIME: 2> - - -
          - - - - -
          -
          -
          - WEEKLY = <MilestoneType.WEEKLY: 3> - - -
          - - - - -
          -
          -
          - DAILY = <MilestoneType.DAILY: 4> - - -
          - - - - -
          -
          -
          - SPECIAL = <MilestoneType.SPECIAL: 5> - - -
          - - - - -
          Inherited Members
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          -
          - +
          +
          @typing.final
          class - Race(builtins.int, Enum): + Place(builtins.int, Enum): - +
          - -
          496@typing.final
          -497class Race(int, Enum):
          -498    """An Enum for Destiny races."""
          -499
          -500    HUMAN = 0
          -501    AWOKEN = 1
          -502    EXO = 2
          -503    UNKNOWN = 3
          +    
          +            
          230@typing.final
          +231class Place(int, Enum):
          +232    """An Enum for Destiny 2 Places and NOT Planets"""
          +233
          +234    ORBIT = 2961497387
          +235    SOCIAL = 4151112093
          +236    LIGHT_HOUSE = 4276116472
          +237    EXPLORE = 3497767639
           
          -

          An Enum for Destiny races.

          +

          An Enum for Destiny 2 Places and NOT Planets

          -
          -
          - HUMAN = <Race.HUMAN: 0> - - -
          - - - - -
          -
          -
          - AWOKEN = <Race.AWOKEN: 1> - - -
          - - - - -
          -
          -
          - EXO = <Race.EXO: 2> - - -
          - - - - -
          -
          -
          - UNKNOWN = <Race.UNKNOWN: 3> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - Vendor(builtins.int, Enum): - - - -
          - -
          245@typing.final
          -246class Vendor(int, Enum):
          -247    """An Enum for all available vendors in Destiny 2."""
          -248
          -249    ZAVALA = 69482069
          -250    XUR = 2190858386
          -251    BANSHE = 672118013
          -252    SPIDER = 863940356
          -253    SHAXX = 3603221665
          -254    KADI = 529635856
          -255    """Postmaster exo."""
          -256    YUNA = 1796504621
          -257    """Asia servers only."""
          -258    EVERVERSE = 3361454721
          -259    AMANDA = 460529231
          -260    """Amanda holiday"""
          -261    CROW = 3611983588
          -262    HAWTHORNE = 3347378076
          -263    ADA1 = 350061650
          -264    DRIFTER = 248695599
          -265    IKORA = 1976548992
          -266    SAINT = 765357505
          -267    """Saint-14"""
          -268    ERIS_MORN = 1616085565
          -269    SHAW_HAWN = 1816541247
          -270    """COSMODROME Guy"""
          -271    VARIKS = 2531198101
          -
          - - -

          An Enum for all available vendors in Destiny 2.

          -
          - - -
          -
          - ZAVALA = <Vendor.ZAVALA: 69482069> - - -
          - - - - -
          -
          -
          - XUR = <Vendor.XUR: 2190858386> - - -
          - - - - -
          -
          -
          - BANSHE = <Vendor.BANSHE: 672118013> - - -
          - - - - -
          -
          -
          - SPIDER = <Vendor.SPIDER: 863940356> - - -
          - - - - -
          -
          -
          - SHAXX = <Vendor.SHAXX: 3603221665> - - -
          - - - - -
          -
          -
          - KADI = <Vendor.KADI: 529635856> - - -
          - - -

          Postmaster exo.

          -
          - - -
          -
          -
          - YUNA = <Vendor.YUNA: 1796504621> - - -
          - - -

          Asia servers only.

          -
          - - -
          -
          -
          - EVERVERSE = <Vendor.EVERVERSE: 3361454721> - - -
          - - - - -
          -
          -
          - AMANDA = <Vendor.AMANDA: 460529231> - - -
          - - -

          Amanda holiday

          -
          - - -
          -
          -
          - CROW = <Vendor.CROW: 3611983588> - - -
          - - - - -
          -
          -
          - HAWTHORNE = <Vendor.HAWTHORNE: 3347378076> - - -
          - - - - -
          -
          -
          - ADA1 = <Vendor.ADA1: 350061650> - - -
          - - - - -
          -
          -
          - DRIFTER = <Vendor.DRIFTER: 248695599> - - -
          - - - - -
          -
          -
          - IKORA = <Vendor.IKORA: 1976548992> - - -
          - - - - -
          -
          -
          - SAINT = <Vendor.SAINT: 765357505> - - -
          - - -

          Saint-14

          -
          - - -
          -
          -
          - ERIS_MORN = <Vendor.ERIS_MORN: 1616085565> - - -
          - - - - -
          -
          -
          - SHAW_HAWN = <Vendor.SHAW_HAWN: 1816541247> - - -
          - - -

          COSMODROME Guy

          -
          - - -
          -
          -
          - VARIKS = <Vendor.VARIKS: 2531198101> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - Raid(builtins.int, Enum): - - - -
          - -
          148@typing.final
          -149class Raid(int, Enum):
          -150    """An Enum for all available raids in Destiny 2."""
          -151
          -152    DSC = 910380154
          -153    """Deep Stone Crypt"""
          -154
          -155    LW = 2122313384
          -156    """Last Wish"""
          -157
          -158    VOG = 3881495763
          -159    """Normal Valut of Glass"""
          -160
          -161    GOS = 3458480158
          -162    """Garden Of Salvation"""
          -
          - - -

          An Enum for all available raids in Destiny 2.

          -
          - - -
          -
          - DSC = <Raid.DSC: 910380154> - - -
          - - -

          Deep Stone Crypt

          -
          - - -
          -
          -
          - LW = <Raid.LW: 2122313384> - - -
          - - -

          Last Wish

          -
          - - -
          -
          -
          - VOG = <Raid.VOG: 3881495763> - - -
          - - -

          Normal Valut of Glass

          -
          - - -
          -
          -
          - GOS = <Raid.GOS: 3458480158> - - -
          - - -

          Garden Of Salvation

          -
          - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - Dungeon(builtins.int, Enum): - - - -
          - -
          165@typing.final
          -166class Dungeon(int, Enum):
          -167    """An Enum for all available Dungeon/Like missions in Destiny 2."""
          -168
          -169    NORMAL_PRESAGE = 2124066889
          -170    """Normal Presage"""
          -171
          -172    MASTER_PRESAGE = 4212753278
          -173    """Master Presage"""
          -174
          -175    HARBINGER = 1738383283
          -176    """Harbinger"""
          -177
          -178    PROPHECY = 4148187374
          -179    """Prophecy"""
          -180
          -181    MASTER_POH = 785700673
          -182    """Master Pit of Heresy?"""
          -183
          -184    LEGEND_POH = 785700678
          -185    """Legend Pit of Heresy?"""
          -186
          -187    POH = 1375089621
          -188    """Normal Pit of Heresy."""
          -189
          -190    SHATTERED = 2032534090
          -191    """Shattered Throne"""
          -192
          -193    GOA_LEGEND = 4078656646
          -194    """Grasp of Avarice legend."""
          -195
          -196    GOA_MASTER = 3774021532
          -197    """Grasp of Avarice master."""
          -
          - - -

          An Enum for all available Dungeon/Like missions in Destiny 2.

          -
          - - -
          -
          - NORMAL_PRESAGE = <Dungeon.NORMAL_PRESAGE: 2124066889> - - -
          - - -

          Normal Presage

          -
          - - -
          -
          -
          - MASTER_PRESAGE = <Dungeon.MASTER_PRESAGE: 4212753278> - - -
          - - -

          Master Presage

          -
          - - -
          -
          -
          - HARBINGER = <Dungeon.HARBINGER: 1738383283> - - -
          - - -

          Harbinger

          -
          - - -
          -
          -
          - PROPHECY = <Dungeon.PROPHECY: 4148187374> - - -
          - - -

          Prophecy

          -
          - - -
          -
          -
          - MASTER_POH = <Dungeon.MASTER_POH: 785700673> - - -
          - - -

          Master Pit of Heresy?

          -
          - - -
          -
          -
          - LEGEND_POH = <Dungeon.LEGEND_POH: 785700678> - - -
          - - -

          Legend Pit of Heresy?

          -
          - - -
          -
          -
          - POH = <Dungeon.POH: 1375089621> - - -
          - - -

          Normal Pit of Heresy.

          -
          - - -
          -
          -
          - SHATTERED = <Dungeon.SHATTERED: 2032534090> - - -
          - - -

          Shattered Throne

          -
          - - -
          -
          -
          - GOA_LEGEND = <Dungeon.GOA_LEGEND: 4078656646> - - -
          - - -

          Grasp of Avarice legend.

          -
          - - -
          -
          -
          - GOA_MASTER = <Dungeon.GOA_MASTER: 3774021532> - - -
          - - -

          Grasp of Avarice master.

          -
          - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - Gender(builtins.int, Enum): - - - -
          - -
          487@typing.final
          -488class Gender(int, Enum):
          -489    """An Enum for Destiny Genders."""
          -490
          -491    MALE = 0
          -492    FEMALE = 1
          -493    UNKNOWN = 2
          -
          - - -

          An Enum for Destiny Genders.

          -
          - - -
          -
          - MALE = <Gender.MALE: 0> - - -
          - - - - -
          -
          -
          - FEMALE = <Gender.FEMALE: 1> - - -
          - - - - -
          -
          -
          - UNKNOWN = <Gender.UNKNOWN: 2> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - ComponentType(Enum): - - - -
          - -
          363@typing.final
          -364class ComponentType(Enum):
          -365    """An Enum for Destiny 2 profile Components."""
          -366
          -367    NONE = 0
          -368
          -369    PROFILE = 100
          -370    PROFILE_INVENTORIES = 102
          -371    PROFILE_CURRENCIES = 103
          -372    PROFILE_PROGRESSION = 104
          -373    ALL_PROFILES = (
          -374        PROFILE,
          -375        PROFILE_INVENTORIES,
          -376        PROFILE_CURRENCIES,
          -377        PROFILE_PROGRESSION,
          -378    )
          -379    """All profile components."""
          -380
          -381    VENDORS = 400
          -382    VENDOR_SALES = 402
          -383    VENDOR_RECEIPTS = 101
          -384    ALL_VENDORS = (VENDORS, VENDOR_RECEIPTS, VENDOR_SALES)
          -385    """All vendor components."""
          -386
          -387    # Items
          -388    ITEM_INSTANCES = 300
          -389    ITEM_OBJECTIVES = 301
          -390    ITEM_PERKS = 302
          -391    ITEM_RENDER_DATA = 303
          -392    ITEM_STATS = 304
          -393    ITEM_SOCKETS = 305
          -394    ITEM_TALENT_GRINDS = 306
          -395    ITEM_PLUG_STATES = 308
          -396    ITEM_PLUG_OBJECTIVES = 309
          -397    ITEM_REUSABLE_PLUGS = 310
          -398
          -399    ALL_ITEMS = (
          -400        ITEM_PLUG_OBJECTIVES,
          -401        ITEM_PLUG_STATES,
          -402        ITEM_SOCKETS,
          -403        ITEM_INSTANCES,
          -404        ITEM_OBJECTIVES,
          -405        ITEM_PERKS,
          -406        ITEM_RENDER_DATA,
          -407        ITEM_STATS,
          -408        ITEM_TALENT_GRINDS,
          -409        ITEM_REUSABLE_PLUGS,
          -410    )
          -411    """All item components."""
          -412
          -413    PLATFORM_SILVER = 105
          -414    KIOSKS = 500
          -415    CURRENCY_LOOKUPS = 600
          -416    PRESENTATION_NODES = 700
          -417    COLLECTIBLES = 800
          -418    RECORDS = 900
          -419    TRANSITORY = 1000
          -420    METRICS = 1100
          -421    INVENTORIES = 102
          -422    STRING_VARIABLES = 1200
          -423    CRAFTABLES = 1300
          -424
          -425    CHARACTERS = 200
          -426    CHARACTER_INVENTORY = 201
          -427    CHARECTER_PROGRESSION = 202
          -428    CHARACTER_RENDER_DATA = 203
          -429    CHARACTER_ACTIVITIES = 204
          -430    CHARACTER_EQUIPMENT = 205
          -431
          -432    ALL_CHARACTERS = (
          -433        CHARACTERS,
          -434        CHARACTER_INVENTORY,
          -435        CHARECTER_PROGRESSION,
          -436        CHARACTER_RENDER_DATA,
          -437        CHARACTER_ACTIVITIES,
          -438        CHARACTER_EQUIPMENT,
          -439        RECORDS,
          -440    )
          -441    """All character components."""
          -442
          -443    ALL = (
          -444        *ALL_PROFILES,  # type: ignore
          -445        *ALL_CHARACTERS,  # type: ignore
          -446        *ALL_VENDORS,  # type: ignore
          -447        *ALL_ITEMS,  # type: ignore
          -448        RECORDS,
          -449        CURRENCY_LOOKUPS,
          -450        PRESENTATION_NODES,
          -451        COLLECTIBLES,
          -452        KIOSKS,
          -453        METRICS,
          -454        PLATFORM_SILVER,
          -455        INVENTORIES,
          -456        STRING_VARIABLES,
          -457        TRANSITORY,
          -458        CRAFTABLES,
          -459    )
          -460    """ALl components included."""
          -
          - - -

          An Enum for Destiny 2 profile Components.

          -
          - - -
          -
          - NONE = <ComponentType.NONE: 0> - - -
          - - - - -
          -
          -
          - PROFILE = <ComponentType.PROFILE: 100> - - -
          - - - - -
          -
          -
          - PROFILE_INVENTORIES = <ComponentType.PROFILE_INVENTORIES: 102> - - -
          - - - - -
          -
          -
          - PROFILE_CURRENCIES = <ComponentType.PROFILE_CURRENCIES: 103> - - -
          - - - - -
          -
          -
          - PROFILE_PROGRESSION = <ComponentType.PROFILE_PROGRESSION: 104> - - -
          - - - - -
          -
          -
          - ALL_PROFILES = <ComponentType.ALL_PROFILES: (100, 102, 103, 104)> - - -
          - - -

          All profile components.

          -
          - - -
          -
          -
          - VENDORS = <ComponentType.VENDORS: 400> - - -
          - - - - -
          -
          -
          - VENDOR_SALES = <ComponentType.VENDOR_SALES: 402> - - -
          - - - - -
          -
          -
          - VENDOR_RECEIPTS = <ComponentType.VENDOR_RECEIPTS: 101> - - -
          - - - - -
          -
          -
          - ALL_VENDORS = <ComponentType.ALL_VENDORS: (400, 101, 402)> - - -
          - - -

          All vendor components.

          -
          - - -
          -
          -
          - ITEM_INSTANCES = <ComponentType.ITEM_INSTANCES: 300> - - -
          - - - - -
          -
          -
          - ITEM_OBJECTIVES = <ComponentType.ITEM_OBJECTIVES: 301> - - -
          - - - - -
          -
          -
          - ITEM_PERKS = <ComponentType.ITEM_PERKS: 302> - - -
          - - - - -
          -
          -
          - ITEM_RENDER_DATA = <ComponentType.ITEM_RENDER_DATA: 303> - - -
          - - - - -
          -
          -
          - ITEM_STATS = <ComponentType.ITEM_STATS: 304> - - -
          - - - - -
          -
          -
          - ITEM_SOCKETS = <ComponentType.ITEM_SOCKETS: 305> - - -
          - - - - -
          -
          -
          - ITEM_TALENT_GRINDS = <ComponentType.ITEM_TALENT_GRINDS: 306> - - -
          - - - - -
          -
          -
          - ITEM_PLUG_STATES = <ComponentType.ITEM_PLUG_STATES: 308> - - -
          - - - - -
          -
          -
          - ITEM_PLUG_OBJECTIVES = <ComponentType.ITEM_PLUG_OBJECTIVES: 309> - - -
          - - - - -
          -
          -
          - ITEM_REUSABLE_PLUGS = <ComponentType.ITEM_REUSABLE_PLUGS: 310> - - -
          - - - - -
          -
          -
          - ALL_ITEMS = <ComponentType.ALL_ITEMS: (309, 308, 305, 300, 301, 302, 303, 304, 306, 310)> - - -
          - - -

          All item components.

          -
          - - -
          -
          -
          - PLATFORM_SILVER = <ComponentType.PLATFORM_SILVER: 105> - - -
          - - - - -
          -
          -
          - KIOSKS = <ComponentType.KIOSKS: 500> - - -
          - - - - -
          -
          -
          - CURRENCY_LOOKUPS = <ComponentType.CURRENCY_LOOKUPS: 600> - - -
          - - - - -
          -
          -
          - PRESENTATION_NODES = <ComponentType.PRESENTATION_NODES: 700> - - -
          - - - - -
          -
          -
          - COLLECTIBLES = <ComponentType.COLLECTIBLES: 800> - - -
          - - - - -
          -
          -
          - RECORDS = <ComponentType.RECORDS: 900> - - -
          - - - - -
          -
          -
          - TRANSITORY = <ComponentType.TRANSITORY: 1000> - - -
          - - - - -
          -
          -
          - METRICS = <ComponentType.METRICS: 1100> - - -
          - - - - -
          -
          -
          - INVENTORIES = <ComponentType.PROFILE_INVENTORIES: 102> - - -
          - - - - -
          -
          -
          - STRING_VARIABLES = <ComponentType.STRING_VARIABLES: 1200> - - -
          - - - - -
          -
          -
          - CRAFTABLES = <ComponentType.CRAFTABLES: 1300> - - -
          - - - - -
          -
          -
          - CHARACTERS = <ComponentType.CHARACTERS: 200> - - -
          - - - - -
          -
          -
          - CHARACTER_INVENTORY = <ComponentType.CHARACTER_INVENTORY: 201> - - -
          - - - - -
          -
          -
          - CHARECTER_PROGRESSION = <ComponentType.CHARECTER_PROGRESSION: 202> - - -
          - - - - -
          -
          -
          - CHARACTER_RENDER_DATA = <ComponentType.CHARACTER_RENDER_DATA: 203> - - -
          - - - - -
          -
          -
          - CHARACTER_ACTIVITIES = <ComponentType.CHARACTER_ACTIVITIES: 204> - - -
          - - - - -
          -
          -
          - CHARACTER_EQUIPMENT = <ComponentType.CHARACTER_EQUIPMENT: 205> - - -
          - - - - -
          -
          -
          - ALL_CHARACTERS = <ComponentType.ALL_CHARACTERS: (200, 201, 202, 203, 204, 205, 900)> - - -
          - - -

          All character components.

          -
          - - -
          -
          -
          - ALL = <ComponentType.ALL: (100, 102, 103, 104, 200, 201, 202, 203, 204, 205, 900, 400, 101, 402, 309, 308, 305, 300, 301, 302, 303, 304, 306, 310, 900, 600, 700, 800, 500, 1100, 105, 102, 1200, 1000, 1300)> - - -
          - - -

          ALl components included.

          -
          - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - Planet(builtins.int, Enum): - - - -
          - -
          200@typing.final
          -201class Planet(int, Enum):
          -202    """An Enum for all available planets in Destiny 2."""
          -203
          -204    UNKNOWN = 0
          -205    """Unknown space"""
          -206
          -207    EARTH = 3747705955
          -208    """Earth"""
          -209
          -210    DREAMING_CITY = 2877881518
          -211    """The Dreaming city."""
          -212
          -213    NESSUS = 3526908984
          -214    """Nessus"""
          -215
          -216    MOON = 3325508439
          -217    """The Moon"""
          -218
          -219    COSMODROME = 3990611421
          -220    """The Cosmodrome"""
          -221
          -222    TANGLED_SHORE = 3821439926
          -223    """The Tangled Shore"""
          -224
          -225    VENUS = 3871070152
          -226    """Venus"""
          -227
          -228    EAZ = 541863059  # Exclusive event.
          -229    """European Aerial Zone"""
          -230
          -231    EUROPA = 1729879943
          -232    """Europa"""
          -
          - - -

          An Enum for all available planets in Destiny 2.

          -
          - - -
          -
          - UNKNOWN = <Planet.UNKNOWN: 0> - - -
          - - -

          Unknown space

          -
          - - -
          -
          -
          - EARTH = <Planet.EARTH: 3747705955> - - -
          - - -

          Earth

          -
          - - -
          -
          -
          - DREAMING_CITY = <Planet.DREAMING_CITY: 2877881518> - - -
          - - -

          The Dreaming city.

          -
          - - -
          -
          -
          - NESSUS = <Planet.NESSUS: 3526908984> - - -
          - - -

          Nessus

          -
          - - -
          -
          -
          - MOON = <Planet.MOON: 3325508439> - - -
          - - -

          The Moon

          -
          - - -
          -
          -
          - COSMODROME = <Planet.COSMODROME: 3990611421> - - -
          - - -

          The Cosmodrome

          -
          - - -
          -
          -
          - TANGLED_SHORE = <Planet.TANGLED_SHORE: 3821439926> - - -
          - - -

          The Tangled Shore

          -
          - - -
          -
          -
          - VENUS = <Planet.VENUS: 3871070152> - - -
          - - -

          Venus

          -
          - - -
          -
          -
          - EAZ = <Planet.EAZ: 541863059> - - -
          - - -

          European Aerial Zone

          -
          - - -
          -
          -
          - EUROPA = <Planet.EUROPA: 1729879943> - - -
          - - -

          Europa

          -
          - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - Stat(builtins.int, Enum): - - - -
          - -
          518@typing.final
          -519class Stat(int, Enum):
          -520    """An Enum for Destiny 2 character stats."""
          -521
          -522    NONE = 0
          -523    MOBILITY = 2996146975
          -524    RESILIENCE = 392767087
          -525    RECOVERY = 1943323491
          -526    DISCIPLINE = 1735777505
          -527    INTELLECT = 144602215
          -528    STRENGTH = 4244567218
          -529    LIGHT_POWER = 1935470627
          -
          - - -

          An Enum for Destiny 2 character stats.

          -
          - - -
          -
          - NONE = <Stat.NONE: 0> - - -
          - - - - -
          -
          -
          - MOBILITY = <Stat.MOBILITY: 2996146975> - - -
          - - - - -
          -
          -
          - RESILIENCE = <Stat.RESILIENCE: 392767087> - - -
          - - - - -
          -
          -
          - RECOVERY = <Stat.RECOVERY: 1943323491> - - -
          - - - - -
          -
          -
          - DISCIPLINE = <Stat.DISCIPLINE: 1735777505> - - -
          - - - - -
          -
          -
          - INTELLECT = <Stat.INTELLECT: 144602215> - - -
          - - - - -
          -
          -
          - STRENGTH = <Stat.STRENGTH: 4244567218> - - -
          - - - - -
          -
          -
          - LIGHT_POWER = <Stat.LIGHT_POWER: 1935470627> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - WeaponType(builtins.int, Enum): - - - -
          - -
          532@typing.final
          -533class WeaponType(int, Enum):
          -534    """Enums for The three Destiny Weapon Types"""
          -535
          -536    NONE = 0
          -537    KINETIC = 1498876634
          -538    ENERGY = 2465295065
          -539    POWER = 953998645
          -
          - - -

          Enums for The three Destiny Weapon Types

          -
          - - -
          -
          - NONE = <WeaponType.NONE: 0> - - -
          - - - - -
          -
          -
          - KINETIC = <WeaponType.KINETIC: 1498876634> - - -
          - - - - -
          -
          -
          - ENERGY = <WeaponType.ENERGY: 2465295065> - - -
          - - - - -
          -
          -
          - POWER = <WeaponType.POWER: 953998645> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - DamageType(builtins.int, Enum): - - - -
          - -
          542@typing.final
          -543class DamageType(int, Enum):
          -544    """Enums for Destiny Damage types"""
          -545
          -546    NONE = 0
          -547    KINETIC = 1
          -548    ARC = 2
          -549    SOLAR = 3
          -550    VOID = 4
          -551    RAID = 5
          -552    """This is a special damage type reserved for some raid activity encounters."""
          -553    STASIS = 6
          -
          - - -

          Enums for Destiny Damage types

          -
          - - -
          -
          - NONE = <DamageType.NONE: 0> - - -
          - - - - -
          -
          -
          - KINETIC = <DamageType.KINETIC: 1> - - -
          - - - - -
          -
          -
          - ARC = <DamageType.ARC: 2> - - -
          - - - - -
          -
          -
          - SOLAR = <DamageType.SOLAR: 3> - - -
          - - - - -
          -
          -
          - VOID = <DamageType.VOID: 4> - - -
          - - - - -
          -
          -
          - RAID = <DamageType.RAID: 5> - - -
          - - -

          This is a special damage type reserved for some raid activity encounters.

          -
          - - -
          -
          -
          - STASIS = <DamageType.STASIS: 6> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - ItemType(builtins.int, Enum): - - - -
          - -
          556@typing.final
          -557class ItemType(int, Enum):
          -558    """Enums for Destiny2's item types."""
          -559
          -560    NONE = 0
          -561    CURRENCY = 1
          -562    ARMOR = 2
          -563    WEAPON = 3
          -564    MESSAGE = 7
          -565    ENGRAM = 8
          -566    CONSUMABLE = 9
          -567    EXCHANGEMATERIAL = 10
          -568    MISSIONREWARD = 11
          -569    QUESTSTEP = 12
          -570    QUESTSTEPCOMPLETE = 13
          -571    EMBLEM = 14
          -572    QUEST = 15
          -573    SUBCLASS = 16
          -574    CLANBANNER = 17
          -575    AURA = 18
          -576    MOD = 19
          -577    DUMMY = 20
          -578    SHIP = 21
          -579    VEHICLE = 22
          -580    EMOTE = 23
          -581    GHOST = 24
          -582    PACKAGE = 25
          -583    BOUNTY = 26
          -584    WRAPPER = 27
          -585    SEASONALARTIFACT = 28
          -586    FINISHER = 29
          -
          - - -

          Enums for Destiny2's item types.

          -
          - - -
          -
          - NONE = <ItemType.NONE: 0> - - -
          - - - - -
          -
          -
          - CURRENCY = <ItemType.CURRENCY: 1> - - -
          - - - - -
          -
          -
          - ARMOR = <ItemType.ARMOR: 2> - - -
          - - - - -
          -
          -
          - WEAPON = <ItemType.WEAPON: 3> - - -
          - - - - -
          -
          -
          - MESSAGE = <ItemType.MESSAGE: 7> - - -
          - - - - -
          -
          -
          - ENGRAM = <ItemType.ENGRAM: 8> - - -
          - - - - -
          -
          -
          - CONSUMABLE = <ItemType.CONSUMABLE: 9> - - -
          - - - - -
          -
          -
          - EXCHANGEMATERIAL = <ItemType.EXCHANGEMATERIAL: 10> - - -
          - - - - -
          -
          -
          - MISSIONREWARD = <ItemType.MISSIONREWARD: 11> - - -
          - - - - -
          -
          -
          - QUESTSTEP = <ItemType.QUESTSTEP: 12> - - -
          - - - - -
          -
          -
          - QUESTSTEPCOMPLETE = <ItemType.QUESTSTEPCOMPLETE: 13> - - -
          - - - - -
          -
          -
          - EMBLEM = <ItemType.EMBLEM: 14> - - -
          - - - - -
          -
          -
          - QUEST = <ItemType.QUEST: 15> - - -
          - - - - -
          -
          -
          - SUBCLASS = <ItemType.SUBCLASS: 16> - - -
          - - - - -
          -
          -
          - CLANBANNER = <ItemType.CLANBANNER: 17> - - -
          - - - - -
          -
          -
          - AURA = <ItemType.AURA: 18> - - -
          - - - - -
          -
          -
          - MOD = <ItemType.MOD: 19> - - -
          - - - - -
          -
          -
          - DUMMY = <ItemType.DUMMY: 20> - - -
          - - - - -
          -
          -
          - SHIP = <ItemType.SHIP: 21> - - -
          - - - - -
          -
          -
          - VEHICLE = <ItemType.VEHICLE: 22> - - -
          - - - - -
          -
          -
          - EMOTE = <ItemType.EMOTE: 23> - - -
          - - - - -
          -
          -
          - GHOST = <ItemType.GHOST: 24> - - -
          - - - - -
          -
          -
          - PACKAGE = <ItemType.PACKAGE: 25> - - -
          - - - - -
          -
          -
          - BOUNTY = <ItemType.BOUNTY: 26> - - -
          - - - - -
          -
          -
          - WRAPPER = <ItemType.WRAPPER: 27> - - -
          - - - - -
          -
          -
          - SEASONALARTIFACT = <ItemType.SEASONALARTIFACT: 28> - - -
          - - - - -
          -
          -
          - FINISHER = <ItemType.FINISHER: 29> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - Place(builtins.int, Enum): - - - -
          - -
          235@typing.final
          -236class Place(int, Enum):
          -237    """An Enum for Destiny 2 Places and NOT Planets"""
          -238
          -239    ORBIT = 2961497387
          -240    SOCIAL = 4151112093
          -241    LIGHT_HOUSE = 4276116472
          -242    EXPLORE = 3497767639
          -
          - - -

          An Enum for Destiny 2 Places and NOT Planets

          -
          - - -
          -
          - ORBIT = <Place.ORBIT: 2961497387> - - -
          - - - - -
          -
          -
          - SOCIAL = <Place.SOCIAL: 4151112093> - - -
          - - - - -
          -
          -
          - LIGHT_HOUSE = <Place.LIGHT_HOUSE: 4276116472> - - -
          - - - - -
          -
          -
          - EXPLORE = <Place.EXPLORE: 3497767639> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - ItemTier(builtins.int, Enum): - - - -
          - -
          621@typing.final
          -622class ItemTier(int, Enum):
          -623    """An enum for a Destiny 2 item tier."""
          -624
          -625    NONE = 0
          -626    BASIC = 3340296461
          -627    COMMON = 2395677314
          -628    RARE = 2127292149
          -629    LEGENDERY = 4008398120
          -630    EXOTIC = 2759499571
          -
          - - -

          An enum for a Destiny 2 item tier.

          -
          - - -
          -
          - NONE = <ItemTier.NONE: 0> - - -
          - - - - -
          -
          -
          - BASIC = <ItemTier.BASIC: 3340296461> - - -
          - - - - -
          -
          -
          - COMMON = <ItemTier.COMMON: 2395677314> - - -
          - - - - -
          -
          -
          - RARE = <ItemTier.RARE: 2127292149> - - -
          - - - - -
          -
          -
          - LEGENDERY = <ItemTier.LEGENDERY: 4008398120> - - -
          - - - - -
          -
          -
          - EXOTIC = <ItemTier.EXOTIC: 2759499571> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - AmmoType(builtins.int, Enum): - - - -
          - -
          646@typing.final
          -647class AmmoType(int, Enum):
          -648    """AN enum for Detyiny 2 ammo types."""
          -649
          -650    NONE = 0
          -651    PRIMARY = 1
          -652    SPECIAL = 2
          -653    HEAVY = 3
          -
          - - -

          AN enum for Detyiny 2 ammo types.

          -
          - - -
          -
          - NONE = <AmmoType.NONE: 0> - - -
          - - - - -
          -
          -
          - PRIMARY = <AmmoType.PRIMARY: 1> - - -
          - - - - -
          -
          -
          - SPECIAL = <AmmoType.SPECIAL: 2> - - -
          - - - - -
          -
          -
          - HEAVY = <AmmoType.HEAVY: 3> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - GroupType(builtins.int, Enum): - - - -
          - -
          656@typing.final
          -657class GroupType(int, Enum):
          -658    """An enums for the known bungie group types."""
          -659
          -660    GENERAL = 0
          -661    CLAN = 1
          -
          - - -

          An enums for the known bungie group types.

          -
          - - -
          -
          - GENERAL = <GroupType.GENERAL: 0> - - -
          - - - - -
          -
          -
          - CLAN = <GroupType.CLAN: 1> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - CredentialType(builtins.int, Enum): - - - -
          - -
          664@typing.final
          -665class CredentialType(int, Enum):
          -666    """The types of the accounts system supports at bungie."""
          -667
          -668    NONE = 0
          -669    XUID = 1
          -670    PSNID = 2
          -671    WILD = 3
          -672    FAKE = 4
          -673    FACEBOOK = 5
          -674    GOOGLE = 8
          -675    WINDOWS = 9
          -676    DEMONID = 10
          -677    STEAMID = 12
          -678    BATTLENETID = 14
          -679    STADIAID = 16
          -680    TWITCHID = 18
          -
          - - -

          The types of the accounts system supports at bungie.

          -
          - - -
          -
          - NONE = <CredentialType.NONE: 0> - - -
          - - - - -
          -
          -
          - XUID = <CredentialType.XUID: 1> - - -
          - - - - -
          -
          -
          - PSNID = <CredentialType.PSNID: 2> - - -
          - - - - -
          -
          -
          - WILD = <CredentialType.WILD: 3> - - -
          - - - - -
          -
          -
          - FAKE = <CredentialType.FAKE: 4> - - -
          - - - - -
          -
          -
          - FACEBOOK = <CredentialType.FACEBOOK: 5> - - -
          - - - - -
          -
          -
          - GOOGLE = <CredentialType.GOOGLE: 8> - - -
          - - - - -
          -
          -
          - WINDOWS = <CredentialType.WINDOWS: 9> - - -
          - - - - -
          -
          -
          - DEMONID = <CredentialType.DEMONID: 10> - - -
          - - - - -
          -
          -
          - STEAMID = <CredentialType.STEAMID: 12> - - -
          - - - - -
          -
          -
          - BATTLENETID = <CredentialType.BATTLENETID: 14> - - -
          - - - - -
          -
          -
          - STADIAID = <CredentialType.STADIAID: 16> - - -
          - - - - -
          -
          -
          - TWITCHID = <CredentialType.TWITCHID: 18> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - Presence(builtins.int, Enum): - - - -
          - -
          683@typing.final
          -684class Presence(int, Enum):
          -685    """An enum for a bungie friend status."""
          -686
          -687    OFFLINE_OR_UNKNOWN = 0
          -688    ONLINE = 1
          -
          - - -

          An enum for a bungie friend status.

          -
          - - -
          -
          - OFFLINE_OR_UNKNOWN = <Presence.OFFLINE_OR_UNKNOWN: 0> - - -
          - - - - -
          -
          -
          - ONLINE = <Presence.ONLINE: 1> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - Relationship(builtins.int, Enum): - - - -
          - -
          691@typing.final
          -692class Relationship(int, Enum):
          -693    """An enum for bungie friends relationship types."""
          -694
          -695    UNKNOWN = 0
          -696    FRIEND = 1
          -697    INCOMING_REQUEST = 2
          -698    OUTGOING_REQUEST = 3
          -
          - - -

          An enum for bungie friends relationship types.

          -
          - - -
          -
          - UNKNOWN = <Relationship.UNKNOWN: 0> - - -
          - - - - -
          -
          -
          - FRIEND = <Relationship.FRIEND: 1> - - -
          - - - - -
          -
          -
          - INCOMING_REQUEST = <Relationship.INCOMING_REQUEST: 2> - - -
          - - - - -
          -
          -
          - OUTGOING_REQUEST = <Relationship.OUTGOING_REQUEST: 3> - - -
          - - - - -
          -
          -
          Inherited Members
          -
          -
          Enum
          -
          name
          -
          value
          - -
          -
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          - -
          -
          -
          -
          -
          - -
          -
          @typing.final
          - - class - ClanMemberType(builtins.int, Enum): - - - -
          - -
          701@typing.final
          -702class ClanMemberType(int, Enum):
          -703    """An enum for bungie clan member types."""
          -704
          -705    NONE = 0
          -706    BEGINNER = 1
          -707    MEMBER = 2
          -708    ADMIN = 3
          -709    ACTING_FOUNDER = 4
          -710    FOUNDER = 5
          -
          - - -

          An enum for bungie clan member types.

          -
          - - -
          -
          - NONE = <ClanMemberType.NONE: 0> - - -
          - - - - -
          -
          -
          - BEGINNER = <ClanMemberType.BEGINNER: 1> - - -
          - - - - -
          -
          -
          - MEMBER = <ClanMemberType.MEMBER: 2> - - -
          - - - - -
          -
          -
          - ADMIN = <ClanMemberType.ADMIN: 3> - - -
          - - - - -
          -
          -
          - ACTING_FOUNDER = <ClanMemberType.ACTING_FOUNDER: 4> - - -
          - - - - -
          -
          -
          - FOUNDER = <ClanMemberType.FOUNDER: 5> - - -
          - - - - -
          Inherited Members
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          -
          - +
          +
          @typing.final
          class - MembershipOption(builtins.int, Enum): + ItemTier(builtins.int, Enum): - +
          - -
          713@typing.final
          -714class MembershipOption(int, Enum):
          -715    """A enum for GroupV2 membership options."""
          -716
          -717    REVIEWD = 0
          -718    OPEN = 1
          -719    CLOSED = 2
          +    
          +            
          618@typing.final
          +619class ItemTier(int, Enum):
          +620    """An enum for a Destiny 2 item tier."""
          +621
          +622    NONE = 0
          +623    BASIC = 3340296461
          +624    COMMON = 2395677314
          +625    RARE = 2127292149
          +626    LEGENDERY = 4008398120
          +627    EXOTIC = 2759499571
           
          -

          A enum for GroupV2 membership options.

          +

          An enum for a Destiny 2 item tier.

          -
          -
          - REVIEWD = <MembershipOption.REVIEWD: 0> - - -
          - - - - -
          -
          -
          - OPEN = <MembershipOption.OPEN: 1> - - -
          - - - - -
          -
          -
          - CLOSED = <MembershipOption.CLOSED: 2> - - -
          - - - - -
          Inherited Members
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          -
          - +
          +
          @typing.final
          class - ItemBindStatus(builtins.int, Enum): + AmmoType(builtins.int, Enum): - +
          - -
          722@typing.final
          -723class ItemBindStatus(int, Enum):
          -724    """An enum for Destiny 2 items bind status."""
          -725
          -726    NOT_BOUND = 0
          -727    BOUND_TO_CHARACTER = 1
          -728    BOUND_TO_ACCOUNT = 2
          -729    BOUNT_TO_GUILD = 3
          +    
          +            
          643@typing.final
          +644class AmmoType(int, Enum):
          +645    """AN enum for Detyiny 2 ammo types."""
          +646
          +647    NONE = 0
          +648    PRIMARY = 1
          +649    SPECIAL = 2
          +650    HEAVY = 3
           
          -

          An enum for Destiny 2 items bind status.

          +

          AN enum for Detyiny 2 ammo types.

          -
          -
          - NOT_BOUND = <ItemBindStatus.NOT_BOUND: 0> - - -
          - - - - -
          -
          -
          - BOUND_TO_CHARACTER = <ItemBindStatus.BOUND_TO_CHARACTER: 1> - - -
          - - - - -
          -
          -
          - BOUND_TO_ACCOUNT = <ItemBindStatus.BOUND_TO_ACCOUNT: 2> - - -
          - - - - -
          -
          -
          - BOUNT_TO_GUILD = <ItemBindStatus.BOUNT_TO_GUILD: 3> - - -
          - - - - -
          Inherited Members
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          -
          - +
          +
          @typing.final
          class - ItemLocation(builtins.int, Enum): + GroupType(builtins.int, Enum): - +
          - -
          732@typing.final
          -733class ItemLocation(int, Enum):
          -734    """An enum for Destiny 2 items location."""
          -735
          -736    UNKNOWN = 0
          -737    INVENTORY = 1
          -738    VAULT = 2
          -739    VENDOR = 3
          -740    POSTMASTER = 4
          +    
          +            
          653@typing.final
          +654class GroupType(int, Enum):
          +655    """An enums for the known bungie group types."""
          +656
          +657    GENERAL = 0
          +658    CLAN = 1
           
          -

          An enum for Destiny 2 items location.

          -
          - - -
          -
          - UNKNOWN = <ItemLocation.UNKNOWN: 0> - - -
          - - - - -
          -
          -
          - INVENTORY = <ItemLocation.INVENTORY: 1> - - -
          - - - - -
          -
          -
          - VAULT = <ItemLocation.VAULT: 2> - - -
          - - - - -
          -
          -
          - VENDOR = <ItemLocation.VENDOR: 3> - - -
          - - - - -
          -
          -
          - POSTMASTER = <ItemLocation.POSTMASTER: 4> +

          An enums for the known bungie group types.

          +
          - -
          - - - -
          Inherited Members
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          -
          - +
          +
          @typing.final
          class - TransferStatus(Flag): + CredentialType(builtins.int, Enum): - +
          - -
          743@typing.final
          -744class TransferStatus(Flag):
          -745    """An enum for items transfer statuses."""
          -746
          -747    CAN_TRANSFER = 0
          -748    """The item can be transferred."""
          -749    IS_EQUIPPED = 1
          -750    """You can't transfer since the item is equipped."""
          -751    NOT_TRASNFERRABLE = 2
          -752    """This item can not be transferred."""
          -753    COULD_BE_TRANSFERRED = 4
          -754    """You can trasnfer the item. But the place you're trying to put it at has no space for it."""
          +    
          +            
          661@typing.final
          +662class CredentialType(int, Enum):
          +663    """The types of the accounts system supports at bungie."""
          +664
          +665    NONE = 0
          +666    XUID = 1
          +667    PSNID = 2
          +668    WILD = 3
          +669    FAKE = 4
          +670    FACEBOOK = 5
          +671    GOOGLE = 8
          +672    WINDOWS = 9
          +673    DEMONID = 10
          +674    STEAMID = 12
          +675    BATTLENETID = 14
          +676    STADIAID = 16
          +677    TWITCHID = 18
           
          -

          An enum for items transfer statuses.

          +

          The types of the accounts system supports at bungie.

          -
          -
          - CAN_TRANSFER = <TransferStatus.CAN_TRANSFER: 0> - - -
          - - -

          The item can be transferred.

          -
          +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - IS_EQUIPPED = <TransferStatus.IS_EQUIPPED: 1> - - -
          - - -

          You can't transfer since the item is equipped.

          -
          +
          +
          + +
          +
          @typing.final
          + class + Presence(builtins.int, Enum): -
          -
          -
          - NOT_TRASNFERRABLE = <TransferStatus.NOT_TRASNFERRABLE: 2> + -
          - - -

          This item can not be transferred.

          -
          - + +
          680@typing.final
          +681class Presence(int, Enum):
          +682    """An enum for a bungie friend status."""
          +683
          +684    OFFLINE_OR_UNKNOWN = 0
          +685    ONLINE = 1
          +
          -
          -
          -
          - COULD_BE_TRANSFERRED = <TransferStatus.COULD_BE_TRANSFERRED: 4> - -
          - - -

          You can trasnfer the item. But the place you're trying to put it at has no space for it.

          +

          An enum for a bungie friend status.

          -
          Inherited Members
          -
          Flag
          -
          name
          -
          value
          +
          Enum
          +
          name
          +
          value
          + +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          -
          - +
          +
          @typing.final
          class - ItemState(Flag): + Relationship(builtins.int, Enum): - +
          - -
          757@typing.final
          -758class ItemState(Flag):
          -759    """An enum for Destiny 2 item states."""
          -760
          -761    NONE = 0
          -762    LOCKED = 1
          -763    TRACKED = 2
          -764    MASTERWORKED = 4
          -765    CRAFTED = 8
          -766    """If this bit is set, the item has been 'crafted' by the player."""
          -767    HIGHLITED_OBJECTIVE = 16
          -768    """If this bit is set, the item is a 'highlighted' objective."""
          +    
          +            
          688@typing.final
          +689class Relationship(int, Enum):
          +690    """An enum for bungie friends relationship types."""
          +691
          +692    UNKNOWN = 0
          +693    FRIEND = 1
          +694    INCOMING_REQUEST = 2
          +695    OUTGOING_REQUEST = 3
           
          -

          An enum for Destiny 2 item states.

          +

          An enum for bungie friends relationship types.

          -
          -
          - NONE = <ItemState.NONE: 0> +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          - -
          - - - +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - LOCKED = <ItemState.LOCKED: 1> +
          +
          + +
          +
          @typing.final
          - -
          - - - + class + ClanMemberType(builtins.int, Enum): -
          -
          -
          - TRACKED = <ItemState.TRACKED: 2> + -
          - - - + +
          698@typing.final
          +699class ClanMemberType(int, Enum):
          +700    """An enum for bungie clan member types."""
          +701
          +702    NONE = 0
          +703    BEGINNER = 1
          +704    MEMBER = 2
          +705    ADMIN = 3
          +706    ACTING_FOUNDER = 4
          +707    FOUNDER = 5
          +
          -
          -
          -
          - MASTERWORKED = <ItemState.MASTERWORKED: 4> - -
          - - - +

          An enum for bungie clan member types.

          +
          -
          -
          -
          - CRAFTED = <ItemState.CRAFTED: 8> - -
          - - -

          If this bit is set, the item has been 'crafted' by the player.

          -
          +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - HIGHLITED_OBJECTIVE = <ItemState.HIGHLITED_OBJECTIVE: 16> + +
          + +
          +
          @typing.final
          + + class + MembershipOption(builtins.int, Enum): + + -
          - - -

          If this bit is set, the item is a 'highlighted' objective.

          + +
          710@typing.final
          +711class MembershipOption(int, Enum):
          +712    """A enum for GroupV2 membership options."""
          +713
          +714    REVIEWD = 0
          +715    OPEN = 1
          +716    CLOSED = 2
          +
          + + +

          A enum for GroupV2 membership options.

          -
          Inherited Members
          -
          Flag
          -
          name
          -
          value
          +
          Enum
          +
          name
          +
          value
          + +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          -
          - +
          +
          @typing.final
          class - PrivacySetting(builtins.int, Enum): + ItemBindStatus(builtins.int, Enum): - +
          - -
          771@typing.final
          -772class PrivacySetting(int, Enum):
          -773    """An enum for players's privacy settings."""
          -774
          -775    OPEN = 0
          -776    CLAN_AND_FRIENDS = 1
          -777    FRIENDS_ONLY = 2
          -778    INVITE_ONLY = 3
          -779    CLOSED = 4
          +    
          +            
          719@typing.final
          +720class ItemBindStatus(int, Enum):
          +721    """An enum for Destiny 2 items bind status."""
          +722
          +723    NOT_BOUND = 0
          +724    BOUND_TO_CHARACTER = 1
          +725    BOUND_TO_ACCOUNT = 2
          +726    BOUNT_TO_GUILD = 3
           
          -

          An enum for players's privacy settings.

          +

          An enum for Destiny 2 items bind status.

          -
          -
          - OPEN = <PrivacySetting.OPEN: 0> +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          - -
          - - - +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - CLAN_AND_FRIENDS = <PrivacySetting.CLAN_AND_FRIENDS: 1> +
          +
          + +
          +
          @typing.final
          - -
          - - - + class + ItemLocation(builtins.int, Enum): -
          -
          -
          - FRIENDS_ONLY = <PrivacySetting.FRIENDS_ONLY: 2> + -
          - - - - -
          -
          -
          - INVITE_ONLY = <PrivacySetting.INVITE_ONLY: 3> + +
          729@typing.final
          +730class ItemLocation(int, Enum):
          +731    """An enum for Destiny 2 items location."""
          +732
          +733    UNKNOWN = 0
          +734    INVENTORY = 1
          +735    VAULT = 2
          +736    VENDOR = 3
          +737    POSTMASTER = 4
          +
          - -
          - - - -
          -
          -
          - CLOSED = <PrivacySetting.CLOSED: 4> +

          An enum for Destiny 2 items location.

          +
          - -
          - - - -
          Inherited Members
          builtins.int
          -
          conjugate
          -
          bit_length
          -
          bit_count
          -
          to_bytes
          -
          from_bytes
          -
          as_integer_ratio
          -
          real
          -
          imag
          -
          numerator
          -
          denominator
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          -
          - +
          +
          @typing.final
          class - ClosedReasons(Flag): + TransferStatus(Flag): - +
          - -
          782@typing.final
          -783class ClosedReasons(Flag):
          -784    """A Flags enumeration representing the reasons why a person can't join this user's fireteam."""
          -785
          -786    NONE = 0
          -787    MATCHMAKING = 1
          -788    LOADING = 2
          -789    SOLO = 4
          -790    """The activity is required to be played solo."""
          -791    INTERNAL_REASONS = 8
          -792    """
          -793    The user can't be joined for one of a variety of internal reasons.
          -794    Basically, the game can't let you join at this time,
          -795    but for reasons that aren't under the control of this user
          -796    """
          -797    DISALLOWED_BY_GAME_STATE = 16
          -798    """The user's current activity/quest/other transitory game state is preventing joining."""
          -799    OFFLINE = 32768
          -800    """The user appears offline."""
          +    
          +            
          740@typing.final
          +741class TransferStatus(Flag):
          +742    """An enum for items transfer statuses."""
          +743
          +744    CAN_TRANSFER = 0
          +745    """The item can be transferred."""
          +746    IS_EQUIPPED = 1 << 0
          +747    """You can't transfer since the item is equipped."""
          +748    NOT_TRASNFERRABLE = 1 << 1
          +749    """This item can not be transferred."""
          +750    COULD_BE_TRANSFERRED = 1 << 2
          +751    """You can trasnfer the item. But the place you're trying to put it at has no space for it."""
           
          -

          A Flags enumeration representing the reasons why a person can't join this user's fireteam.

          +

          An enum for items transfer statuses.

          -
          -
          - NONE = <ClosedReasons.NONE: 0> - - -
          - - - - -
          -
          -
          - MATCHMAKING = <ClosedReasons.MATCHMAKING: 1> - - -
          - - - - -
          -
          -
          - LOADING = <ClosedReasons.LOADING: 2> - - -
          - - - - -
          -
          +
          - SOLO = <ClosedReasons.SOLO: 4> + CAN_TRANSFER = <TransferStatus.CAN_TRANSFER: 0>
          - + -

          The activity is required to be played solo.

          +

          The item can be transferred.

          -
          +
          - INTERNAL_REASONS = <ClosedReasons.INTERNAL_REASONS: 8> + IS_EQUIPPED = <TransferStatus.IS_EQUIPPED: 1>
          - + -

          The user can't be joined for one of a variety of internal reasons. -Basically, the game can't let you join at this time, -but for reasons that aren't under the control of this user

          +

          You can't transfer since the item is equipped.

          -
          +
          - DISALLOWED_BY_GAME_STATE = <ClosedReasons.DISALLOWED_BY_GAME_STATE: 16> + NOT_TRASNFERRABLE = <TransferStatus.NOT_TRASNFERRABLE: 2>
          - + -

          The user's current activity/quest/other transitory game state is preventing joining.

          +

          This item can not be transferred.

          -
          +
          - OFFLINE = <ClosedReasons.OFFLINE: 32768> + COULD_BE_TRANSFERRED = <TransferStatus.COULD_BE_TRANSFERRED: 4>
          - + -

          The user appears offline.

          +

          You can trasnfer the item. But the place you're trying to put it at has no space for it.

          @@ -7576,348 +3537,285 @@
          Inherited Members
          Inherited Members
          -
          - +
          +
          @typing.final
          class - ItemSubType(builtins.int, Enum): + ItemState(Flag): - +
          - -
          589@typing.final
          -590class ItemSubType(int, Enum):
          -591    """An enum for Destiny 2 inventory items subtype."""
          -592
          -593    NONE = 0
          -594    AUTORIFLE = 6
          -595    SHOTGUN = 7
          -596    MACHINEGUN = 8
          -597    HANDCANNON = 9
          -598    ROCKETLAUNCHER = 10
          -599    FUSIONRIFLE = 11
          -600    SNIPERRIFLE = 12
          -601    PULSERIFLE = 13
          -602    SCOUTRIFLE = 14
          -603    SIDEARM = 17
          -604    SWORD = 18
          -605    MASK = 19
          -606    SHADER = 20
          -607    ORNAMENT = 21
          -608    FUSIONRIFLELINE = 22
          -609    GRENADELAUNCHER = 23
          -610    SUBMACHINEGUN = 24
          -611    TRACERIFLE = 25
          -612    HELMETARMOR = 26
          -613    GAUNTLETSARMOR = 27
          -614    CHESTARMOR = 28
          -615    LEGARMOR = 29
          -616    CLASSARMOR = 30
          -617    BOW = 31
          -618    DUMMYREPEATABLEBOUNTY = 32
          +    
          +            
          754@typing.final
          +755class ItemState(Flag):
          +756    """An enum for Destiny 2 item states."""
          +757
          +758    NONE = 0
          +759    LOCKED = 1 << 0
          +760    TRACKED = 1 << 1
          +761    MASTERWORKED = 1 << 2
          +762    CRAFTED = 1 << 3
          +763    """If this bit is set, the item has been 'crafted' by the player."""
          +764    HIGHLITED_OBJECTIVE = 1 << 4
          +765    """If this bit is set, the item is a 'highlighted' objective."""
           
          -

          An enum for Destiny 2 inventory items subtype.

          -
          - - -
          -
          - NONE = <ItemSubType.NONE: 0> - - -
          - - - - -
          -
          -
          - AUTORIFLE = <ItemSubType.AUTORIFLE: 6> - - -
          - - - - -
          -
          -
          - SHOTGUN = <ItemSubType.SHOTGUN: 7> - - -
          - - - - -
          -
          -
          - MACHINEGUN = <ItemSubType.MACHINEGUN: 8> - - -
          - - - - -
          -
          -
          - HANDCANNON = <ItemSubType.HANDCANNON: 9> - - -
          - - - - -
          -
          -
          - ROCKETLAUNCHER = <ItemSubType.ROCKETLAUNCHER: 10> - - -
          - - - - -
          -
          -
          - FUSIONRIFLE = <ItemSubType.FUSIONRIFLE: 11> - - -
          - - - - -
          -
          -
          - SNIPERRIFLE = <ItemSubType.SNIPERRIFLE: 12> +

          An enum for Destiny 2 item states.

          +
          - -
          - - - -
          -
          +
          - PULSERIFLE = <ItemSubType.PULSERIFLE: 13> + CRAFTED = <ItemState.CRAFTED: 8>
          - - + +

          If this bit is set, the item has been 'crafted' by the player.

          +
          +
          -
          +
          - SCOUTRIFLE = <ItemSubType.SCOUTRIFLE: 14> + HIGHLITED_OBJECTIVE = <ItemState.HIGHLITED_OBJECTIVE: 16>
          - - + +

          If this bit is set, the item is a 'highlighted' objective.

          +
          -
          -
          -
          - SIDEARM = <ItemSubType.SIDEARM: 17> - -
          - - - +
          +
          +
          Inherited Members
          +
          +
          Flag
          +
          name
          +
          value
          +
          +
          -
          -
          - SWORD = <ItemSubType.SWORD: 18> +
          +
          + +
          +
          @typing.final
          - -
          - - - + class + PrivacySetting(builtins.int, Enum): -
          -
          -
          - MASK = <ItemSubType.MASK: 19> + -
          - - - + +
          768@typing.final
          +769class PrivacySetting(int, Enum):
          +770    """An enum for players's privacy settings."""
          +771
          +772    OPEN = 0
          +773    CLAN_AND_FRIENDS = 1
          +774    FRIENDS_ONLY = 2
          +775    INVITE_ONLY = 3
          +776    CLOSED = 4
          +
          -
          -
          -
          - SHADER = <ItemSubType.SHADER: 20> - -
          - - - +

          An enum for players's privacy settings.

          +
          -
          -
          -
          - ORNAMENT = <ItemSubType.ORNAMENT: 21> - -
          - - - +
          +
          Inherited Members
          +
          +
          Enum
          +
          name
          +
          value
          + +
          +
          builtins.int
          +
          conjugate
          +
          bit_length
          +
          bit_count
          +
          to_bytes
          +
          from_bytes
          +
          as_integer_ratio
          +
          real
          +
          imag
          +
          numerator
          +
          denominator
          +
          +
          -
          -
          - FUSIONRIFLELINE = <ItemSubType.FUSIONRIFLELINE: 22> + +
          + +
          +
          @typing.final
          - -
          - - - + class + ClosedReasons(Flag): -
          -
          -
          - GRENADELAUNCHER = <ItemSubType.GRENADELAUNCHER: 23> + -
          - - - + +
          779@typing.final
          +780class ClosedReasons(Flag):
          +781    """A Flags enumeration representing the reasons why a person can't join this user's fireteam."""
          +782
          +783    NONE = 0
          +784    MATCHMAKING = 1 << 0
          +785    LOADING = 1 << 1
          +786    SOLO = 1 << 2
          +787    """The activity is required to be played solo."""
          +788    INTERNAL_REASONS = 1 << 3
          +789    """
          +790    The user can't be joined for one of a variety of internal reasons.
          +791    Basically, the game can't let you join at this time,
          +792    but for reasons that aren't under the control of this user
          +793    """
          +794    DISALLOWED_BY_GAME_STATE = 1 << 4
          +795    """The user's current activity/quest/other transitory game state is preventing joining."""
          +796    OFFLINE = 32768
          +797    """The user appears offline."""
          +
          -
          -
          -
          - SUBMACHINEGUN = <ItemSubType.SUBMACHINEGUN: 24> - -
          - - - +

          A Flags enumeration representing the reasons why a person can't join this user's fireteam.

          +
          -
          -
          + +
          - TRACERIFLE = <ItemSubType.TRACERIFLE: 25> + SOLO = <ClosedReasons.SOLO: 4>
          - - + +

          The activity is required to be played solo.

          +
          +
          -
          +
          - HELMETARMOR = <ItemSubType.HELMETARMOR: 26> + INTERNAL_REASONS = <ClosedReasons.INTERNAL_REASONS: 8>
          - - + +

          The user can't be joined for one of a variety of internal reasons. +Basically, the game can't let you join at this time, +but for reasons that aren't under the control of this user

          +
          +
          -
          +
          - GAUNTLETSARMOR = <ItemSubType.GAUNTLETSARMOR: 27> + DISALLOWED_BY_GAME_STATE = <ClosedReasons.DISALLOWED_BY_GAME_STATE: 16>
          - - + +

          The user's current activity/quest/other transitory game state is preventing joining.

          +
          +
          -
          +
          - CHESTARMOR = <ItemSubType.CHESTARMOR: 28> + OFFLINE = <ClosedReasons.OFFLINE: 32768>
          - - + +

          The user appears offline.

          +
          -
          -
          -
          - LEGARMOR = <ItemSubType.LEGARMOR: 29> - -
          - - - +
          +
          +
          Inherited Members
          +
          +
          Flag
          +
          name
          +
          value
          +
          +
          -
          -
          - CLASSARMOR = <ItemSubType.CLASSARMOR: 30> + +
          + +
          +
          @typing.final
          - -
          - - - + class + ItemSubType(builtins.int, Enum): -
          -
          -
          - BOW = <ItemSubType.BOW: 31> + -
          - - - + +
          586@typing.final
          +587class ItemSubType(int, Enum):
          +588    """An enum for Destiny 2 inventory items subtype."""
          +589
          +590    NONE = 0
          +591    AUTORIFLE = 6
          +592    SHOTGUN = 7
          +593    MACHINEGUN = 8
          +594    HANDCANNON = 9
          +595    ROCKETLAUNCHER = 10
          +596    FUSIONRIFLE = 11
          +597    SNIPERRIFLE = 12
          +598    PULSERIFLE = 13
          +599    SCOUTRIFLE = 14
          +600    SIDEARM = 17
          +601    SWORD = 18
          +602    MASK = 19
          +603    SHADER = 20
          +604    ORNAMENT = 21
          +605    FUSIONRIFLELINE = 22
          +606    GRENADELAUNCHER = 23
          +607    SUBMACHINEGUN = 24
          +608    TRACERIFLE = 25
          +609    HELMETARMOR = 26
          +610    GAUNTLETSARMOR = 27
          +611    CHESTARMOR = 28
          +612    LEGARMOR = 29
          +613    CLASSARMOR = 30
          +614    BOW = 31
          +615    DUMMYREPEATABLEBOUNTY = 32
          +
          -
          -
          -
          - DUMMYREPEATABLEBOUNTY = <ItemSubType.DUMMYREPEATABLEBOUNTY: 32> - -
          - - - +

          An enum for Destiny 2 inventory items subtype.

          +
          + -
          Inherited Members
          @@ -7954,17 +3852,17 @@
          Inherited Members
          -
          633@typing.final
          -634class TierType(int, Enum):
          -635    """An enum for a Destiny 2 item tier type."""
          -636
          -637    UNKNOWN = 0
          -638    CURRENCY = 1
          -639    BASIC = 2
          -640    COMMON = 3
          -641    RARE = 4
          -642    SUPERIOR = 5
          -643    EXOTIC = 6
          +            
          630@typing.final
          +631class TierType(int, Enum):
          +632    """An enum for a Destiny 2 item tier type."""
          +633
          +634    UNKNOWN = 0
          +635    CURRENCY = 1
          +636    BASIC = 2
          +637    COMMON = 3
          +638    RARE = 4
          +639    SUPERIOR = 5
          +640    EXOTIC = 6
           
          @@ -7972,83 +3870,6 @@
          Inherited Members
          -
          -
          - UNKNOWN = <TierType.UNKNOWN: 0> - - -
          - - - - -
          -
          -
          - CURRENCY = <TierType.CURRENCY: 1> - - -
          - - - - -
          -
          -
          - BASIC = <TierType.BASIC: 2> - - -
          - - - - -
          -
          -
          - COMMON = <TierType.COMMON: 3> - - -
          - - - - -
          -
          -
          - RARE = <TierType.RARE: 4> - - -
          - - - - -
          -
          -
          - SUPERIOR = <TierType.SUPERIOR: 5> - - -
          - - - - -
          -
          -
          - EXOTIC = <TierType.EXOTIC: 6> - - -
          - - - - -
          Inherited Members
          @@ -8176,7 +3997,11 @@
          Inherited Members
          let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/internal/factory.html b/docs/aiobungie/internal/factory.html index e2b5507f..222a696c 100644 --- a/docs/aiobungie/internal/factory.html +++ b/docs/aiobungie/internal/factory.html @@ -3,7 +3,7 @@ - + aiobungie.internal.factory API documentation @@ -57,9 +57,6 @@

          API Documentation

        • deserialize_user_credentials
        • -
        • - set_themese_attrs -
        • deserialize_user_themes
        • @@ -274,9 +271,9 @@

          Marshalling factory used to deserializing REST JSON payloads into an aiobungie.crates.

          - + - +
             1# MIT License
              2# Copyright (c) 2020 - Present nxtlo
          @@ -473,2312 +470,2306 @@ 

          193 for creds in payload 194 ] 195 - 196 @staticmethod - 197 def set_themese_attrs( - 198 payload: typedefs.JSONArray, / - 199 ) -> typing.Collection[user.UserThemes]: - 200 return [ - 201 user.UserThemes( - 202 id=int(entry["userThemeId"]), - 203 name=entry["userThemeName"] - 204 if "userThemeName" in entry - 205 else undefined.Undefined, - 206 description=entry["userThemeDescription"] - 207 if "userThemeDescription" in entry - 208 else undefined.Undefined, - 209 ) - 210 for entry in payload - 211 ] - 212 - 213 def deserialize_user_themes( - 214 self, payload: typedefs.JSONArray - 215 ) -> collections.Sequence[user.UserThemes]: - 216 return list(self.set_themese_attrs(payload)) - 217 - 218 def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan: - 219 - 220 # This is kinda redundant - 221 data = payload - 222 - 223 # This is always outside the details. - 224 current_user_map: typing.Optional[ - 225 collections.Mapping[str, clans.ClanMember] - 226 ] = None - 227 if raw_current_user_map := payload.get("currentUserMemberMap"): - 228 current_user_map = { - 229 membership_type: self.deserialize_clan_member(membership) - 230 for membership_type, membership in raw_current_user_map.items() - 231 } - 232 - 233 try: - 234 data = payload["detail"] - 235 except KeyError: - 236 pass - 237 - 238 id = data["groupId"] - 239 name = data["name"] - 240 created_at = data["creationDate"] - 241 member_count = data["memberCount"] - 242 about = data["about"] - 243 motto = data["motto"] - 244 is_public = data["isPublic"] - 245 banner = assets.Image(str(data["bannerPath"])) - 246 avatar = assets.Image(str(data["avatarPath"])) - 247 tags = data["tags"] - 248 type = data["groupType"] - 249 - 250 features = data["features"] - 251 features_obj = clans.ClanFeatures( - 252 max_members=features["maximumMembers"], - 253 max_membership_types=features["maximumMembershipsOfGroupType"], - 254 capabilities=features["capabilities"], - 255 membership_types=features["membershipTypes"], - 256 invite_permissions=features["invitePermissionOverride"], - 257 update_banner_permissions=features["updateBannerPermissionOverride"], - 258 update_culture_permissions=features["updateCulturePermissionOverride"], - 259 join_level=features["joinLevel"], - 260 ) + 196 def deserialize_user_themes( + 197 self, payload: typedefs.JSONArray + 198 ) -> collections.Sequence[user.UserThemes]: + 199 return [ + 200 user.UserThemes( + 201 id=int(entry["userThemeId"]), + 202 name=entry["userThemeName"] + 203 if "userThemeName" in entry + 204 else undefined.Undefined, + 205 description=entry["userThemeDescription"] + 206 if "userThemeDescription" in entry + 207 else undefined.Undefined, + 208 ) + 209 for entry in payload + 210 ] + 211 + 212 def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan: + 213 + 214 # This is kinda redundant + 215 data = payload + 216 + 217 # This is always outside the details. + 218 current_user_map: typing.Optional[ + 219 collections.Mapping[str, clans.ClanMember] + 220 ] = None + 221 if raw_current_user_map := payload.get("currentUserMemberMap"): + 222 current_user_map = { + 223 membership_type: self.deserialize_clan_member(membership) + 224 for membership_type, membership in raw_current_user_map.items() + 225 } + 226 + 227 try: + 228 data = payload["detail"] + 229 except KeyError: + 230 pass + 231 + 232 id = data["groupId"] + 233 name = data["name"] + 234 created_at = data["creationDate"] + 235 member_count = data["memberCount"] + 236 about = data["about"] + 237 motto = data["motto"] + 238 is_public = data["isPublic"] + 239 banner = assets.Image(str(data["bannerPath"])) + 240 avatar = assets.Image(str(data["avatarPath"])) + 241 tags = data["tags"] + 242 type = data["groupType"] + 243 + 244 features = data["features"] + 245 features_obj = clans.ClanFeatures( + 246 max_members=features["maximumMembers"], + 247 max_membership_types=features["maximumMembershipsOfGroupType"], + 248 capabilities=features["capabilities"], + 249 membership_types=features["membershipTypes"], + 250 invite_permissions=features["invitePermissionOverride"], + 251 update_banner_permissions=features["updateBannerPermissionOverride"], + 252 update_culture_permissions=features["updateCulturePermissionOverride"], + 253 join_level=features["joinLevel"], + 254 ) + 255 + 256 information: typedefs.JSONObject = data["clanInfo"] + 257 progression: collections.Mapping[int, progressions.Progression] = { + 258 int(prog_hash): self.deserialize_progressions(prog) + 259 for prog_hash, prog in information["d2ClanProgressions"].items() + 260 } 261 - 262 information: typedefs.JSONObject = data["clanInfo"] - 263 progression: collections.Mapping[int, progressions.Progression] = { - 264 int(prog_hash): self.deserialize_progressions(prog) - 265 for prog_hash, prog in information["d2ClanProgressions"].items() - 266 } - 267 - 268 founder: typedefs.NoneOr[clans.ClanMember] = None - 269 if raw_founder := payload.get("founder"): - 270 founder = self.deserialize_clan_member(raw_founder) - 271 - 272 return clans.Clan( - 273 net=self._net, - 274 id=int(id), - 275 name=name, - 276 type=enums.GroupType(type), - 277 created_at=time.clean_date(created_at), - 278 member_count=member_count, - 279 motto=motto, - 280 about=about, - 281 is_public=is_public, - 282 banner=banner, - 283 avatar=avatar, - 284 tags=tags, - 285 features=features_obj, - 286 owner=founder, - 287 progressions=progression, - 288 call_sign=information["clanCallsign"], - 289 banner_data=information["clanBannerData"], - 290 chat_security=data["chatSecurity"], - 291 conversation_id=int(data["conversationId"]), - 292 allow_chat=data["allowChat"], - 293 theme=data["theme"], - 294 current_user_membership=current_user_map, - 295 ) - 296 - 297 def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember: - 298 destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"]) - 299 return clans.ClanMember( - 300 net=self._net, - 301 last_seen_name=destiny_user.last_seen_name, - 302 id=destiny_user.id, - 303 name=destiny_user.name, - 304 icon=destiny_user.icon, - 305 last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])), - 306 group_id=int(data["groupId"]), - 307 joined_at=time.clean_date(data["joinDate"]), - 308 types=destiny_user.types, - 309 is_public=destiny_user.is_public, - 310 type=destiny_user.type, - 311 code=destiny_user.code, - 312 is_online=data["isOnline"], - 313 crossave_override=destiny_user.crossave_override, - 314 bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"]) - 315 if "bungieNetUserInfo" in data - 316 else None, - 317 member_type=enums.ClanMemberType(int(data["memberType"])), - 318 ) - 319 - 320 def deserialize_clan_members( - 321 self, data: typedefs.JSONObject, / - 322 ) -> iterators.FlatIterator[clans.ClanMember]: - 323 return iterators.FlatIterator( - 324 [self.deserialize_clan_member(member) for member in data["results"]] - 325 ) - 326 - 327 def deserialize_group_member( - 328 self, payload: typedefs.JSONObject - 329 ) -> clans.GroupMember: - 330 member = payload["member"] - 331 return clans.GroupMember( - 332 net=self._net, - 333 join_date=time.clean_date(member["joinDate"]), - 334 group_id=int(member["groupId"]), - 335 member_type=enums.ClanMemberType(member["memberType"]), - 336 is_online=member["isOnline"], - 337 last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])), - 338 inactive_memberships=payload.get("areAllMembershipsInactive", None), - 339 member=self.deserialize_destiny_membership(member["destinyUserInfo"]), - 340 group=self.deserialize_clan(payload["group"]), - 341 ) - 342 - 343 def _deserialize_clan_conversation( - 344 self, payload: typedefs.JSONObject - 345 ) -> clans.ClanConversation: - 346 return clans.ClanConversation( - 347 net=self._net, - 348 id=int(payload["conversationId"]), - 349 group_id=int(payload["groupId"]), - 350 name=( - 351 payload["chatName"] - 352 if not typedefs.is_unknown(payload["chatName"]) - 353 else undefined.Undefined - 354 ), - 355 chat_enabled=payload["chatEnabled"], - 356 security=payload["chatSecurity"], - 357 ) - 358 - 359 def deserialize_clan_conversations( - 360 self, payload: typedefs.JSONArray - 361 ) -> collections.Sequence[clans.ClanConversation]: - 362 return [self._deserialize_clan_conversation(conv) for conv in payload] - 363 - 364 def deserialize_app_owner( - 365 self, payload: typedefs.JSONObject - 366 ) -> application.ApplicationOwner: - 367 return application.ApplicationOwner( - 368 net=self._net, - 369 name=payload.get("bungieGlobalDisplayName", undefined.Undefined), - 370 id=int(payload["membershipId"]), - 371 type=enums.MembershipType(payload["membershipType"]), - 372 icon=assets.Image(str(payload["iconPath"])), - 373 is_public=payload["isPublic"], - 374 code=payload.get("bungieGlobalDisplayNameCode", None), - 375 ) - 376 - 377 def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application: - 378 return application.Application( - 379 id=int(payload["applicationId"]), - 380 name=payload["name"], - 381 link=payload["link"], - 382 status=payload["status"], - 383 redirect_url=payload.get("redirectUrl", None), - 384 created_at=time.clean_date(str(payload["creationDate"])), - 385 published_at=time.clean_date(str(payload["firstPublished"])), - 386 owner=self.deserialize_app_owner(payload["team"][0]["user"]), # type: ignore - 387 scope=payload.get("scope", undefined.Undefined), - 388 ) - 389 - 390 def _set_character_attrs(self, payload: typedefs.JSONObject) -> character.Character: - 391 total_time = time.format_played(int(payload["minutesPlayedTotal"]), suffix=True) - 392 return character.Character( - 393 net=self._net, - 394 id=int(payload["characterId"]), - 395 gender=enums.Gender(payload["genderType"]), - 396 race=enums.Race(payload["raceType"]), - 397 class_type=enums.Class(payload["classType"]), - 398 emblem=assets.Image(str(payload["emblemBackgroundPath"])), - 399 emblem_icon=assets.Image(str(payload["emblemPath"])), - 400 emblem_hash=int(payload["emblemHash"]), - 401 last_played=time.clean_date(payload["dateLastPlayed"]), - 402 total_played_time=total_time, - 403 member_id=int(payload["membershipId"]), - 404 member_type=enums.MembershipType(payload["membershipType"]), - 405 level=payload["baseCharacterLevel"], - 406 title_hash=payload.get("titleRecordHash", None), - 407 light=payload["light"], - 408 stats={enums.Stat(int(k)): v for k, v in payload["stats"].items()}, - 409 ) + 262 founder: typedefs.NoneOr[clans.ClanMember] = None + 263 if raw_founder := payload.get("founder"): + 264 founder = self.deserialize_clan_member(raw_founder) + 265 + 266 return clans.Clan( + 267 net=self._net, + 268 id=int(id), + 269 name=name, + 270 type=enums.GroupType(type), + 271 created_at=time.clean_date(created_at), + 272 member_count=member_count, + 273 motto=motto, + 274 about=about, + 275 is_public=is_public, + 276 banner=banner, + 277 avatar=avatar, + 278 tags=tags, + 279 features=features_obj, + 280 owner=founder, + 281 progressions=progression, + 282 call_sign=information["clanCallsign"], + 283 banner_data=information["clanBannerData"], + 284 chat_security=data["chatSecurity"], + 285 conversation_id=int(data["conversationId"]), + 286 allow_chat=data["allowChat"], + 287 theme=data["theme"], + 288 current_user_membership=current_user_map, + 289 ) + 290 + 291 def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember: + 292 destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"]) + 293 return clans.ClanMember( + 294 net=self._net, + 295 last_seen_name=destiny_user.last_seen_name, + 296 id=destiny_user.id, + 297 name=destiny_user.name, + 298 icon=destiny_user.icon, + 299 last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])), + 300 group_id=int(data["groupId"]), + 301 joined_at=time.clean_date(data["joinDate"]), + 302 types=destiny_user.types, + 303 is_public=destiny_user.is_public, + 304 type=destiny_user.type, + 305 code=destiny_user.code, + 306 is_online=data["isOnline"], + 307 crossave_override=destiny_user.crossave_override, + 308 bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"]) + 309 if "bungieNetUserInfo" in data + 310 else None, + 311 member_type=enums.ClanMemberType(int(data["memberType"])), + 312 ) + 313 + 314 def deserialize_clan_members( + 315 self, data: typedefs.JSONObject, / + 316 ) -> iterators.Iterator[clans.ClanMember]: + 317 return iterators.Iterator( + 318 [self.deserialize_clan_member(member) for member in data["results"]] + 319 ) + 320 + 321 def deserialize_group_member( + 322 self, payload: typedefs.JSONObject + 323 ) -> clans.GroupMember: + 324 member = payload["member"] + 325 return clans.GroupMember( + 326 net=self._net, + 327 join_date=time.clean_date(member["joinDate"]), + 328 group_id=int(member["groupId"]), + 329 member_type=enums.ClanMemberType(member["memberType"]), + 330 is_online=member["isOnline"], + 331 last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])), + 332 inactive_memberships=payload.get("areAllMembershipsInactive", None), + 333 member=self.deserialize_destiny_membership(member["destinyUserInfo"]), + 334 group=self.deserialize_clan(payload["group"]), + 335 ) + 336 + 337 def _deserialize_clan_conversation( + 338 self, payload: typedefs.JSONObject + 339 ) -> clans.ClanConversation: + 340 return clans.ClanConversation( + 341 net=self._net, + 342 id=int(payload["conversationId"]), + 343 group_id=int(payload["groupId"]), + 344 name=( + 345 payload["chatName"] + 346 if not typedefs.is_unknown(payload["chatName"]) + 347 else undefined.Undefined + 348 ), + 349 chat_enabled=payload["chatEnabled"], + 350 security=payload["chatSecurity"], + 351 ) + 352 + 353 def deserialize_clan_conversations( + 354 self, payload: typedefs.JSONArray + 355 ) -> collections.Sequence[clans.ClanConversation]: + 356 return [self._deserialize_clan_conversation(conv) for conv in payload] + 357 + 358 def deserialize_app_owner( + 359 self, payload: typedefs.JSONObject + 360 ) -> application.ApplicationOwner: + 361 return application.ApplicationOwner( + 362 net=self._net, + 363 name=payload.get("bungieGlobalDisplayName", undefined.Undefined), + 364 id=int(payload["membershipId"]), + 365 type=enums.MembershipType(payload["membershipType"]), + 366 icon=assets.Image(str(payload["iconPath"])), + 367 is_public=payload["isPublic"], + 368 code=payload.get("bungieGlobalDisplayNameCode", None), + 369 ) + 370 + 371 def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application: + 372 return application.Application( + 373 id=int(payload["applicationId"]), + 374 name=payload["name"], + 375 link=payload["link"], + 376 status=payload["status"], + 377 redirect_url=payload.get("redirectUrl", None), + 378 created_at=time.clean_date(str(payload["creationDate"])), + 379 published_at=time.clean_date(str(payload["firstPublished"])), + 380 owner=self.deserialize_app_owner(payload["team"][0]["user"]), # type: ignore + 381 scope=payload.get("scope", undefined.Undefined), + 382 ) + 383 + 384 def _set_character_attrs(self, payload: typedefs.JSONObject) -> character.Character: + 385 total_time = time.format_played(int(payload["minutesPlayedTotal"]), suffix=True) + 386 return character.Character( + 387 net=self._net, + 388 id=int(payload["characterId"]), + 389 gender=enums.Gender(payload["genderType"]), + 390 race=enums.Race(payload["raceType"]), + 391 class_type=enums.Class(payload["classType"]), + 392 emblem=assets.Image(str(payload["emblemBackgroundPath"])), + 393 emblem_icon=assets.Image(str(payload["emblemPath"])), + 394 emblem_hash=int(payload["emblemHash"]), + 395 last_played=time.clean_date(payload["dateLastPlayed"]), + 396 total_played_time=total_time, + 397 member_id=int(payload["membershipId"]), + 398 member_type=enums.MembershipType(payload["membershipType"]), + 399 level=payload["baseCharacterLevel"], + 400 title_hash=payload.get("titleRecordHash", None), + 401 light=payload["light"], + 402 stats={enums.Stat(int(k)): v for k, v in payload["stats"].items()}, + 403 ) + 404 + 405 def deserialize_profile( + 406 self, payload: typedefs.JSONObject, / + 407 ) -> typing.Optional[profile.Profile]: + 408 if (raw_profile := payload.get("data")) is None: + 409 return None 410 - 411 def deserialize_profile( - 412 self, payload: typedefs.JSONObject, / - 413 ) -> typing.Optional[profile.Profile]: - 414 if (raw_profile := payload.get("data")) is None: - 415 return None - 416 - 417 payload = raw_profile - 418 id = int(payload["userInfo"]["membershipId"]) - 419 name = payload["userInfo"]["displayName"] - 420 is_public = payload["userInfo"]["isPublic"] - 421 type = enums.MembershipType(payload["userInfo"]["membershipType"]) - 422 last_played = time.clean_date(str(payload["dateLastPlayed"])) - 423 character_ids = [int(cid) for cid in payload["characterIds"]] - 424 power_cap = payload["currentSeasonRewardPowerCap"] - 425 - 426 return profile.Profile( - 427 id=int(id), - 428 name=name, - 429 is_public=is_public, - 430 type=type, - 431 last_played=last_played, - 432 character_ids=character_ids, - 433 power_cap=power_cap, - 434 net=self._net, - 435 ) - 436 - 437 def deserialize_profile_item( - 438 self, payload: typedefs.JSONObject - 439 ) -> profile.ProfileItemImpl: - 440 - 441 instance_id: typing.Optional[int] = None - 442 if raw_instance_id := payload.get("itemInstanceId"): - 443 instance_id = int(raw_instance_id) + 411 payload = raw_profile + 412 id = int(payload["userInfo"]["membershipId"]) + 413 name = payload["userInfo"]["displayName"] + 414 is_public = payload["userInfo"]["isPublic"] + 415 type = enums.MembershipType(payload["userInfo"]["membershipType"]) + 416 last_played = time.clean_date(str(payload["dateLastPlayed"])) + 417 character_ids = [int(cid) for cid in payload["characterIds"]] + 418 power_cap = payload["currentSeasonRewardPowerCap"] + 419 + 420 return profile.Profile( + 421 id=int(id), + 422 name=name, + 423 is_public=is_public, + 424 type=type, + 425 last_played=last_played, + 426 character_ids=character_ids, + 427 power_cap=power_cap, + 428 net=self._net, + 429 ) + 430 + 431 def deserialize_profile_item( + 432 self, payload: typedefs.JSONObject + 433 ) -> profile.ProfileItemImpl: + 434 + 435 instance_id: typing.Optional[int] = None + 436 if raw_instance_id := payload.get("itemInstanceId"): + 437 instance_id = int(raw_instance_id) + 438 + 439 version_number: typing.Optional[int] = None + 440 if raw_version := payload.get("versionNumber"): + 441 version_number = int(raw_version) + 442 + 443 transfer_status = enums.TransferStatus(payload["transferStatus"]) 444 - 445 version_number: typing.Optional[int] = None - 446 if raw_version := payload.get("versionNumber"): - 447 version_number = int(raw_version) - 448 - 449 transfer_status = enums.TransferStatus(payload["transferStatus"]) - 450 - 451 return profile.ProfileItemImpl( - 452 net=self._net, - 453 hash=payload["itemHash"], - 454 quantity=payload["quantity"], - 455 bind_status=enums.ItemBindStatus(payload["bindStatus"]), - 456 location=enums.ItemLocation(payload["location"]), - 457 bucket=payload["bucketHash"], - 458 transfer_status=transfer_status, - 459 lockable=payload["lockable"], - 460 state=enums.ItemState(payload["state"]), - 461 dismantel_permissions=payload["dismantlePermission"], - 462 is_wrapper=payload["isWrapper"], - 463 instance_id=instance_id, - 464 version_number=version_number, - 465 ornament_id=payload.get("overrideStyleItemHash"), - 466 ) - 467 - 468 def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective: - 469 return records.Objective( - 470 net=self._net, - 471 hash=payload["objectiveHash"], - 472 visible=payload["visible"], - 473 complete=payload["complete"], - 474 completion_value=payload["completionValue"], - 475 progress=payload.get("progress"), - 476 destination_hash=payload.get("destinationHash"), - 477 activity_hash=payload.get("activityHash"), - 478 ) - 479 - 480 def deserialize_records( - 481 self, - 482 payload: typedefs.JSONObject, - 483 scores: typing.Optional[records.RecordScores] = None, - 484 **nodes: int, - 485 ) -> records.Record: - 486 objectives: typing.Optional[list[records.Objective]] = None - 487 interval_objectives: typing.Optional[list[records.Objective]] = None - 488 record_state: typedefs.IntAnd[records.RecordState] - 489 - 490 record_state = records.RecordState(payload["state"]) - 491 - 492 if raw_objs := payload.get("objectives"): - 493 objectives = [self.deserialize_objectives(obj) for obj in raw_objs] - 494 - 495 if raw_interval_objs := payload.get("intervalObjectives"): - 496 interval_objectives = [ - 497 self.deserialize_objectives(obj) for obj in raw_interval_objs - 498 ] - 499 - 500 return records.Record( - 501 scores=scores, - 502 categories_node_hash=nodes.get("categories_hash", undefined.Undefined), - 503 seals_node_hash=nodes.get("seals_hash", undefined.Undefined), - 504 state=record_state, - 505 objectives=objectives, - 506 interval_objectives=interval_objectives, - 507 redeemed_count=payload.get("intervalsRedeemedCount", 0), - 508 completion_times=payload.get("completedCount", None), - 509 reward_visibility=payload.get("rewardVisibilty", None), - 510 ) - 511 - 512 def deserialize_character_records( - 513 self, - 514 payload: typedefs.JSONObject, - 515 scores: typing.Optional[records.RecordScores] = None, - 516 record_hashes: typing.Optional[list[int]] = None, - 517 ) -> records.CharacterRecord: - 518 - 519 record = self.deserialize_records(payload, scores) - 520 return records.CharacterRecord( - 521 scores=scores, - 522 categories_node_hash=record.categories_node_hash, - 523 seals_node_hash=record.seals_node_hash, - 524 state=record.state, - 525 objectives=record.objectives, - 526 interval_objectives=record.interval_objectives, - 527 redeemed_count=payload.get("intervalsRedeemedCount", 0), - 528 completion_times=payload.get("completedCount"), - 529 reward_visibility=payload.get("rewardVisibilty"), - 530 record_hashes=record_hashes or [], - 531 ) - 532 - 533 def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye: - 534 return character.Dye( - 535 channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"] - 536 ) - 537 - 538 def deserialize_character_customization( - 539 self, payload: typedefs.JSONObject - 540 ) -> character.CustomizationOptions: - 541 return character.CustomizationOptions( - 542 personality=payload["personality"], - 543 face=payload["face"], - 544 skin_color=payload["skinColor"], - 545 lip_color=payload["lipColor"], - 546 eye_color=payload["eyeColor"], - 547 hair_colors=payload.get("hairColors", []), - 548 feature_colors=payload.get("featureColors", []), - 549 decal_color=payload["decalColor"], - 550 wear_helmet=payload["wearHelmet"], - 551 hair_index=payload["hairIndex"], - 552 feature_index=payload["featureIndex"], - 553 decal_index=payload["decalIndex"], - 554 ) - 555 - 556 def deserialize_character_minimal_equipments( - 557 self, payload: typedefs.JSONObject - 558 ) -> character.MinimalEquipments: - 559 dyes = None - 560 if raw_dyes := payload.get("dyes"): - 561 if raw_dyes: - 562 dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes] - 563 return character.MinimalEquipments( - 564 net=self._net, item_hash=payload["itemHash"], dyes=dyes - 565 ) - 566 - 567 def deserialize_character_render_data( - 568 self, payload: typedefs.JSONObject, / - 569 ) -> character.RenderedData: - 570 return character.RenderedData( - 571 net=self._net, - 572 customization=self.deserialize_character_customization( - 573 payload["customization"] - 574 ), - 575 custom_dyes=[ - 576 self.deserialize_character_dye(dye) - 577 for dye in payload["customDyes"] - 578 if dye - 579 ], - 580 equipment=[ - 581 self.deserialize_character_minimal_equipments(equipment) - 582 for equipment in payload["peerView"]["equipment"] - 583 ], - 584 ) - 585 - 586 def deserialize_available_activity( - 587 self, payload: typedefs.JSONObject - 588 ) -> activity.AvailableActivity: - 589 return activity.AvailableActivity( - 590 hash=payload["activityHash"], - 591 is_new=payload["isNew"], - 592 is_completed=payload["isCompleted"], - 593 is_visible=payload["isVisible"], - 594 display_level=payload.get("displayLevel"), - 595 recommended_light=payload.get("recommendedLight"), - 596 difficulty=activity.Difficulty(payload["difficultyTier"]), - 597 can_join=payload["canJoin"], - 598 can_lead=payload["canLead"], - 599 ) - 600 - 601 def deserialize_character_activity( - 602 self, payload: typedefs.JSONObject - 603 ) -> activity.CharacterActivity: - 604 current_mode: typing.Optional[enums.GameMode] = None - 605 if raw_current_mode := payload.get("currentActivityModeType"): - 606 current_mode = enums.GameMode(raw_current_mode) - 607 - 608 current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None - 609 if raw_current_modes := payload.get("currentActivityModeTypes"): - 610 current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes] - 611 - 612 return activity.CharacterActivity( - 613 date_started=time.clean_date(payload["dateActivityStarted"]), - 614 current_hash=payload["currentActivityHash"], - 615 current_mode_hash=payload["currentActivityModeHash"], - 616 current_mode=current_mode, - 617 current_mode_hashes=payload.get("currentActivityModeHashes"), - 618 current_mode_types=current_mode_types, - 619 current_playlist_hash=payload.get("currentPlaylistActivityHash"), - 620 last_story_hash=payload["lastCompletedStoryHash"], - 621 available_activities=[ - 622 self.deserialize_available_activity(activity_) - 623 for activity_ in payload["availableActivities"] - 624 ], - 625 ) - 626 - 627 def deserialize_profile_items( - 628 self, payload: typedefs.JSONObject, / - 629 ) -> list[profile.ProfileItemImpl]: - 630 return [self.deserialize_profile_item(item) for item in payload["items"]] - 631 - 632 def _deserialize_node(self, payload: typedefs.JSONObject) -> records.Node: - 633 return records.Node( - 634 state=int(payload["state"]), - 635 objective=self.deserialize_objectives(payload["objective"]) - 636 if "objective" in payload - 637 else None, - 638 progress_value=int(payload["progressValue"]), - 639 completion_value=int(payload["completionValue"]), - 640 record_category_score=int(payload["recordCategoryScore"]) - 641 if "recordCategoryScore" in payload - 642 else None, - 643 ) - 644 - 645 @staticmethod - 646 def _deserialize_collectible(payload: typedefs.JSONObject) -> items.Collectible: - 647 recent_collectibles: typing.Optional[collections.Collection[int]] = None - 648 if raw_recent_collectibles := payload.get("recentCollectibleHashes"): - 649 recent_collectibles = [ - 650 int(item_hash) for item_hash in raw_recent_collectibles - 651 ] - 652 - 653 collectibles: dict[int, int] = {} - 654 for item_hash, mapping in payload["collectibles"].items(): - 655 collectibles[int(item_hash)] = int(mapping["state"]) - 656 - 657 return items.Collectible( - 658 recent_collectibles=recent_collectibles, - 659 collectibles=collectibles, - 660 collection_categorie_hash=int(payload["collectionCategoriesRootNodeHash"]), - 661 collection_badges_hash=int(payload["collectionBadgesRootNodeHash"]), - 662 ) - 663 - 664 @staticmethod - 665 def _deserialize_currencies( - 666 payload: typedefs.JSONObject, - 667 ) -> collections.Sequence[items.Currency]: - 668 return [ - 669 items.Currency(hash=int(item_hash), amount=int(amount)) - 670 for item_hash, amount in payload["itemQuantities"].items() - 671 ] - 672 - 673 def deserialize_progressions( - 674 self, payload: typedefs.JSONObject - 675 ) -> progressions.Progression: - 676 return progressions.Progression( - 677 hash=int(payload["progressionHash"]), - 678 level=int(payload["level"]), - 679 cap=int(payload["levelCap"]), - 680 daily_limit=int(payload["dailyLimit"]), - 681 weekly_limit=int(payload["weeklyLimit"]), - 682 current_progress=int(payload["currentProgress"]), - 683 daily_progress=int(payload["dailyProgress"]), - 684 needed=int(payload["progressToNextLevel"]), - 685 next_level=int(payload["nextLevelAt"]), - 686 ) - 687 - 688 def _deserialize_factions( - 689 self, payload: typedefs.JSONObject - 690 ) -> progressions.Factions: - 691 progs = self.deserialize_progressions(payload) - 692 return progressions.Factions( - 693 hash=progs.hash, - 694 level=progs.level, - 695 cap=progs.cap, - 696 daily_limit=progs.daily_limit, - 697 weekly_limit=progs.weekly_limit, - 698 current_progress=progs.current_progress, - 699 daily_progress=progs.daily_progress, - 700 needed=progs.needed, - 701 next_level=progs.next_level, - 702 faction_hash=payload["factionHash"], - 703 faction_vendor_hash=payload["factionVendorIndex"], - 704 ) - 705 - 706 def _deserialize_milestone_available_quest( - 707 self, payload: typedefs.JSONObject - 708 ) -> milestones.MilestoneQuest: - 709 return milestones.MilestoneQuest( - 710 item_hash=payload["questItemHash"], - 711 status=self._deserialize_milestone_quest_status(payload["status"]), - 712 ) - 713 - 714 def _deserialize_milestone_activity( - 715 self, payload: typedefs.JSONObject - 716 ) -> milestones.MilestoneActivity: - 717 - 718 phases: typing.Optional[ - 719 collections.Sequence[milestones.MilestoneActivityPhase] - 720 ] = None - 721 if raw_phases := payload.get("phases"): - 722 phases = [ - 723 milestones.MilestoneActivityPhase( - 724 is_completed=obj["complete"], hash=obj["phaseHash"] - 725 ) - 726 for obj in raw_phases - 727 ] - 728 - 729 return milestones.MilestoneActivity( - 730 hash=payload["activityHash"], - 731 challenges=[ - 732 self.deserialize_objectives(obj["objective"]) - 733 for obj in payload["challenges"] - 734 ], - 735 modifier_hashes=payload.get("modifierHashes"), - 736 boolean_options=payload.get("booleanActivityOptions"), - 737 phases=phases, - 738 ) - 739 - 740 def _deserialize_milestone_quest_status( - 741 self, payload: typedefs.JSONObject - 742 ) -> milestones.QuestStatus: - 743 return milestones.QuestStatus( - 744 net=self._net, - 745 quest_hash=payload["questHash"], - 746 step_hash=payload["stepHash"], - 747 step_objectives=[ - 748 self.deserialize_objectives(objective) - 749 for objective in payload["stepObjectives"] - 750 ], - 751 is_tracked=payload["tracked"], - 752 is_completed=payload["completed"], - 753 started=payload["started"], - 754 item_instance_id=payload["itemInstanceId"], - 755 vendor_hash=payload.get("vendorHash"), - 756 is_redeemed=payload["redeemed"], - 757 ) - 758 - 759 def _deserialize_milestone_rewards( - 760 self, payload: typedefs.JSONObject - 761 ) -> milestones.MilestoneReward: - 762 return milestones.MilestoneReward( - 763 category_hash=payload["rewardCategoryHash"], - 764 entries=[ - 765 milestones.MilestoneRewardEntry( - 766 entry_hash=entry["rewardEntryHash"], - 767 is_earned=entry["earned"], - 768 is_redeemed=entry["redeemed"], - 769 ) - 770 for entry in payload["entries"] - 771 ], - 772 ) - 773 - 774 def deserialize_milestone( - 775 self, payload: typedefs.JSONObject - 776 ) -> milestones.Milestone: - 777 start_date: typing.Optional[datetime.datetime] = None - 778 if raw_start_date := payload.get("startDate"): - 779 start_date = time.clean_date(raw_start_date) - 780 - 781 end_date: typing.Optional[datetime.datetime] = None - 782 if raw_end_date := payload.get("endDate"): - 783 end_date = time.clean_date(raw_end_date) - 784 - 785 rewards: typing.Optional[ - 786 collections.Collection[milestones.MilestoneReward] - 787 ] = None - 788 if raw_rewards := payload.get("rewards"): - 789 rewards = [ - 790 self._deserialize_milestone_rewards(reward) for reward in raw_rewards - 791 ] - 792 - 793 activities: typing.Optional[ - 794 collections.Sequence[milestones.MilestoneActivity] - 795 ] = None - 796 if raw_activities := payload.get("activities"): - 797 activities = [ - 798 self._deserialize_milestone_activity(active) - 799 for active in raw_activities - 800 ] - 801 - 802 quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None - 803 if raw_quests := payload.get("availableQuests"): - 804 quests = [ - 805 self._deserialize_milestone_available_quest(quest) - 806 for quest in raw_quests - 807 ] - 808 - 809 vendors: typing.Optional[ - 810 collections.Sequence[milestones.MilestoneVendor] - 811 ] = None - 812 if raw_vendors := payload.get("vendors"): - 813 vendors = [ - 814 milestones.MilestoneVendor( - 815 vendor_hash=vendor["vendorHash"], - 816 preview_itemhash=vendor.get("previewItemHash"), - 817 ) - 818 for vendor in raw_vendors - 819 ] - 820 - 821 return milestones.Milestone( - 822 hash=payload["milestoneHash"], - 823 start_date=start_date, - 824 end_date=end_date, - 825 order=payload["order"], - 826 rewards=rewards, - 827 available_quests=quests, - 828 activities=activities, - 829 vendors=vendors, - 830 ) - 831 - 832 def _deserialize_artifact_tiers( - 833 self, payload: typedefs.JSONObject - 834 ) -> season.ArtifactTier: - 835 return season.ArtifactTier( - 836 hash=payload["tierHash"], - 837 is_unlocked=payload["isUnlocked"], - 838 points_to_unlock=payload["pointsToUnlock"], - 839 items=[ - 840 season.ArtifactTierItem( - 841 hash=item["itemHash"], is_active=item["isActive"] - 842 ) - 843 for item in payload["items"] - 844 ], - 845 ) - 846 - 847 def deserialize_characters( - 848 self, payload: typedefs.JSONObject - 849 ) -> collections.Mapping[int, character.Character]: - 850 return { - 851 int(char_id): self._set_character_attrs(char) - 852 for char_id, char in payload["data"].items() - 853 } - 854 - 855 def deserialize_character( - 856 self, payload: typedefs.JSONObject - 857 ) -> character.Character: - 858 return self._set_character_attrs(payload) - 859 - 860 def deserialize_character_equipments( - 861 self, payload: typedefs.JSONObject - 862 ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]: - 863 return { - 864 int(char_id): self.deserialize_profile_items(item) - 865 for char_id, item in payload["data"].items() - 866 } - 867 - 868 def deserialize_character_activities( - 869 self, payload: typedefs.JSONObject - 870 ) -> collections.Mapping[int, activity.CharacterActivity]: - 871 return { - 872 int(char_id): self.deserialize_character_activity(data) - 873 for char_id, data in payload["data"].items() - 874 } - 875 - 876 def deserialize_characters_render_data( - 877 self, payload: typedefs.JSONObject - 878 ) -> collections.Mapping[int, character.RenderedData]: - 879 return { - 880 int(char_id): self.deserialize_character_render_data(data) - 881 for char_id, data in payload["data"].items() - 882 } - 883 - 884 def deserialize_character_progressions( - 885 self, payload: typedefs.JSONObject - 886 ) -> character.CharacterProgression: - 887 progressions_ = { - 888 int(prog_id): self.deserialize_progressions(prog) - 889 for prog_id, prog in payload["progressions"].items() - 890 } - 891 - 892 factions = { - 893 int(faction_id): self._deserialize_factions(faction) - 894 for faction_id, faction in payload["factions"].items() - 895 } - 896 - 897 milestones_ = { - 898 int(milestone_hash): self.deserialize_milestone(milestone) - 899 for milestone_hash, milestone in payload["milestones"].items() - 900 } - 901 - 902 uninstanced_item_objectives = { - 903 int(item_hash): [self.deserialize_objectives(ins) for ins in obj] - 904 for item_hash, obj in payload["uninstancedItemObjectives"].items() - 905 } - 906 - 907 artifact = payload["seasonalArtifact"] - 908 seasonal_artifact = season.CharacterScopedArtifact( - 909 hash=artifact["artifactHash"], - 910 points_used=artifact["pointsUsed"], - 911 reset_count=artifact["resetCount"], - 912 tiers=[ - 913 self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"] - 914 ], - 915 ) - 916 checklists = payload["checklists"] - 917 - 918 return character.CharacterProgression( - 919 progressions=progressions_, - 920 factions=factions, - 921 checklists=checklists, - 922 milestones=milestones_, - 923 seasonal_artifact=seasonal_artifact, - 924 uninstanced_item_objectives=uninstanced_item_objectives, - 925 ) - 926 - 927 def deserialize_character_progressions_mapping( - 928 self, payload: typedefs.JSONObject - 929 ) -> collections.Mapping[int, character.CharacterProgression]: - 930 character_progressions: collections.Mapping[ - 931 int, character.CharacterProgression - 932 ] = {} - 933 for char_id, data in payload["data"].items(): - 934 # A little hack to stop mypy complaining about Mapping <-> dict - 935 character_progressions[int(char_id)] = self.deserialize_character_progressions(data) # type: ignore[index] - 936 return character_progressions - 937 - 938 def deserialize_characters_records( - 939 self, - 940 payload: typedefs.JSONObject, - 941 ) -> collections.Mapping[int, records.CharacterRecord]: - 942 - 943 return { - 944 int(rec_id): self.deserialize_character_records( - 945 rec, record_hashes=payload.get("featuredRecordHashes") - 946 ) - 947 for rec_id, rec in payload["records"].items() - 948 } - 949 - 950 def deserialize_profile_records( - 951 self, payload: typedefs.JSONObject - 952 ) -> collections.Mapping[int, records.Record]: - 953 raw_profile_records = payload["data"] - 954 scores = records.RecordScores( - 955 current_score=raw_profile_records["score"], - 956 legacy_score=raw_profile_records["legacyScore"], - 957 lifetime_score=raw_profile_records["lifetimeScore"], - 958 ) - 959 return { - 960 int(record_id): self.deserialize_records( - 961 record, - 962 scores, - 963 categories_hash=raw_profile_records["recordCategoriesRootNodeHash"], - 964 seals_hash=raw_profile_records["recordSealsRootNodeHash"], - 965 ) - 966 for record_id, record in raw_profile_records["records"].items() - 967 } - 968 - 969 def _deserialize_craftable_socket_plug( - 970 self, payload: typedefs.JSONObject - 971 ) -> items.CraftableSocketPlug: - 972 return items.CraftableSocketPlug( - 973 item_hash=int(payload["plugItemHash"]), - 974 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), - 975 ) - 976 - 977 def _deserialize_craftable_socket( - 978 self, payload: typedefs.JSONObject - 979 ) -> items.CraftableSocket: + 445 return profile.ProfileItemImpl( + 446 net=self._net, + 447 hash=payload["itemHash"], + 448 quantity=payload["quantity"], + 449 bind_status=enums.ItemBindStatus(payload["bindStatus"]), + 450 location=enums.ItemLocation(payload["location"]), + 451 bucket=payload["bucketHash"], + 452 transfer_status=transfer_status, + 453 lockable=payload["lockable"], + 454 state=enums.ItemState(payload["state"]), + 455 dismantel_permissions=payload["dismantlePermission"], + 456 is_wrapper=payload["isWrapper"], + 457 instance_id=instance_id, + 458 version_number=version_number, + 459 ornament_id=payload.get("overrideStyleItemHash"), + 460 ) + 461 + 462 def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective: + 463 return records.Objective( + 464 net=self._net, + 465 hash=payload["objectiveHash"], + 466 visible=payload["visible"], + 467 complete=payload["complete"], + 468 completion_value=payload["completionValue"], + 469 progress=payload.get("progress"), + 470 destination_hash=payload.get("destinationHash"), + 471 activity_hash=payload.get("activityHash"), + 472 ) + 473 + 474 def deserialize_records( + 475 self, + 476 payload: typedefs.JSONObject, + 477 scores: typing.Optional[records.RecordScores] = None, + 478 **nodes: int, + 479 ) -> records.Record: + 480 objectives: typing.Optional[list[records.Objective]] = None + 481 interval_objectives: typing.Optional[list[records.Objective]] = None + 482 record_state: typedefs.IntAnd[records.RecordState] + 483 + 484 record_state = records.RecordState(payload["state"]) + 485 + 486 if raw_objs := payload.get("objectives"): + 487 objectives = [self.deserialize_objectives(obj) for obj in raw_objs] + 488 + 489 if raw_interval_objs := payload.get("intervalObjectives"): + 490 interval_objectives = [ + 491 self.deserialize_objectives(obj) for obj in raw_interval_objs + 492 ] + 493 + 494 return records.Record( + 495 scores=scores, + 496 categories_node_hash=nodes.get("categories_hash", undefined.Undefined), + 497 seals_node_hash=nodes.get("seals_hash", undefined.Undefined), + 498 state=record_state, + 499 objectives=objectives, + 500 interval_objectives=interval_objectives, + 501 redeemed_count=payload.get("intervalsRedeemedCount", 0), + 502 completion_times=payload.get("completedCount", None), + 503 reward_visibility=payload.get("rewardVisibilty", None), + 504 ) + 505 + 506 def deserialize_character_records( + 507 self, + 508 payload: typedefs.JSONObject, + 509 scores: typing.Optional[records.RecordScores] = None, + 510 record_hashes: typing.Optional[list[int]] = None, + 511 ) -> records.CharacterRecord: + 512 + 513 record = self.deserialize_records(payload, scores) + 514 return records.CharacterRecord( + 515 scores=scores, + 516 categories_node_hash=record.categories_node_hash, + 517 seals_node_hash=record.seals_node_hash, + 518 state=record.state, + 519 objectives=record.objectives, + 520 interval_objectives=record.interval_objectives, + 521 redeemed_count=payload.get("intervalsRedeemedCount", 0), + 522 completion_times=payload.get("completedCount"), + 523 reward_visibility=payload.get("rewardVisibilty"), + 524 record_hashes=record_hashes or [], + 525 ) + 526 + 527 def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye: + 528 return character.Dye( + 529 channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"] + 530 ) + 531 + 532 def deserialize_character_customization( + 533 self, payload: typedefs.JSONObject + 534 ) -> character.CustomizationOptions: + 535 return character.CustomizationOptions( + 536 personality=payload["personality"], + 537 face=payload["face"], + 538 skin_color=payload["skinColor"], + 539 lip_color=payload["lipColor"], + 540 eye_color=payload["eyeColor"], + 541 hair_colors=payload.get("hairColors", []), + 542 feature_colors=payload.get("featureColors", []), + 543 decal_color=payload["decalColor"], + 544 wear_helmet=payload["wearHelmet"], + 545 hair_index=payload["hairIndex"], + 546 feature_index=payload["featureIndex"], + 547 decal_index=payload["decalIndex"], + 548 ) + 549 + 550 def deserialize_character_minimal_equipments( + 551 self, payload: typedefs.JSONObject + 552 ) -> character.MinimalEquipments: + 553 dyes = None + 554 if raw_dyes := payload.get("dyes"): + 555 if raw_dyes: + 556 dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes] + 557 return character.MinimalEquipments( + 558 net=self._net, item_hash=payload["itemHash"], dyes=dyes + 559 ) + 560 + 561 def deserialize_character_render_data( + 562 self, payload: typedefs.JSONObject, / + 563 ) -> character.RenderedData: + 564 return character.RenderedData( + 565 net=self._net, + 566 customization=self.deserialize_character_customization( + 567 payload["customization"] + 568 ), + 569 custom_dyes=[ + 570 self.deserialize_character_dye(dye) + 571 for dye in payload["customDyes"] + 572 if dye + 573 ], + 574 equipment=[ + 575 self.deserialize_character_minimal_equipments(equipment) + 576 for equipment in payload["peerView"]["equipment"] + 577 ], + 578 ) + 579 + 580 def deserialize_available_activity( + 581 self, payload: typedefs.JSONObject + 582 ) -> activity.AvailableActivity: + 583 return activity.AvailableActivity( + 584 hash=payload["activityHash"], + 585 is_new=payload["isNew"], + 586 is_completed=payload["isCompleted"], + 587 is_visible=payload["isVisible"], + 588 display_level=payload.get("displayLevel"), + 589 recommended_light=payload.get("recommendedLight"), + 590 difficulty=activity.Difficulty(payload["difficultyTier"]), + 591 can_join=payload["canJoin"], + 592 can_lead=payload["canLead"], + 593 ) + 594 + 595 def deserialize_character_activity( + 596 self, payload: typedefs.JSONObject + 597 ) -> activity.CharacterActivity: + 598 current_mode: typing.Optional[enums.GameMode] = None + 599 if raw_current_mode := payload.get("currentActivityModeType"): + 600 current_mode = enums.GameMode(raw_current_mode) + 601 + 602 current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None + 603 if raw_current_modes := payload.get("currentActivityModeTypes"): + 604 current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes] + 605 + 606 return activity.CharacterActivity( + 607 date_started=time.clean_date(payload["dateActivityStarted"]), + 608 current_hash=payload["currentActivityHash"], + 609 current_mode_hash=payload["currentActivityModeHash"], + 610 current_mode=current_mode, + 611 current_mode_hashes=payload.get("currentActivityModeHashes"), + 612 current_mode_types=current_mode_types, + 613 current_playlist_hash=payload.get("currentPlaylistActivityHash"), + 614 last_story_hash=payload["lastCompletedStoryHash"], + 615 available_activities=[ + 616 self.deserialize_available_activity(activity_) + 617 for activity_ in payload["availableActivities"] + 618 ], + 619 ) + 620 + 621 def deserialize_profile_items( + 622 self, payload: typedefs.JSONObject, / + 623 ) -> list[profile.ProfileItemImpl]: + 624 return [self.deserialize_profile_item(item) for item in payload["items"]] + 625 + 626 def _deserialize_node(self, payload: typedefs.JSONObject) -> records.Node: + 627 return records.Node( + 628 state=int(payload["state"]), + 629 objective=self.deserialize_objectives(payload["objective"]) + 630 if "objective" in payload + 631 else None, + 632 progress_value=int(payload["progressValue"]), + 633 completion_value=int(payload["completionValue"]), + 634 record_category_score=int(payload["recordCategoryScore"]) + 635 if "recordCategoryScore" in payload + 636 else None, + 637 ) + 638 + 639 @staticmethod + 640 def _deserialize_collectible(payload: typedefs.JSONObject) -> items.Collectible: + 641 recent_collectibles: typing.Optional[collections.Collection[int]] = None + 642 if raw_recent_collectibles := payload.get("recentCollectibleHashes"): + 643 recent_collectibles = [ + 644 int(item_hash) for item_hash in raw_recent_collectibles + 645 ] + 646 + 647 collectibles: dict[int, int] = {} + 648 for item_hash, mapping in payload["collectibles"].items(): + 649 collectibles[int(item_hash)] = int(mapping["state"]) + 650 + 651 return items.Collectible( + 652 recent_collectibles=recent_collectibles, + 653 collectibles=collectibles, + 654 collection_categorie_hash=int(payload["collectionCategoriesRootNodeHash"]), + 655 collection_badges_hash=int(payload["collectionBadgesRootNodeHash"]), + 656 ) + 657 + 658 @staticmethod + 659 def _deserialize_currencies( + 660 payload: typedefs.JSONObject, + 661 ) -> collections.Sequence[items.Currency]: + 662 return [ + 663 items.Currency(hash=int(item_hash), amount=int(amount)) + 664 for item_hash, amount in payload["itemQuantities"].items() + 665 ] + 666 + 667 def deserialize_progressions( + 668 self, payload: typedefs.JSONObject + 669 ) -> progressions.Progression: + 670 return progressions.Progression( + 671 hash=int(payload["progressionHash"]), + 672 level=int(payload["level"]), + 673 cap=int(payload["levelCap"]), + 674 daily_limit=int(payload["dailyLimit"]), + 675 weekly_limit=int(payload["weeklyLimit"]), + 676 current_progress=int(payload["currentProgress"]), + 677 daily_progress=int(payload["dailyProgress"]), + 678 needed=int(payload["progressToNextLevel"]), + 679 next_level=int(payload["nextLevelAt"]), + 680 ) + 681 + 682 def _deserialize_factions( + 683 self, payload: typedefs.JSONObject + 684 ) -> progressions.Factions: + 685 progs = self.deserialize_progressions(payload) + 686 return progressions.Factions( + 687 hash=progs.hash, + 688 level=progs.level, + 689 cap=progs.cap, + 690 daily_limit=progs.daily_limit, + 691 weekly_limit=progs.weekly_limit, + 692 current_progress=progs.current_progress, + 693 daily_progress=progs.daily_progress, + 694 needed=progs.needed, + 695 next_level=progs.next_level, + 696 faction_hash=payload["factionHash"], + 697 faction_vendor_hash=payload["factionVendorIndex"], + 698 ) + 699 + 700 def _deserialize_milestone_available_quest( + 701 self, payload: typedefs.JSONObject + 702 ) -> milestones.MilestoneQuest: + 703 return milestones.MilestoneQuest( + 704 item_hash=payload["questItemHash"], + 705 status=self._deserialize_milestone_quest_status(payload["status"]), + 706 ) + 707 + 708 def _deserialize_milestone_activity( + 709 self, payload: typedefs.JSONObject + 710 ) -> milestones.MilestoneActivity: + 711 + 712 phases: typing.Optional[ + 713 collections.Sequence[milestones.MilestoneActivityPhase] + 714 ] = None + 715 if raw_phases := payload.get("phases"): + 716 phases = [ + 717 milestones.MilestoneActivityPhase( + 718 is_completed=obj["complete"], hash=obj["phaseHash"] + 719 ) + 720 for obj in raw_phases + 721 ] + 722 + 723 return milestones.MilestoneActivity( + 724 hash=payload["activityHash"], + 725 challenges=[ + 726 self.deserialize_objectives(obj["objective"]) + 727 for obj in payload["challenges"] + 728 ], + 729 modifier_hashes=payload.get("modifierHashes"), + 730 boolean_options=payload.get("booleanActivityOptions"), + 731 phases=phases, + 732 ) + 733 + 734 def _deserialize_milestone_quest_status( + 735 self, payload: typedefs.JSONObject + 736 ) -> milestones.QuestStatus: + 737 return milestones.QuestStatus( + 738 net=self._net, + 739 quest_hash=payload["questHash"], + 740 step_hash=payload["stepHash"], + 741 step_objectives=[ + 742 self.deserialize_objectives(objective) + 743 for objective in payload["stepObjectives"] + 744 ], + 745 is_tracked=payload["tracked"], + 746 is_completed=payload["completed"], + 747 started=payload["started"], + 748 item_instance_id=payload["itemInstanceId"], + 749 vendor_hash=payload.get("vendorHash"), + 750 is_redeemed=payload["redeemed"], + 751 ) + 752 + 753 def _deserialize_milestone_rewards( + 754 self, payload: typedefs.JSONObject + 755 ) -> milestones.MilestoneReward: + 756 return milestones.MilestoneReward( + 757 category_hash=payload["rewardCategoryHash"], + 758 entries=[ + 759 milestones.MilestoneRewardEntry( + 760 entry_hash=entry["rewardEntryHash"], + 761 is_earned=entry["earned"], + 762 is_redeemed=entry["redeemed"], + 763 ) + 764 for entry in payload["entries"] + 765 ], + 766 ) + 767 + 768 def deserialize_milestone( + 769 self, payload: typedefs.JSONObject + 770 ) -> milestones.Milestone: + 771 start_date: typing.Optional[datetime.datetime] = None + 772 if raw_start_date := payload.get("startDate"): + 773 start_date = time.clean_date(raw_start_date) + 774 + 775 end_date: typing.Optional[datetime.datetime] = None + 776 if raw_end_date := payload.get("endDate"): + 777 end_date = time.clean_date(raw_end_date) + 778 + 779 rewards: typing.Optional[ + 780 collections.Collection[milestones.MilestoneReward] + 781 ] = None + 782 if raw_rewards := payload.get("rewards"): + 783 rewards = [ + 784 self._deserialize_milestone_rewards(reward) for reward in raw_rewards + 785 ] + 786 + 787 activities: typing.Optional[ + 788 collections.Sequence[milestones.MilestoneActivity] + 789 ] = None + 790 if raw_activities := payload.get("activities"): + 791 activities = [ + 792 self._deserialize_milestone_activity(active) + 793 for active in raw_activities + 794 ] + 795 + 796 quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None + 797 if raw_quests := payload.get("availableQuests"): + 798 quests = [ + 799 self._deserialize_milestone_available_quest(quest) + 800 for quest in raw_quests + 801 ] + 802 + 803 vendors: typing.Optional[ + 804 collections.Sequence[milestones.MilestoneVendor] + 805 ] = None + 806 if raw_vendors := payload.get("vendors"): + 807 vendors = [ + 808 milestones.MilestoneVendor( + 809 vendor_hash=vendor["vendorHash"], + 810 preview_itemhash=vendor.get("previewItemHash"), + 811 ) + 812 for vendor in raw_vendors + 813 ] + 814 + 815 return milestones.Milestone( + 816 hash=payload["milestoneHash"], + 817 start_date=start_date, + 818 end_date=end_date, + 819 order=payload["order"], + 820 rewards=rewards, + 821 available_quests=quests, + 822 activities=activities, + 823 vendors=vendors, + 824 ) + 825 + 826 def _deserialize_artifact_tiers( + 827 self, payload: typedefs.JSONObject + 828 ) -> season.ArtifactTier: + 829 return season.ArtifactTier( + 830 hash=payload["tierHash"], + 831 is_unlocked=payload["isUnlocked"], + 832 points_to_unlock=payload["pointsToUnlock"], + 833 items=[ + 834 season.ArtifactTierItem( + 835 hash=item["itemHash"], is_active=item["isActive"] + 836 ) + 837 for item in payload["items"] + 838 ], + 839 ) + 840 + 841 def deserialize_characters( + 842 self, payload: typedefs.JSONObject + 843 ) -> collections.Mapping[int, character.Character]: + 844 return { + 845 int(char_id): self._set_character_attrs(char) + 846 for char_id, char in payload["data"].items() + 847 } + 848 + 849 def deserialize_character( + 850 self, payload: typedefs.JSONObject + 851 ) -> character.Character: + 852 return self._set_character_attrs(payload) + 853 + 854 def deserialize_character_equipments( + 855 self, payload: typedefs.JSONObject + 856 ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]: + 857 return { + 858 int(char_id): self.deserialize_profile_items(item) + 859 for char_id, item in payload["data"].items() + 860 } + 861 + 862 def deserialize_character_activities( + 863 self, payload: typedefs.JSONObject + 864 ) -> collections.Mapping[int, activity.CharacterActivity]: + 865 return { + 866 int(char_id): self.deserialize_character_activity(data) + 867 for char_id, data in payload["data"].items() + 868 } + 869 + 870 def deserialize_characters_render_data( + 871 self, payload: typedefs.JSONObject + 872 ) -> collections.Mapping[int, character.RenderedData]: + 873 return { + 874 int(char_id): self.deserialize_character_render_data(data) + 875 for char_id, data in payload["data"].items() + 876 } + 877 + 878 def deserialize_character_progressions( + 879 self, payload: typedefs.JSONObject + 880 ) -> character.CharacterProgression: + 881 progressions_ = { + 882 int(prog_id): self.deserialize_progressions(prog) + 883 for prog_id, prog in payload["progressions"].items() + 884 } + 885 + 886 factions = { + 887 int(faction_id): self._deserialize_factions(faction) + 888 for faction_id, faction in payload["factions"].items() + 889 } + 890 + 891 milestones_ = { + 892 int(milestone_hash): self.deserialize_milestone(milestone) + 893 for milestone_hash, milestone in payload["milestones"].items() + 894 } + 895 + 896 uninstanced_item_objectives = { + 897 int(item_hash): [self.deserialize_objectives(ins) for ins in obj] + 898 for item_hash, obj in payload["uninstancedItemObjectives"].items() + 899 } + 900 + 901 artifact = payload["seasonalArtifact"] + 902 seasonal_artifact = season.CharacterScopedArtifact( + 903 hash=artifact["artifactHash"], + 904 points_used=artifact["pointsUsed"], + 905 reset_count=artifact["resetCount"], + 906 tiers=[ + 907 self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"] + 908 ], + 909 ) + 910 checklists = payload["checklists"] + 911 + 912 return character.CharacterProgression( + 913 progressions=progressions_, + 914 factions=factions, + 915 checklists=checklists, + 916 milestones=milestones_, + 917 seasonal_artifact=seasonal_artifact, + 918 uninstanced_item_objectives=uninstanced_item_objectives, + 919 ) + 920 + 921 def deserialize_character_progressions_mapping( + 922 self, payload: typedefs.JSONObject + 923 ) -> collections.Mapping[int, character.CharacterProgression]: + 924 character_progressions: collections.Mapping[ + 925 int, character.CharacterProgression + 926 ] = {} + 927 for char_id, data in payload["data"].items(): + 928 # A little hack to stop mypy complaining about Mapping <-> dict + 929 character_progressions[int(char_id)] = self.deserialize_character_progressions(data) # type: ignore[index] + 930 return character_progressions + 931 + 932 def deserialize_characters_records( + 933 self, + 934 payload: typedefs.JSONObject, + 935 ) -> collections.Mapping[int, records.CharacterRecord]: + 936 + 937 return { + 938 int(rec_id): self.deserialize_character_records( + 939 rec, record_hashes=payload.get("featuredRecordHashes") + 940 ) + 941 for rec_id, rec in payload["records"].items() + 942 } + 943 + 944 def deserialize_profile_records( + 945 self, payload: typedefs.JSONObject + 946 ) -> collections.Mapping[int, records.Record]: + 947 raw_profile_records = payload["data"] + 948 scores = records.RecordScores( + 949 current_score=raw_profile_records["score"], + 950 legacy_score=raw_profile_records["legacyScore"], + 951 lifetime_score=raw_profile_records["lifetimeScore"], + 952 ) + 953 return { + 954 int(record_id): self.deserialize_records( + 955 record, + 956 scores, + 957 categories_hash=raw_profile_records["recordCategoriesRootNodeHash"], + 958 seals_hash=raw_profile_records["recordSealsRootNodeHash"], + 959 ) + 960 for record_id, record in raw_profile_records["records"].items() + 961 } + 962 + 963 def _deserialize_craftable_socket_plug( + 964 self, payload: typedefs.JSONObject + 965 ) -> items.CraftableSocketPlug: + 966 return items.CraftableSocketPlug( + 967 item_hash=int(payload["plugItemHash"]), + 968 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), + 969 ) + 970 + 971 def _deserialize_craftable_socket( + 972 self, payload: typedefs.JSONObject + 973 ) -> items.CraftableSocket: + 974 + 975 plugs: list[items.CraftableSocketPlug] = [] + 976 if raw_plug := payload.get("plug"): + 977 plugs.extend( + 978 self._deserialize_craftable_socket_plug(plug) for plug in raw_plug + 979 ) 980 - 981 plugs: list[items.CraftableSocketPlug] = [] - 982 if raw_plug := payload.get("plug"): - 983 plugs.extend( - 984 self._deserialize_craftable_socket_plug(plug) for plug in raw_plug - 985 ) - 986 - 987 return items.CraftableSocket( - 988 plug_set_hash=int(payload["plugSetHash"]), plugs=plugs - 989 ) - 990 - 991 def _deserialize_craftable_item( - 992 self, payload: typedefs.JSONObject - 993 ) -> items.CraftableItem: - 994 - 995 return items.CraftableItem( - 996 is_visible=payload["visible"], - 997 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), - 998 sockets=[ - 999 self._deserialize_craftable_socket(socket) -1000 for socket in payload["sockets"] -1001 ], -1002 ) -1003 -1004 def deserialize_craftables_component( -1005 self, payload: typedefs.JSONObject -1006 ) -> components.CraftablesComponent: -1007 return components.CraftablesComponent( -1008 net=self._net, -1009 craftables={ -1010 int(item_id): self._deserialize_craftable_item(item) -1011 for item_id, item in payload["craftables"].items() -1012 if item is not None -1013 }, -1014 crafting_root_node_hash=payload["craftingRootNodeHash"], -1015 ) -1016 -1017 def deserialize_components( # noqa: C901 Too complex. -1018 self, payload: typedefs.JSONObject -1019 ) -> components.Component: -1020 -1021 profile_: typing.Optional[profile.Profile] = None -1022 if raw_profile := payload.get("profile"): -1023 profile_ = self.deserialize_profile(raw_profile) + 981 return items.CraftableSocket( + 982 plug_set_hash=int(payload["plugSetHash"]), plugs=plugs + 983 ) + 984 + 985 def _deserialize_craftable_item( + 986 self, payload: typedefs.JSONObject + 987 ) -> items.CraftableItem: + 988 + 989 return items.CraftableItem( + 990 is_visible=payload["visible"], + 991 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), + 992 sockets=[ + 993 self._deserialize_craftable_socket(socket) + 994 for socket in payload["sockets"] + 995 ], + 996 ) + 997 + 998 def deserialize_craftables_component( + 999 self, payload: typedefs.JSONObject +1000 ) -> components.CraftablesComponent: +1001 return components.CraftablesComponent( +1002 net=self._net, +1003 craftables={ +1004 int(item_id): self._deserialize_craftable_item(item) +1005 for item_id, item in payload["craftables"].items() +1006 if item is not None +1007 }, +1008 crafting_root_node_hash=payload["craftingRootNodeHash"], +1009 ) +1010 +1011 def deserialize_components( # noqa: C901 Too complex. +1012 self, payload: typedefs.JSONObject +1013 ) -> components.Component: +1014 +1015 profile_: typing.Optional[profile.Profile] = None +1016 if raw_profile := payload.get("profile"): +1017 profile_ = self.deserialize_profile(raw_profile) +1018 +1019 profile_progression: typing.Optional[profile.ProfileProgression] = None +1020 if raw_profile_progression := payload.get("profileProgression"): +1021 profile_progression = self.deserialize_profile_progression( +1022 raw_profile_progression +1023 ) 1024 -1025 profile_progression: typing.Optional[profile.ProfileProgression] = None -1026 if raw_profile_progression := payload.get("profileProgression"): -1027 profile_progression = self.deserialize_profile_progression( -1028 raw_profile_progression -1029 ) -1030 -1031 profile_currencies: typing.Optional[ -1032 collections.Sequence[profile.ProfileItemImpl] -1033 ] = None -1034 if raw_profile_currencies := payload.get("profileCurrencies"): -1035 if "data" in raw_profile_currencies: -1036 profile_currencies = self.deserialize_profile_items( -1037 raw_profile_currencies["data"] -1038 ) -1039 -1040 profile_inventories: typing.Optional[ -1041 collections.Sequence[profile.ProfileItemImpl] -1042 ] = None -1043 if raw_profile_inventories := payload.get("profileInventory"): -1044 if "data" in raw_profile_inventories: -1045 profile_inventories = self.deserialize_profile_items( -1046 raw_profile_inventories["data"] -1047 ) -1048 -1049 profile_records: typing.Optional[ -1050 collections.Mapping[int, records.Record] -1051 ] = None -1052 -1053 if raw_profile_records_ := payload.get("profileRecords"): -1054 profile_records = self.deserialize_profile_records(raw_profile_records_) -1055 -1056 characters: typing.Optional[typing.Mapping[int, character.Character]] = None -1057 if raw_characters := payload.get("characters"): -1058 characters = self.deserialize_characters(raw_characters) -1059 -1060 character_records: typing.Optional[ -1061 collections.Mapping[int, records.CharacterRecord] -1062 ] = None -1063 -1064 if raw_character_records := payload.get("characterRecords"): -1065 # Had to do it in two steps.. -1066 to_update: typedefs.JSONObject = {} -1067 for _, data in raw_character_records["data"].items(): -1068 for record_id, record in data.items(): -1069 to_update[record_id] = record -1070 -1071 character_records = { -1072 int(rec_id): self.deserialize_character_records( -1073 rec, record_hashes=to_update.get("featuredRecordHashes") -1074 ) -1075 for rec_id, rec in to_update["records"].items() -1076 } -1077 -1078 character_equipments: typing.Optional[ -1079 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] -1080 ] = None -1081 if raw_character_equips := payload.get("characterEquipment"): -1082 character_equipments = self.deserialize_character_equipments( -1083 raw_character_equips -1084 ) -1085 -1086 character_inventories: typing.Optional[ -1087 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] -1088 ] = None -1089 if raw_character_inventories := payload.get("characterInventories"): -1090 if "data" in raw_character_inventories: -1091 character_inventories = self.deserialize_character_equipments( -1092 raw_character_inventories -1093 ) +1025 profile_currencies: typing.Optional[ +1026 collections.Sequence[profile.ProfileItemImpl] +1027 ] = None +1028 if raw_profile_currencies := payload.get("profileCurrencies"): +1029 if "data" in raw_profile_currencies: +1030 profile_currencies = self.deserialize_profile_items( +1031 raw_profile_currencies["data"] +1032 ) +1033 +1034 profile_inventories: typing.Optional[ +1035 collections.Sequence[profile.ProfileItemImpl] +1036 ] = None +1037 if raw_profile_inventories := payload.get("profileInventory"): +1038 if "data" in raw_profile_inventories: +1039 profile_inventories = self.deserialize_profile_items( +1040 raw_profile_inventories["data"] +1041 ) +1042 +1043 profile_records: typing.Optional[ +1044 collections.Mapping[int, records.Record] +1045 ] = None +1046 +1047 if raw_profile_records_ := payload.get("profileRecords"): +1048 profile_records = self.deserialize_profile_records(raw_profile_records_) +1049 +1050 characters: typing.Optional[typing.Mapping[int, character.Character]] = None +1051 if raw_characters := payload.get("characters"): +1052 characters = self.deserialize_characters(raw_characters) +1053 +1054 character_records: typing.Optional[ +1055 collections.Mapping[int, records.CharacterRecord] +1056 ] = None +1057 +1058 if raw_character_records := payload.get("characterRecords"): +1059 # Had to do it in two steps.. +1060 to_update: typedefs.JSONObject = {} +1061 for _, data in raw_character_records["data"].items(): +1062 for record_id, record in data.items(): +1063 to_update[record_id] = record +1064 +1065 character_records = { +1066 int(rec_id): self.deserialize_character_records( +1067 rec, record_hashes=to_update.get("featuredRecordHashes") +1068 ) +1069 for rec_id, rec in to_update["records"].items() +1070 } +1071 +1072 character_equipments: typing.Optional[ +1073 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] +1074 ] = None +1075 if raw_character_equips := payload.get("characterEquipment"): +1076 character_equipments = self.deserialize_character_equipments( +1077 raw_character_equips +1078 ) +1079 +1080 character_inventories: typing.Optional[ +1081 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] +1082 ] = None +1083 if raw_character_inventories := payload.get("characterInventories"): +1084 if "data" in raw_character_inventories: +1085 character_inventories = self.deserialize_character_equipments( +1086 raw_character_inventories +1087 ) +1088 +1089 character_activities: typing.Optional[ +1090 collections.Mapping[int, activity.CharacterActivity] +1091 ] = None +1092 if raw_char_acts := payload.get("characterActivities"): +1093 character_activities = self.deserialize_character_activities(raw_char_acts) 1094 -1095 character_activities: typing.Optional[ -1096 collections.Mapping[int, activity.CharacterActivity] +1095 character_render_data: typing.Optional[ +1096 collections.Mapping[int, character.RenderedData] 1097 ] = None -1098 if raw_char_acts := payload.get("characterActivities"): -1099 character_activities = self.deserialize_character_activities(raw_char_acts) -1100 -1101 character_render_data: typing.Optional[ -1102 collections.Mapping[int, character.RenderedData] -1103 ] = None -1104 if raw_character_render_data := payload.get("characterRenderData"): -1105 character_render_data = self.deserialize_characters_render_data( -1106 raw_character_render_data -1107 ) -1108 -1109 character_progressions: typing.Optional[ -1110 collections.Mapping[int, character.CharacterProgression] -1111 ] = None -1112 -1113 if raw_character_progressions := payload.get("characterProgressions"): -1114 character_progressions = self.deserialize_character_progressions_mapping( -1115 raw_character_progressions -1116 ) -1117 -1118 profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None -1119 if raw_profile_string_vars := payload.get("profileStringVariables"): -1120 profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"] -1121 -1122 character_string_vars: typing.Optional[ -1123 collections.Mapping[int, collections.Mapping[int, int]] -1124 ] = None -1125 if raw_character_string_vars := payload.get("characterStringVariables"): -1126 character_string_vars = { -1127 int(char_id): data["integerValuesByHash"] -1128 for char_id, data in raw_character_string_vars["data"].items() -1129 } -1130 -1131 metrics: typing.Optional[ -1132 collections.Sequence[ -1133 collections.Mapping[ -1134 int, tuple[bool, typing.Optional[records.Objective]] -1135 ] -1136 ] -1137 ] = None -1138 root_node_hash: typing.Optional[int] = None -1139 -1140 if raw_metrics := payload.get("metrics"): -1141 root_node_hash = raw_metrics["data"]["metricsRootNodeHash"] -1142 metrics = [ -1143 { -1144 int(metrics_hash): ( -1145 data["invisible"], -1146 self.deserialize_objectives(data["objectiveProgress"]) -1147 if "objectiveProgress" in data -1148 else None, -1149 ) -1150 for metrics_hash, data in raw_metrics["data"]["metrics"].items() -1151 } -1152 ] -1153 transitory: typing.Optional[fireteams.FireteamParty] = None -1154 if raw_transitory := payload.get("profileTransitoryData"): -1155 if "data" in raw_transitory: -1156 transitory = self.deserialize_fireteam_party(raw_transitory["data"]) -1157 -1158 item_components: typing.Optional[components.ItemsComponent] = None -1159 if raw_item_components := payload.get("itemComponents"): -1160 item_components = self.deserialize_items_component(raw_item_components) -1161 -1162 profile_plugsets: typing.Optional[ -1163 collections.Mapping[int, collections.Sequence[items.PlugItemState]] -1164 ] = None +1098 if raw_character_render_data := payload.get("characterRenderData"): +1099 character_render_data = self.deserialize_characters_render_data( +1100 raw_character_render_data +1101 ) +1102 +1103 character_progressions: typing.Optional[ +1104 collections.Mapping[int, character.CharacterProgression] +1105 ] = None +1106 +1107 if raw_character_progressions := payload.get("characterProgressions"): +1108 character_progressions = self.deserialize_character_progressions_mapping( +1109 raw_character_progressions +1110 ) +1111 +1112 profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None +1113 if raw_profile_string_vars := payload.get("profileStringVariables"): +1114 profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"] +1115 +1116 character_string_vars: typing.Optional[ +1117 collections.Mapping[int, collections.Mapping[int, int]] +1118 ] = None +1119 if raw_character_string_vars := payload.get("characterStringVariables"): +1120 character_string_vars = { +1121 int(char_id): data["integerValuesByHash"] +1122 for char_id, data in raw_character_string_vars["data"].items() +1123 } +1124 +1125 metrics: typing.Optional[ +1126 collections.Sequence[ +1127 collections.Mapping[ +1128 int, tuple[bool, typing.Optional[records.Objective]] +1129 ] +1130 ] +1131 ] = None +1132 root_node_hash: typing.Optional[int] = None +1133 +1134 if raw_metrics := payload.get("metrics"): +1135 root_node_hash = raw_metrics["data"]["metricsRootNodeHash"] +1136 metrics = [ +1137 { +1138 int(metrics_hash): ( +1139 data["invisible"], +1140 self.deserialize_objectives(data["objectiveProgress"]) +1141 if "objectiveProgress" in data +1142 else None, +1143 ) +1144 for metrics_hash, data in raw_metrics["data"]["metrics"].items() +1145 } +1146 ] +1147 transitory: typing.Optional[fireteams.FireteamParty] = None +1148 if raw_transitory := payload.get("profileTransitoryData"): +1149 if "data" in raw_transitory: +1150 transitory = self.deserialize_fireteam_party(raw_transitory["data"]) +1151 +1152 item_components: typing.Optional[components.ItemsComponent] = None +1153 if raw_item_components := payload.get("itemComponents"): +1154 item_components = self.deserialize_items_component(raw_item_components) +1155 +1156 profile_plugsets: typing.Optional[ +1157 collections.Mapping[int, collections.Sequence[items.PlugItemState]] +1158 ] = None +1159 +1160 if raw_profile_plugs := payload.get("profilePlugSets"): +1161 profile_plugsets = { +1162 int(index): [self.deserialize_plug_item_state(state) for state in data] +1163 for index, data in raw_profile_plugs["data"]["plugs"].items() +1164 } 1165 -1166 if raw_profile_plugs := payload.get("profilePlugSets"): -1167 profile_plugsets = { -1168 int(index): [self.deserialize_plug_item_state(state) for state in data] -1169 for index, data in raw_profile_plugs["data"]["plugs"].items() -1170 } -1171 -1172 character_plugsets: typing.Optional[ -1173 collections.Mapping[ -1174 int, collections.Mapping[int, collections.Sequence[items.PlugItemState]] -1175 ] -1176 ] = None -1177 if raw_char_plugsets := payload.get("characterPlugSets"): -1178 character_plugsets = { -1179 int(char_id): { -1180 int(index): [ -1181 self.deserialize_plug_item_state(state) for state in data -1182 ] -1183 for index, data in inner["plugs"].items() -1184 } -1185 for char_id, inner in raw_char_plugsets["data"].items() -1186 } -1187 -1188 character_collectibles: typing.Optional[ -1189 collections.Mapping[int, items.Collectible] -1190 ] = None -1191 if raw_character_collectibles := payload.get("characterCollectibles"): -1192 character_collectibles = { -1193 int(char_id): self._deserialize_collectible(data) -1194 for char_id, data in raw_character_collectibles["data"].items() -1195 } +1166 character_plugsets: typing.Optional[ +1167 collections.Mapping[ +1168 int, collections.Mapping[int, collections.Sequence[items.PlugItemState]] +1169 ] +1170 ] = None +1171 if raw_char_plugsets := payload.get("characterPlugSets"): +1172 character_plugsets = { +1173 int(char_id): { +1174 int(index): [ +1175 self.deserialize_plug_item_state(state) for state in data +1176 ] +1177 for index, data in inner["plugs"].items() +1178 } +1179 for char_id, inner in raw_char_plugsets["data"].items() +1180 } +1181 +1182 character_collectibles: typing.Optional[ +1183 collections.Mapping[int, items.Collectible] +1184 ] = None +1185 if raw_character_collectibles := payload.get("characterCollectibles"): +1186 character_collectibles = { +1187 int(char_id): self._deserialize_collectible(data) +1188 for char_id, data in raw_character_collectibles["data"].items() +1189 } +1190 +1191 profile_collectibles: typing.Optional[items.Collectible] = None +1192 if raw_profile_collectibles := payload.get("profileCollectibles"): +1193 profile_collectibles = self._deserialize_collectible( +1194 raw_profile_collectibles["data"] +1195 ) 1196 -1197 profile_collectibles: typing.Optional[items.Collectible] = None -1198 if raw_profile_collectibles := payload.get("profileCollectibles"): -1199 profile_collectibles = self._deserialize_collectible( -1200 raw_profile_collectibles["data"] -1201 ) -1202 -1203 profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None -1204 if raw_profile_nodes := payload.get("profilePresentationNodes"): -1205 profile_nodes = { -1206 int(node_hash): self._deserialize_node(node) -1207 for node_hash, node in raw_profile_nodes["data"]["nodes"].items() -1208 } -1209 -1210 character_nodes: typing.Optional[ -1211 collections.Mapping[int, collections.Mapping[int, records.Node]] -1212 ] = None -1213 if raw_character_nodes := payload.get("characterPresentationNodes"): -1214 character_nodes = { -1215 int(char_id): { -1216 int(node_hash): self._deserialize_node(node) -1217 for node_hash, node in each_character["nodes"].items() -1218 } -1219 for char_id, each_character in raw_character_nodes["data"].items() -1220 } -1221 -1222 platform_silver: typing.Optional[ -1223 collections.Mapping[str, profile.ProfileItemImpl] -1224 ] = None -1225 if raw_platform_silver := payload.get("platformSilver"): -1226 if "data" in raw_platform_silver: -1227 platform_silver = { -1228 platform_name: self.deserialize_profile_item(item) -1229 for platform_name, item in raw_platform_silver["data"][ -1230 "platformSilver" -1231 ].items() -1232 } -1233 -1234 character_currency_lookups: typing.Optional[ -1235 collections.Mapping[int, collections.Sequence[items.Currency]] -1236 ] = None -1237 if raw_char_lookups := payload.get("characterCurrencyLookups"): -1238 if "data" in raw_char_lookups: -1239 character_currency_lookups = { -1240 int(char_id): self._deserialize_currencies(currencie) -1241 for char_id, currencie in raw_char_lookups["data"].items() -1242 } -1243 -1244 character_craftables: typing.Optional[ -1245 collections.Mapping[int, components.CraftablesComponent] -1246 ] = None -1247 if raw_character_craftables := payload.get("characterCraftables"): +1197 profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None +1198 if raw_profile_nodes := payload.get("profilePresentationNodes"): +1199 profile_nodes = { +1200 int(node_hash): self._deserialize_node(node) +1201 for node_hash, node in raw_profile_nodes["data"]["nodes"].items() +1202 } +1203 +1204 character_nodes: typing.Optional[ +1205 collections.Mapping[int, collections.Mapping[int, records.Node]] +1206 ] = None +1207 if raw_character_nodes := payload.get("characterPresentationNodes"): +1208 character_nodes = { +1209 int(char_id): { +1210 int(node_hash): self._deserialize_node(node) +1211 for node_hash, node in each_character["nodes"].items() +1212 } +1213 for char_id, each_character in raw_character_nodes["data"].items() +1214 } +1215 +1216 platform_silver: typing.Optional[ +1217 collections.Mapping[str, profile.ProfileItemImpl] +1218 ] = None +1219 if raw_platform_silver := payload.get("platformSilver"): +1220 if "data" in raw_platform_silver: +1221 platform_silver = { +1222 platform_name: self.deserialize_profile_item(item) +1223 for platform_name, item in raw_platform_silver["data"][ +1224 "platformSilver" +1225 ].items() +1226 } +1227 +1228 character_currency_lookups: typing.Optional[ +1229 collections.Mapping[int, collections.Sequence[items.Currency]] +1230 ] = None +1231 if raw_char_lookups := payload.get("characterCurrencyLookups"): +1232 if "data" in raw_char_lookups: +1233 character_currency_lookups = { +1234 int(char_id): self._deserialize_currencies(currencie) +1235 for char_id, currencie in raw_char_lookups["data"].items() +1236 } +1237 +1238 character_craftables: typing.Optional[ +1239 collections.Mapping[int, components.CraftablesComponent] +1240 ] = None +1241 if raw_character_craftables := payload.get("characterCraftables"): +1242 +1243 if "data" in raw_character_craftables: +1244 character_craftables = { +1245 int(char_id): self.deserialize_craftables_component(craftable) +1246 for char_id, craftable in raw_character_craftables["data"].items() +1247 } 1248 -1249 if "data" in raw_character_craftables: -1250 character_craftables = { -1251 int(char_id): self.deserialize_craftables_component(craftable) -1252 for char_id, craftable in raw_character_craftables["data"].items() -1253 } -1254 -1255 return components.Component( -1256 profiles=profile_, -1257 profile_progression=profile_progression, -1258 profile_currencies=profile_currencies, -1259 profile_inventories=profile_inventories, -1260 profile_records=profile_records, -1261 characters=characters, -1262 character_records=character_records, -1263 character_equipments=character_equipments, -1264 character_inventories=character_inventories, -1265 character_activities=character_activities, -1266 character_render_data=character_render_data, -1267 character_progressions=character_progressions, -1268 profile_string_variables=profile_string_vars, -1269 character_string_variables=character_string_vars, -1270 metrics=metrics, -1271 root_node_hash=root_node_hash, -1272 transitory=transitory, -1273 item_components=item_components, -1274 profile_plugsets=profile_plugsets, -1275 character_plugsets=character_plugsets, -1276 character_collectibles=character_collectibles, -1277 profile_collectibles=profile_collectibles, -1278 profile_nodes=profile_nodes, -1279 character_nodes=character_nodes, -1280 platform_silver=platform_silver, -1281 character_currency_lookups=character_currency_lookups, -1282 character_craftables=character_craftables, -1283 ) -1284 -1285 def deserialize_items_component( -1286 self, payload: typedefs.JSONObject -1287 ) -> components.ItemsComponent: -1288 instances: typing.Optional[ -1289 collections.Sequence[collections.Mapping[int, items.ItemInstance]] -1290 ] = None -1291 if raw_instances := payload.get("instances"): -1292 instances = [ -1293 { -1294 int(ins_id): self.deserialize_instanced_item(item) -1295 for ins_id, item in raw_instances["data"].items() -1296 } -1297 ] -1298 -1299 render_data: typing.Optional[ -1300 collections.Mapping[int, tuple[bool, dict[int, int]]] -1301 ] = None -1302 if raw_render_data := payload.get("renderData"): -1303 render_data = { -1304 int(ins_id): (data["useCustomDyes"], data["artRegions"]) -1305 for ins_id, data in raw_render_data["data"].items() -1306 } -1307 -1308 stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None -1309 if raw_stats := payload.get("stats"): -1310 builder: collections.Mapping[int, items.ItemStatsView] = {} -1311 for ins_id, stat in raw_stats["data"].items(): -1312 for _, items_ in stat.items(): -1313 builder[int(ins_id)] = self.deserialize_item_stats_view(items_) # type: ignore[index] -1314 stats = builder -1315 -1316 sockets: typing.Optional[ -1317 collections.Mapping[int, collections.Sequence[items.ItemSocket]] -1318 ] = None -1319 if raw_sockets := payload.get("sockets"): -1320 sockets = { -1321 int(ins_id): [ -1322 self.deserialize_item_socket(socket) for socket in item["sockets"] -1323 ] -1324 for ins_id, item in raw_sockets["data"].items() -1325 } -1326 -1327 objeectives: typing.Optional[ -1328 collections.Mapping[int, collections.Sequence[records.Objective]] -1329 ] = None -1330 if raw_objectives := payload.get("objectives"): -1331 objeectives = { -1332 int(ins_id): [self.deserialize_objectives(objective)] -1333 for ins_id, data in raw_objectives["data"].items() -1334 for objective in data["objectives"] -1335 } -1336 -1337 perks: typing.Optional[ -1338 collections.Mapping[int, collections.Collection[items.ItemPerk]] -1339 ] = None -1340 if raw_perks := payload.get("perks"): -1341 perks = { -1342 int(ins_id): [ -1343 self.deserialize_item_perk(perk) for perk in item["perks"] -1344 ] -1345 for ins_id, item in raw_perks["data"].items() -1346 } -1347 -1348 plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None -1349 if raw_plug_states := payload.get("plugStates"): -1350 pending_states: list[items.PlugItemState] = [] -1351 for _, plug in raw_plug_states["data"].items(): -1352 pending_states.append(self.deserialize_plug_item_state(plug)) -1353 plug_states = pending_states -1354 -1355 reusable_plugs: typing.Optional[ -1356 collections.Mapping[int, collections.Sequence[items.PlugItemState]] -1357 ] = None -1358 if raw_re_plugs := payload.get("reusablePlugs"): -1359 reusable_plugs = { -1360 int(ins_id): [ -1361 self.deserialize_plug_item_state(state) for state in inner -1362 ] -1363 for ins_id, plug in raw_re_plugs["data"].items() -1364 for inner in list(plug["plugs"].values()) -1365 } -1366 -1367 plug_objectives: typing.Optional[ -1368 collections.Mapping[ -1369 int, collections.Mapping[int, collections.Collection[records.Objective]] -1370 ] -1371 ] = None -1372 if raw_plug_objectives := payload.get("plugObjectives"): -1373 plug_objectives = { -1374 int(ins_id): { -1375 int(obj_hash): [self.deserialize_objectives(obj) for obj in objs] -1376 for obj_hash, objs in inner["objectivesPerPlug"].items() -1377 } -1378 for ins_id, inner in raw_plug_objectives["data"].items() -1379 } -1380 -1381 return components.ItemsComponent( -1382 sockets=sockets, -1383 stats=stats, -1384 render_data=render_data, -1385 instances=instances, -1386 objectives=objeectives, -1387 perks=perks, -1388 plug_states=plug_states, -1389 reusable_plugs=reusable_plugs, -1390 plug_objectives=plug_objectives, -1391 ) -1392 -1393 def deserialize_character_component( # type: ignore[call-arg] -1394 self, payload: typedefs.JSONObject -1395 ) -> components.CharacterComponent: -1396 -1397 character_: typing.Optional[character.Character] = None -1398 if raw_singuler_character := payload.get("character"): -1399 character_ = self.deserialize_character(raw_singuler_character["data"]) -1400 -1401 inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None -1402 if raw_inventory := payload.get("inventory"): -1403 if "data" in raw_inventory: -1404 inventory = self.deserialize_profile_items(raw_inventory["data"]) -1405 -1406 activities: typing.Optional[activity.CharacterActivity] = None -1407 if raw_activities := payload.get("activities"): -1408 activities = self.deserialize_character_activity(raw_activities["data"]) -1409 -1410 equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None -1411 if raw_equipments := payload.get("equipment"): -1412 equipment = self.deserialize_profile_items(raw_equipments["data"]) +1249 return components.Component( +1250 profiles=profile_, +1251 profile_progression=profile_progression, +1252 profile_currencies=profile_currencies, +1253 profile_inventories=profile_inventories, +1254 profile_records=profile_records, +1255 characters=characters, +1256 character_records=character_records, +1257 character_equipments=character_equipments, +1258 character_inventories=character_inventories, +1259 character_activities=character_activities, +1260 character_render_data=character_render_data, +1261 character_progressions=character_progressions, +1262 profile_string_variables=profile_string_vars, +1263 character_string_variables=character_string_vars, +1264 metrics=metrics, +1265 root_node_hash=root_node_hash, +1266 transitory=transitory, +1267 item_components=item_components, +1268 profile_plugsets=profile_plugsets, +1269 character_plugsets=character_plugsets, +1270 character_collectibles=character_collectibles, +1271 profile_collectibles=profile_collectibles, +1272 profile_nodes=profile_nodes, +1273 character_nodes=character_nodes, +1274 platform_silver=platform_silver, +1275 character_currency_lookups=character_currency_lookups, +1276 character_craftables=character_craftables, +1277 ) +1278 +1279 def deserialize_items_component( +1280 self, payload: typedefs.JSONObject +1281 ) -> components.ItemsComponent: +1282 instances: typing.Optional[ +1283 collections.Sequence[collections.Mapping[int, items.ItemInstance]] +1284 ] = None +1285 if raw_instances := payload.get("instances"): +1286 instances = [ +1287 { +1288 int(ins_id): self.deserialize_instanced_item(item) +1289 for ins_id, item in raw_instances["data"].items() +1290 } +1291 ] +1292 +1293 render_data: typing.Optional[ +1294 collections.Mapping[int, tuple[bool, dict[int, int]]] +1295 ] = None +1296 if raw_render_data := payload.get("renderData"): +1297 render_data = { +1298 int(ins_id): (data["useCustomDyes"], data["artRegions"]) +1299 for ins_id, data in raw_render_data["data"].items() +1300 } +1301 +1302 stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None +1303 if raw_stats := payload.get("stats"): +1304 builder: collections.Mapping[int, items.ItemStatsView] = {} +1305 for ins_id, stat in raw_stats["data"].items(): +1306 for _, items_ in stat.items(): +1307 builder[int(ins_id)] = self.deserialize_item_stats_view(items_) # type: ignore[index] +1308 stats = builder +1309 +1310 sockets: typing.Optional[ +1311 collections.Mapping[int, collections.Sequence[items.ItemSocket]] +1312 ] = None +1313 if raw_sockets := payload.get("sockets"): +1314 sockets = { +1315 int(ins_id): [ +1316 self.deserialize_item_socket(socket) for socket in item["sockets"] +1317 ] +1318 for ins_id, item in raw_sockets["data"].items() +1319 } +1320 +1321 objeectives: typing.Optional[ +1322 collections.Mapping[int, collections.Sequence[records.Objective]] +1323 ] = None +1324 if raw_objectives := payload.get("objectives"): +1325 objeectives = { +1326 int(ins_id): [self.deserialize_objectives(objective)] +1327 for ins_id, data in raw_objectives["data"].items() +1328 for objective in data["objectives"] +1329 } +1330 +1331 perks: typing.Optional[ +1332 collections.Mapping[int, collections.Collection[items.ItemPerk]] +1333 ] = None +1334 if raw_perks := payload.get("perks"): +1335 perks = { +1336 int(ins_id): [ +1337 self.deserialize_item_perk(perk) for perk in item["perks"] +1338 ] +1339 for ins_id, item in raw_perks["data"].items() +1340 } +1341 +1342 plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None +1343 if raw_plug_states := payload.get("plugStates"): +1344 pending_states: list[items.PlugItemState] = [] +1345 for _, plug in raw_plug_states["data"].items(): +1346 pending_states.append(self.deserialize_plug_item_state(plug)) +1347 plug_states = pending_states +1348 +1349 reusable_plugs: typing.Optional[ +1350 collections.Mapping[int, collections.Sequence[items.PlugItemState]] +1351 ] = None +1352 if raw_re_plugs := payload.get("reusablePlugs"): +1353 reusable_plugs = { +1354 int(ins_id): [ +1355 self.deserialize_plug_item_state(state) for state in inner +1356 ] +1357 for ins_id, plug in raw_re_plugs["data"].items() +1358 for inner in list(plug["plugs"].values()) +1359 } +1360 +1361 plug_objectives: typing.Optional[ +1362 collections.Mapping[ +1363 int, collections.Mapping[int, collections.Collection[records.Objective]] +1364 ] +1365 ] = None +1366 if raw_plug_objectives := payload.get("plugObjectives"): +1367 plug_objectives = { +1368 int(ins_id): { +1369 int(obj_hash): [self.deserialize_objectives(obj) for obj in objs] +1370 for obj_hash, objs in inner["objectivesPerPlug"].items() +1371 } +1372 for ins_id, inner in raw_plug_objectives["data"].items() +1373 } +1374 +1375 return components.ItemsComponent( +1376 sockets=sockets, +1377 stats=stats, +1378 render_data=render_data, +1379 instances=instances, +1380 objectives=objeectives, +1381 perks=perks, +1382 plug_states=plug_states, +1383 reusable_plugs=reusable_plugs, +1384 plug_objectives=plug_objectives, +1385 ) +1386 +1387 def deserialize_character_component( # type: ignore[call-arg] +1388 self, payload: typedefs.JSONObject +1389 ) -> components.CharacterComponent: +1390 +1391 character_: typing.Optional[character.Character] = None +1392 if raw_singuler_character := payload.get("character"): +1393 character_ = self.deserialize_character(raw_singuler_character["data"]) +1394 +1395 inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None +1396 if raw_inventory := payload.get("inventory"): +1397 if "data" in raw_inventory: +1398 inventory = self.deserialize_profile_items(raw_inventory["data"]) +1399 +1400 activities: typing.Optional[activity.CharacterActivity] = None +1401 if raw_activities := payload.get("activities"): +1402 activities = self.deserialize_character_activity(raw_activities["data"]) +1403 +1404 equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None +1405 if raw_equipments := payload.get("equipment"): +1406 equipment = self.deserialize_profile_items(raw_equipments["data"]) +1407 +1408 progressions_: typing.Optional[character.CharacterProgression] = None +1409 if raw_progressions := payload.get("progressions"): +1410 progressions_ = self.deserialize_character_progressions( +1411 raw_progressions["data"] +1412 ) 1413 -1414 progressions_: typing.Optional[character.CharacterProgression] = None -1415 if raw_progressions := payload.get("progressions"): -1416 progressions_ = self.deserialize_character_progressions( -1417 raw_progressions["data"] +1414 render_data: typing.Optional[character.RenderedData] = None +1415 if raw_render_data := payload.get("renderData"): +1416 render_data = self.deserialize_character_render_data( +1417 raw_render_data["data"] 1418 ) 1419 -1420 render_data: typing.Optional[character.RenderedData] = None -1421 if raw_render_data := payload.get("renderData"): -1422 render_data = self.deserialize_character_render_data( -1423 raw_render_data["data"] -1424 ) -1425 -1426 character_records: typing.Optional[ -1427 collections.Mapping[int, records.CharacterRecord] -1428 ] = None -1429 if raw_char_records := payload.get("records"): -1430 character_records = self.deserialize_characters_records( -1431 raw_char_records["data"] -1432 ) -1433 -1434 item_components: typing.Optional[components.ItemsComponent] = None -1435 if raw_item_components := payload.get("itemComponents"): -1436 item_components = self.deserialize_items_component(raw_item_components) -1437 -1438 nodes: typing.Optional[collections.Mapping[int, records.Node]] = None -1439 if raw_nodes := payload.get("presentationNodes"): -1440 nodes = { -1441 int(node_hash): self._deserialize_node(node) -1442 for node_hash, node in raw_nodes["data"]["nodes"].items() -1443 } -1444 -1445 collectibles: typing.Optional[items.Collectible] = None -1446 if raw_collectibles := payload.get("collectibles"): -1447 collectibles = self._deserialize_collectible(raw_collectibles["data"]) -1448 -1449 currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None -1450 if raw_currencies := payload.get("currencyLookups"): -1451 if "data" in raw_currencies: -1452 currency_lookups = self._deserialize_currencies(raw_currencies) -1453 -1454 return components.CharacterComponent( -1455 activities=activities, -1456 equipment=equipment, -1457 inventory=inventory, -1458 progressions=progressions_, -1459 render_data=render_data, -1460 character=character_, -1461 character_records=character_records, -1462 profile_records=None, -1463 item_components=item_components, -1464 currency_lookups=currency_lookups, -1465 collectibles=collectibles, -1466 nodes=nodes, -1467 ) -1468 -1469 def _set_entity_attrs( -1470 self, payload: typedefs.JSONObject, *, key: str = "displayProperties" -1471 ) -> entity.Entity: -1472 -1473 name: undefined.UndefinedOr[str] = undefined.Undefined -1474 description: undefined.UndefinedOr[str] = undefined.Undefined -1475 -1476 if properties := payload[key]: -1477 if (raw_name := properties["name"]) is not typedefs.Unknown: -1478 name = raw_name -1479 -1480 if ( -1481 raw_description := properties["description"] -1482 ) and not typedefs.is_unknown(raw_description): -1483 description = raw_description -1484 -1485 return entity.Entity( -1486 net=self._net, -1487 hash=payload["hash"], -1488 index=payload["index"], -1489 name=name, -1490 description=description, -1491 has_icon=properties["hasIcon"], -1492 icon=assets.Image(properties["icon"] if "icon" in properties else None), -1493 ) -1494 -1495 def deserialize_inventory_results( -1496 self, payload: typedefs.JSONObject -1497 ) -> iterators.FlatIterator[entity.SearchableEntity]: -1498 suggested_words: list[str] = payload["suggestedWords"] -1499 -1500 def _check_unknown(s: str) -> undefined.UndefinedOr[str]: -1501 return s if not typedefs.is_unknown(s) else undefined.Undefined -1502 -1503 return iterators.FlatIterator( -1504 [ -1505 entity.SearchableEntity( -1506 net=self._net, -1507 hash=data["hash"], -1508 entity_type=data["entityType"], -1509 weight=data["weight"], -1510 suggested_words=suggested_words, -1511 name=data["displayProperties"]["name"], -1512 has_icon=data["displayProperties"]["hasIcon"], -1513 description=_check_unknown( -1514 data["displayProperties"]["description"] -1515 ), -1516 icon=assets.Image(data["displayProperties"]["icon"]), -1517 ) -1518 for data in payload["results"]["results"] -1519 ] -1520 ) -1521 -1522 def _deserialize_inventory_item_objects( -1523 self, payload: typedefs.JSONObject -1524 ) -> entity.InventoryEntityObjects: -1525 return entity.InventoryEntityObjects( -1526 action=payload.get("action"), -1527 set_data=payload.get("setData"), -1528 stats=payload.get("stats"), -1529 equipping_block=payload.get("equippingBlock"), -1530 translation_block=payload.get("translationBlock"), -1531 preview=payload.get("preview"), -1532 quality=payload.get("quality"), -1533 value=payload.get("value"), -1534 source_data=payload.get("sourceData"), -1535 objectives=payload.get("objectives"), -1536 plug=payload.get("plug"), -1537 metrics=payload.get("metrics"), -1538 gearset=payload.get("gearset"), -1539 sack=payload.get("sack"), -1540 sockets=payload.get("sockets"), -1541 summary=payload.get("summary"), -1542 talent_gird=payload.get("talentGrid"), -1543 investments_stats=payload.get("investmentStats"), -1544 perks=payload.get("perks"), -1545 animations=payload.get("animations", []), -1546 links=payload.get("links", []), -1547 ) -1548 -1549 def deserialize_inventory_entity( # noqa: C901 Too complex. -1550 self, payload: typedefs.JSONObject, / -1551 ) -> entity.InventoryEntity: -1552 -1553 props = self._set_entity_attrs(payload) -1554 objects = self._deserialize_inventory_item_objects(payload) -1555 -1556 collectible_hash: typing.Optional[int] = None -1557 if raw_collectible_hash := payload.get("collectibleHash"): -1558 collectible_hash = int(raw_collectible_hash) -1559 -1560 secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.Undefined -1561 if raw_second_icon := payload.get("secondaryIcon"): -1562 secondary_icon = assets.Image(raw_second_icon) -1563 -1564 secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.Undefined -1565 if raw_second_overlay := payload.get("secondaryOverlay"): -1566 secondary_overlay = assets.Image(raw_second_overlay) -1567 -1568 secondary_special: undefined.UndefinedOr[assets.Image] = undefined.Undefined -1569 if raw_second_special := payload.get("secondarySpecial"): -1570 secondary_special = assets.Image(raw_second_special) -1571 -1572 screenshot: undefined.UndefinedOr[assets.Image] = undefined.Undefined -1573 if raw_screenshot := payload.get("screenshot"): -1574 screenshot = assets.Image(raw_screenshot) -1575 -1576 watermark_icon: typing.Optional[assets.Image] = None -1577 if raw_watermark_icon := payload.get("iconWatermark"): -1578 watermark_icon = assets.Image(raw_watermark_icon) -1579 -1580 watermark_shelved: typing.Optional[assets.Image] = None -1581 if raw_watermark_shelved := payload.get("iconWatermarkShelved"): -1582 watermark_shelved = assets.Image(raw_watermark_shelved) +1420 character_records: typing.Optional[ +1421 collections.Mapping[int, records.CharacterRecord] +1422 ] = None +1423 if raw_char_records := payload.get("records"): +1424 character_records = self.deserialize_characters_records( +1425 raw_char_records["data"] +1426 ) +1427 +1428 item_components: typing.Optional[components.ItemsComponent] = None +1429 if raw_item_components := payload.get("itemComponents"): +1430 item_components = self.deserialize_items_component(raw_item_components) +1431 +1432 nodes: typing.Optional[collections.Mapping[int, records.Node]] = None +1433 if raw_nodes := payload.get("presentationNodes"): +1434 nodes = { +1435 int(node_hash): self._deserialize_node(node) +1436 for node_hash, node in raw_nodes["data"]["nodes"].items() +1437 } +1438 +1439 collectibles: typing.Optional[items.Collectible] = None +1440 if raw_collectibles := payload.get("collectibles"): +1441 collectibles = self._deserialize_collectible(raw_collectibles["data"]) +1442 +1443 currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None +1444 if raw_currencies := payload.get("currencyLookups"): +1445 if "data" in raw_currencies: +1446 currency_lookups = self._deserialize_currencies(raw_currencies) +1447 +1448 return components.CharacterComponent( +1449 activities=activities, +1450 equipment=equipment, +1451 inventory=inventory, +1452 progressions=progressions_, +1453 render_data=render_data, +1454 character=character_, +1455 character_records=character_records, +1456 profile_records=None, +1457 item_components=item_components, +1458 currency_lookups=currency_lookups, +1459 collectibles=collectibles, +1460 nodes=nodes, +1461 ) +1462 +1463 def _set_entity_attrs( +1464 self, payload: typedefs.JSONObject, *, key: str = "displayProperties" +1465 ) -> entity.Entity: +1466 +1467 name: undefined.UndefinedOr[str] = undefined.Undefined +1468 description: undefined.UndefinedOr[str] = undefined.Undefined +1469 +1470 if properties := payload[key]: +1471 if (raw_name := properties["name"]) is not typedefs.Unknown: +1472 name = raw_name +1473 +1474 if ( +1475 raw_description := properties["description"] +1476 ) and not typedefs.is_unknown(raw_description): +1477 description = raw_description +1478 +1479 return entity.Entity( +1480 net=self._net, +1481 hash=payload["hash"], +1482 index=payload["index"], +1483 name=name, +1484 description=description, +1485 has_icon=properties["hasIcon"], +1486 icon=assets.Image(properties["icon"] if "icon" in properties else None), +1487 ) +1488 +1489 def deserialize_inventory_results( +1490 self, payload: typedefs.JSONObject +1491 ) -> iterators.Iterator[entity.SearchableEntity]: +1492 suggested_words: list[str] = payload["suggestedWords"] +1493 +1494 def _check_unknown(s: str) -> undefined.UndefinedOr[str]: +1495 return s if not typedefs.is_unknown(s) else undefined.Undefined +1496 +1497 return iterators.Iterator( +1498 [ +1499 entity.SearchableEntity( +1500 net=self._net, +1501 hash=data["hash"], +1502 entity_type=data["entityType"], +1503 weight=data["weight"], +1504 suggested_words=suggested_words, +1505 name=data["displayProperties"]["name"], +1506 has_icon=data["displayProperties"]["hasIcon"], +1507 description=_check_unknown( +1508 data["displayProperties"]["description"] +1509 ), +1510 icon=assets.Image(data["displayProperties"]["icon"]), +1511 ) +1512 for data in payload["results"]["results"] +1513 ] +1514 ) +1515 +1516 def _deserialize_inventory_item_objects( +1517 self, payload: typedefs.JSONObject +1518 ) -> entity.InventoryEntityObjects: +1519 return entity.InventoryEntityObjects( +1520 action=payload.get("action"), +1521 set_data=payload.get("setData"), +1522 stats=payload.get("stats"), +1523 equipping_block=payload.get("equippingBlock"), +1524 translation_block=payload.get("translationBlock"), +1525 preview=payload.get("preview"), +1526 quality=payload.get("quality"), +1527 value=payload.get("value"), +1528 source_data=payload.get("sourceData"), +1529 objectives=payload.get("objectives"), +1530 plug=payload.get("plug"), +1531 metrics=payload.get("metrics"), +1532 gearset=payload.get("gearset"), +1533 sack=payload.get("sack"), +1534 sockets=payload.get("sockets"), +1535 summary=payload.get("summary"), +1536 talent_gird=payload.get("talentGrid"), +1537 investments_stats=payload.get("investmentStats"), +1538 perks=payload.get("perks"), +1539 animations=payload.get("animations", []), +1540 links=payload.get("links", []), +1541 ) +1542 +1543 def deserialize_inventory_entity( # noqa: C901 Too complex. +1544 self, payload: typedefs.JSONObject, / +1545 ) -> entity.InventoryEntity: +1546 +1547 props = self._set_entity_attrs(payload) +1548 objects = self._deserialize_inventory_item_objects(payload) +1549 +1550 collectible_hash: typing.Optional[int] = None +1551 if raw_collectible_hash := payload.get("collectibleHash"): +1552 collectible_hash = int(raw_collectible_hash) +1553 +1554 secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.Undefined +1555 if raw_second_icon := payload.get("secondaryIcon"): +1556 secondary_icon = assets.Image(raw_second_icon) +1557 +1558 secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.Undefined +1559 if raw_second_overlay := payload.get("secondaryOverlay"): +1560 secondary_overlay = assets.Image(raw_second_overlay) +1561 +1562 secondary_special: undefined.UndefinedOr[assets.Image] = undefined.Undefined +1563 if raw_second_special := payload.get("secondarySpecial"): +1564 secondary_special = assets.Image(raw_second_special) +1565 +1566 screenshot: undefined.UndefinedOr[assets.Image] = undefined.Undefined +1567 if raw_screenshot := payload.get("screenshot"): +1568 screenshot = assets.Image(raw_screenshot) +1569 +1570 watermark_icon: typing.Optional[assets.Image] = None +1571 if raw_watermark_icon := payload.get("iconWatermark"): +1572 watermark_icon = assets.Image(raw_watermark_icon) +1573 +1574 watermark_shelved: typing.Optional[assets.Image] = None +1575 if raw_watermark_shelved := payload.get("iconWatermarkShelved"): +1576 watermark_shelved = assets.Image(raw_watermark_shelved) +1577 +1578 about: undefined.UndefinedOr[str] = undefined.Undefined +1579 if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown( +1580 raw_about +1581 ): +1582 about = raw_about 1583 -1584 about: undefined.UndefinedOr[str] = undefined.Undefined -1585 if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown( -1586 raw_about -1587 ): -1588 about = raw_about +1584 ui_item_style: undefined.UndefinedOr[str] = undefined.Undefined +1585 if ( +1586 raw_ui_style := payload.get("uiItemDisplayStyle") +1587 ) and not typedefs.is_unknown(raw_ui_style): +1588 ui_item_style = raw_ui_style 1589 -1590 ui_item_style: undefined.UndefinedOr[str] = undefined.Undefined +1590 tier_and_name: undefined.UndefinedOr[str] = undefined.Undefined 1591 if ( -1592 raw_ui_style := payload.get("uiItemDisplayStyle") -1593 ) and not typedefs.is_unknown(raw_ui_style): -1594 ui_item_style = raw_ui_style +1592 raw_tier_and_name := payload.get("itemTypeAndTierDisplayName") +1593 ) and not typedefs.is_unknown(raw_tier_and_name): +1594 tier_and_name = raw_tier_and_name 1595 -1596 tier_and_name: undefined.UndefinedOr[str] = undefined.Undefined +1596 type_name: undefined.UndefinedOr[str] = undefined.Undefined 1597 if ( -1598 raw_tier_and_name := payload.get("itemTypeAndTierDisplayName") -1599 ) and not typedefs.is_unknown(raw_tier_and_name): -1600 tier_and_name = raw_tier_and_name +1598 raw_type_name := payload.get("itemTypeDisplayName") +1599 ) and not typedefs.is_unknown(raw_type_name): +1600 type_name = raw_type_name 1601 -1602 type_name: undefined.UndefinedOr[str] = undefined.Undefined +1602 display_source: undefined.UndefinedOr[str] = undefined.Undefined 1603 if ( -1604 raw_type_name := payload.get("itemTypeDisplayName") -1605 ) and not typedefs.is_unknown(raw_type_name): -1606 type_name = raw_type_name +1604 raw_display_source := payload.get("displaySource") +1605 ) and not typedefs.is_unknown(raw_display_source): +1606 display_source = raw_display_source 1607 -1608 display_source: undefined.UndefinedOr[str] = undefined.Undefined -1609 if ( -1610 raw_display_source := payload.get("displaySource") -1611 ) and not typedefs.is_unknown(raw_display_source): -1612 display_source = raw_display_source -1613 -1614 lorehash: typing.Optional[int] = None -1615 if raw_lore_hash := payload.get("loreHash"): -1616 lorehash = int(raw_lore_hash) -1617 -1618 summary_hash: typing.Optional[int] = None -1619 if raw_summary_hash := payload.get("summaryItemHash"): -1620 summary_hash = raw_summary_hash -1621 -1622 breaker_type_hash: typing.Optional[int] = None -1623 if raw_breaker_type_hash := payload.get("breakerTypeHash"): -1624 breaker_type_hash = int(raw_breaker_type_hash) -1625 -1626 damage_types: typing.Optional[collections.Sequence[int]] = None -1627 if raw_damage_types := payload.get("damageTypes"): -1628 damage_types = [int(type_) for type_ in raw_damage_types] -1629 -1630 damagetype_hashes: typing.Optional[collections.Sequence[int]] = None -1631 if raw_damagetype_hashes := payload.get("damageTypeHashes"): -1632 damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes] -1633 -1634 default_damagetype_hash: typing.Optional[int] = None -1635 if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"): -1636 default_damagetype_hash = int(raw_defaultdmg_hash) -1637 -1638 emblem_objective_hash: typing.Optional[int] = None -1639 if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"): -1640 emblem_objective_hash = int(raw_emblem_obj_hash) -1641 -1642 tier_type: typing.Optional[enums.TierType] = None -1643 tier: typing.Optional[enums.ItemTier] = None -1644 bucket_hash: typing.Optional[int] = None -1645 recovery_hash: typing.Optional[int] = None -1646 tier_name: undefined.UndefinedOr[str] = undefined.Undefined -1647 isinstance_item: bool = False -1648 expire_tool_tip: undefined.UndefinedOr[str] = undefined.Undefined -1649 expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.Undefined -1650 suppress_expiration: bool = False -1651 max_stack_size: typing.Optional[int] = None -1652 stack_label: undefined.UndefinedOr[str] = undefined.Undefined -1653 -1654 if inventory := payload.get("inventory"): -1655 tier_type = enums.TierType(int(inventory["tierType"])) -1656 tier = enums.ItemTier(int(inventory["tierTypeHash"])) -1657 bucket_hash = int(inventory["bucketTypeHash"]) -1658 recovery_hash = int(inventory["recoveryBucketTypeHash"]) -1659 tier_name = inventory["tierTypeName"] -1660 isinstance_item = inventory["isInstanceItem"] -1661 suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"] -1662 max_stack_size = int(inventory["maxStackSize"]) -1663 -1664 try: -1665 stack_label = inventory["stackUniqueLabel"] -1666 except KeyError: -1667 pass -1668 -1669 return entity.InventoryEntity( -1670 net=self._net, -1671 collectible_hash=collectible_hash, -1672 name=props.name, -1673 about=about, -1674 emblem_objective_hash=emblem_objective_hash, -1675 suppress_expiration=suppress_expiration, -1676 max_stack_size=max_stack_size, -1677 stack_label=stack_label, -1678 tier=tier, -1679 tier_type=tier_type, -1680 tier_name=tier_name, -1681 bucket_hash=bucket_hash, -1682 recovery_bucket_hash=recovery_hash, -1683 isinstance_item=isinstance_item, -1684 expire_in_orbit_message=expire_in_orbit_message, -1685 expiration_tooltip=expire_tool_tip, -1686 lore_hash=lorehash, -1687 type_and_tier_name=tier_and_name, -1688 summary_hash=summary_hash, -1689 ui_display_style=ui_item_style, -1690 type_name=type_name, -1691 breaker_type_hash=breaker_type_hash, -1692 description=props.description, -1693 display_source=display_source, -1694 hash=props.hash, -1695 damage_types=damage_types, -1696 index=props.index, -1697 icon=props.icon, -1698 has_icon=props.has_icon, -1699 screenshot=screenshot, -1700 watermark_icon=watermark_icon, -1701 watermark_shelved=watermark_shelved, -1702 secondary_icon=secondary_icon, -1703 secondary_overlay=secondary_overlay, -1704 secondary_special=secondary_special, -1705 type=enums.ItemType(int(payload["itemType"])), -1706 trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])], -1707 trait_ids=[trait for trait in payload.get("traitIds", [])], -1708 category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]], -1709 item_class=enums.Class(int(payload["classType"])), -1710 sub_type=enums.ItemSubType(int(payload["itemSubType"])), -1711 breaker_type=int(payload["breakerType"]), -1712 default_damagetype=int(payload["defaultDamageType"]), -1713 default_damagetype_hash=default_damagetype_hash, -1714 damagetype_hashes=damagetype_hashes, -1715 tooltip_notifications=payload["tooltipNotifications"], -1716 not_transferable=payload["nonTransferrable"], -1717 allow_actions=payload["allowActions"], -1718 is_equippable=payload["equippable"], -1719 objects=objects, -1720 background_colors=payload.get("backgroundColor", {}), -1721 season_hash=payload.get("seasonHash"), -1722 has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"], -1723 ) -1724 -1725 def deserialize_objective_entity( -1726 self, payload: typedefs.JSONObject, / -1727 ) -> entity.ObjectiveEntity: -1728 props = self._set_entity_attrs(payload) -1729 return entity.ObjectiveEntity( -1730 net=self._net, -1731 hash=props.hash, -1732 index=props.index, -1733 description=props.description, -1734 name=props.name, -1735 has_icon=props.has_icon, -1736 icon=props.icon, -1737 unlock_value_hash=payload["unlockValueHash"], -1738 completion_value=payload["completionValue"], -1739 scope=entity.GatingScope(int(payload["scope"])), -1740 location_hash=payload["locationHash"], -1741 allowed_negative_value=payload["allowNegativeValue"], -1742 allowed_value_change=payload["allowValueChangeWhenCompleted"], -1743 counting_downward=payload["isCountingDownward"], -1744 value_style=entity.ValueUIStyle(int(payload["valueStyle"])), -1745 progress_description=payload["progressDescription"], -1746 perks=payload["perks"], -1747 stats=payload["stats"], -1748 minimum_visibility=payload["minimumVisibilityThreshold"], -1749 allow_over_completion=payload["allowOvercompletion"], -1750 show_value_style=payload["showValueOnComplete"], -1751 display_only_objective=payload["isDisplayOnlyObjective"], -1752 complete_value_style=entity.ValueUIStyle( -1753 int(payload["completedValueStyle"]) -1754 ), -1755 progress_value_style=entity.ValueUIStyle( -1756 int(payload["inProgressValueStyle"]) -1757 ), -1758 ui_label=payload["uiLabel"], -1759 ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])), -1760 ) -1761 -1762 def _deserialize_activity_values( -1763 self, payload: typedefs.JSONObject, / -1764 ) -> activity.ActivityValues: -1765 team: typing.Optional[int] = None -1766 if raw_team := payload.get("team"): -1767 team = raw_team["basic"]["value"] -1768 return activity.ActivityValues( -1769 assists=payload["assists"]["basic"]["value"], -1770 deaths=payload["deaths"]["basic"]["value"], -1771 kills=payload["kills"]["basic"]["value"], -1772 is_completed=bool(payload["completed"]["basic"]["value"]), -1773 opponents_defeated=payload["opponentsDefeated"]["basic"]["value"], -1774 efficiency=payload["efficiency"]["basic"]["value"], -1775 kd_ratio=payload["killsDeathsRatio"]["basic"]["value"], -1776 kd_assists=payload["killsDeathsAssists"]["basic"]["value"], -1777 score=payload["score"]["basic"]["value"], -1778 duration=payload["activityDurationSeconds"]["basic"]["displayValue"], -1779 team=team, -1780 completion_reason=payload["completionReason"]["basic"]["displayValue"], -1781 fireteam_id=payload["fireteamId"]["basic"]["value"], -1782 start_seconds=payload["startSeconds"]["basic"]["value"], -1783 played_time=payload["timePlayedSeconds"]["basic"]["displayValue"], -1784 player_count=payload["playerCount"]["basic"]["value"], -1785 team_score=payload["teamScore"]["basic"]["value"], -1786 ) -1787 -1788 def deserialize_activity( -1789 self, -1790 payload: typedefs.JSONObject, -1791 /, -1792 ) -> activity.Activity: -1793 period = time.clean_date(payload["period"]) -1794 details = payload["activityDetails"] -1795 ref_id = int(details["referenceId"]) -1796 instance_id = int(details["instanceId"]) -1797 mode = enums.GameMode(details["mode"]) -1798 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] -1799 is_private = details["isPrivate"] -1800 membership_type = enums.MembershipType(int(details["membershipType"])) -1801 -1802 # Since we're using the same fields for post activity method -1803 # this check is required since post activity doesn't values values -1804 values = self._deserialize_activity_values(payload["values"]) -1805 -1806 return activity.Activity( -1807 net=self._net, -1808 hash=ref_id, -1809 instance_id=instance_id, -1810 mode=mode, -1811 modes=modes, -1812 is_private=is_private, -1813 membership_type=membership_type, -1814 occurred_at=period, -1815 values=values, -1816 ) -1817 -1818 def deserialize_activities( -1819 self, payload: typedefs.JSONObject -1820 ) -> iterators.FlatIterator[activity.Activity]: -1821 return iterators.FlatIterator( -1822 [ -1823 self.deserialize_activity(activity_) -1824 for activity_ in payload["activities"] -1825 ] -1826 ) -1827 -1828 def deserialize_extended_weapon_values( -1829 self, payload: typedefs.JSONObject -1830 ) -> activity.ExtendedWeaponValues: -1831 -1832 assists: typing.Optional[int] = None -1833 if raw_assists := payload["values"].get("uniqueWeaponAssists"): -1834 assists = raw_assists["basic"]["value"] -1835 assists_damage: typing.Optional[int] = None -1836 -1837 if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"): -1838 assists_damage = raw_assists_damage["basic"]["value"] -1839 -1840 return activity.ExtendedWeaponValues( -1841 reference_id=int(payload["referenceId"]), -1842 kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"], -1843 precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][ -1844 "value" -1845 ], -1846 assists=assists, -1847 assists_damage=assists_damage, -1848 precision_kills_percentage=( -1849 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"], -1850 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][ -1851 "displayValue" -1852 ], -1853 ), -1854 ) -1855 -1856 def _deserialize_extended_values( -1857 self, payload: typedefs.JSONObject -1858 ) -> activity.ExtendedValues: -1859 weapons: typing.Optional[ -1860 collections.Collection[activity.ExtendedWeaponValues] -1861 ] = None -1862 -1863 if raw_weapons := payload.get("weapons"): -1864 weapons = [ -1865 self.deserialize_extended_weapon_values(value) for value in raw_weapons -1866 ] -1867 -1868 return activity.ExtendedValues( -1869 precision_kills=payload["values"]["precisionKills"]["basic"]["value"], -1870 grenade_kills=payload["values"]["weaponKillsGrenade"]["basic"]["value"], -1871 melee_kills=payload["values"]["weaponKillsMelee"]["basic"]["value"], -1872 super_kills=payload["values"]["weaponKillsSuper"]["basic"]["value"], -1873 ability_kills=payload["values"]["weaponKillsAbility"]["basic"]["value"], -1874 weapons=weapons, -1875 ) -1876 -1877 def deserialize_post_activity_player( -1878 self, payload: typedefs.JSONObject, / -1879 ) -> activity.PostActivityPlayer: -1880 player = payload["player"] -1881 -1882 class_hash: typedefs.NoneOr[int] = None -1883 if (class_hash := player.get("classHash")) is not None: -1884 class_hash = class_hash -1885 -1886 race_hash: typedefs.NoneOr[int] = None -1887 if (race_hash := player.get("raceHash")) is not None: -1888 race_hash = race_hash -1889 -1890 gender_hash: typedefs.NoneOr[int] = None -1891 if (gender_hash := player.get("genderHash")) is not None: -1892 gender_hash = gender_hash +1608 lorehash: typing.Optional[int] = None +1609 if raw_lore_hash := payload.get("loreHash"): +1610 lorehash = int(raw_lore_hash) +1611 +1612 summary_hash: typing.Optional[int] = None +1613 if raw_summary_hash := payload.get("summaryItemHash"): +1614 summary_hash = raw_summary_hash +1615 +1616 breaker_type_hash: typing.Optional[int] = None +1617 if raw_breaker_type_hash := payload.get("breakerTypeHash"): +1618 breaker_type_hash = int(raw_breaker_type_hash) +1619 +1620 damage_types: typing.Optional[collections.Sequence[int]] = None +1621 if raw_damage_types := payload.get("damageTypes"): +1622 damage_types = [int(type_) for type_ in raw_damage_types] +1623 +1624 damagetype_hashes: typing.Optional[collections.Sequence[int]] = None +1625 if raw_damagetype_hashes := payload.get("damageTypeHashes"): +1626 damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes] +1627 +1628 default_damagetype_hash: typing.Optional[int] = None +1629 if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"): +1630 default_damagetype_hash = int(raw_defaultdmg_hash) +1631 +1632 emblem_objective_hash: typing.Optional[int] = None +1633 if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"): +1634 emblem_objective_hash = int(raw_emblem_obj_hash) +1635 +1636 tier_type: typing.Optional[enums.TierType] = None +1637 tier: typing.Optional[enums.ItemTier] = None +1638 bucket_hash: typing.Optional[int] = None +1639 recovery_hash: typing.Optional[int] = None +1640 tier_name: undefined.UndefinedOr[str] = undefined.Undefined +1641 isinstance_item: bool = False +1642 expire_tool_tip: undefined.UndefinedOr[str] = undefined.Undefined +1643 expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.Undefined +1644 suppress_expiration: bool = False +1645 max_stack_size: typing.Optional[int] = None +1646 stack_label: undefined.UndefinedOr[str] = undefined.Undefined +1647 +1648 if inventory := payload.get("inventory"): +1649 tier_type = enums.TierType(int(inventory["tierType"])) +1650 tier = enums.ItemTier(int(inventory["tierTypeHash"])) +1651 bucket_hash = int(inventory["bucketTypeHash"]) +1652 recovery_hash = int(inventory["recoveryBucketTypeHash"]) +1653 tier_name = inventory["tierTypeName"] +1654 isinstance_item = inventory["isInstanceItem"] +1655 suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"] +1656 max_stack_size = int(inventory["maxStackSize"]) +1657 +1658 try: +1659 stack_label = inventory["stackUniqueLabel"] +1660 except KeyError: +1661 pass +1662 +1663 return entity.InventoryEntity( +1664 net=self._net, +1665 collectible_hash=collectible_hash, +1666 name=props.name, +1667 about=about, +1668 emblem_objective_hash=emblem_objective_hash, +1669 suppress_expiration=suppress_expiration, +1670 max_stack_size=max_stack_size, +1671 stack_label=stack_label, +1672 tier=tier, +1673 tier_type=tier_type, +1674 tier_name=tier_name, +1675 bucket_hash=bucket_hash, +1676 recovery_bucket_hash=recovery_hash, +1677 isinstance_item=isinstance_item, +1678 expire_in_orbit_message=expire_in_orbit_message, +1679 expiration_tooltip=expire_tool_tip, +1680 lore_hash=lorehash, +1681 type_and_tier_name=tier_and_name, +1682 summary_hash=summary_hash, +1683 ui_display_style=ui_item_style, +1684 type_name=type_name, +1685 breaker_type_hash=breaker_type_hash, +1686 description=props.description, +1687 display_source=display_source, +1688 hash=props.hash, +1689 damage_types=damage_types, +1690 index=props.index, +1691 icon=props.icon, +1692 has_icon=props.has_icon, +1693 screenshot=screenshot, +1694 watermark_icon=watermark_icon, +1695 watermark_shelved=watermark_shelved, +1696 secondary_icon=secondary_icon, +1697 secondary_overlay=secondary_overlay, +1698 secondary_special=secondary_special, +1699 type=enums.ItemType(int(payload["itemType"])), +1700 trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])], +1701 trait_ids=[trait for trait in payload.get("traitIds", [])], +1702 category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]], +1703 item_class=enums.Class(int(payload["classType"])), +1704 sub_type=enums.ItemSubType(int(payload["itemSubType"])), +1705 breaker_type=int(payload["breakerType"]), +1706 default_damagetype=int(payload["defaultDamageType"]), +1707 default_damagetype_hash=default_damagetype_hash, +1708 damagetype_hashes=damagetype_hashes, +1709 tooltip_notifications=payload["tooltipNotifications"], +1710 not_transferable=payload["nonTransferrable"], +1711 allow_actions=payload["allowActions"], +1712 is_equippable=payload["equippable"], +1713 objects=objects, +1714 background_colors=payload.get("backgroundColor", {}), +1715 season_hash=payload.get("seasonHash"), +1716 has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"], +1717 ) +1718 +1719 def deserialize_objective_entity( +1720 self, payload: typedefs.JSONObject, / +1721 ) -> entity.ObjectiveEntity: +1722 props = self._set_entity_attrs(payload) +1723 return entity.ObjectiveEntity( +1724 net=self._net, +1725 hash=props.hash, +1726 index=props.index, +1727 description=props.description, +1728 name=props.name, +1729 has_icon=props.has_icon, +1730 icon=props.icon, +1731 unlock_value_hash=payload["unlockValueHash"], +1732 completion_value=payload["completionValue"], +1733 scope=entity.GatingScope(int(payload["scope"])), +1734 location_hash=payload["locationHash"], +1735 allowed_negative_value=payload["allowNegativeValue"], +1736 allowed_value_change=payload["allowValueChangeWhenCompleted"], +1737 counting_downward=payload["isCountingDownward"], +1738 value_style=entity.ValueUIStyle(int(payload["valueStyle"])), +1739 progress_description=payload["progressDescription"], +1740 perks=payload["perks"], +1741 stats=payload["stats"], +1742 minimum_visibility=payload["minimumVisibilityThreshold"], +1743 allow_over_completion=payload["allowOvercompletion"], +1744 show_value_style=payload["showValueOnComplete"], +1745 display_only_objective=payload["isDisplayOnlyObjective"], +1746 complete_value_style=entity.ValueUIStyle( +1747 int(payload["completedValueStyle"]) +1748 ), +1749 progress_value_style=entity.ValueUIStyle( +1750 int(payload["inProgressValueStyle"]) +1751 ), +1752 ui_label=payload["uiLabel"], +1753 ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])), +1754 ) +1755 +1756 def _deserialize_activity_values( +1757 self, payload: typedefs.JSONObject, / +1758 ) -> activity.ActivityValues: +1759 team: typing.Optional[int] = None +1760 if raw_team := payload.get("team"): +1761 team = raw_team["basic"]["value"] +1762 return activity.ActivityValues( +1763 assists=payload["assists"]["basic"]["value"], +1764 deaths=payload["deaths"]["basic"]["value"], +1765 kills=payload["kills"]["basic"]["value"], +1766 is_completed=bool(payload["completed"]["basic"]["value"]), +1767 opponents_defeated=payload["opponentsDefeated"]["basic"]["value"], +1768 efficiency=payload["efficiency"]["basic"]["value"], +1769 kd_ratio=payload["killsDeathsRatio"]["basic"]["value"], +1770 kd_assists=payload["killsDeathsAssists"]["basic"]["value"], +1771 score=payload["score"]["basic"]["value"], +1772 duration=payload["activityDurationSeconds"]["basic"]["displayValue"], +1773 team=team, +1774 completion_reason=payload["completionReason"]["basic"]["displayValue"], +1775 fireteam_id=payload["fireteamId"]["basic"]["value"], +1776 start_seconds=payload["startSeconds"]["basic"]["value"], +1777 played_time=payload["timePlayedSeconds"]["basic"]["displayValue"], +1778 player_count=payload["playerCount"]["basic"]["value"], +1779 team_score=payload["teamScore"]["basic"]["value"], +1780 ) +1781 +1782 def deserialize_activity( +1783 self, +1784 payload: typedefs.JSONObject, +1785 /, +1786 ) -> activity.Activity: +1787 period = time.clean_date(payload["period"]) +1788 details = payload["activityDetails"] +1789 ref_id = int(details["referenceId"]) +1790 instance_id = int(details["instanceId"]) +1791 mode = enums.GameMode(details["mode"]) +1792 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] +1793 is_private = details["isPrivate"] +1794 membership_type = enums.MembershipType(int(details["membershipType"])) +1795 +1796 # Since we're using the same fields for post activity method +1797 # this check is required since post activity doesn't values values +1798 values = self._deserialize_activity_values(payload["values"]) +1799 +1800 return activity.Activity( +1801 net=self._net, +1802 hash=ref_id, +1803 instance_id=instance_id, +1804 mode=mode, +1805 modes=modes, +1806 is_private=is_private, +1807 membership_type=membership_type, +1808 occurred_at=period, +1809 values=values, +1810 ) +1811 +1812 def deserialize_activities( +1813 self, payload: typedefs.JSONObject +1814 ) -> iterators.Iterator[activity.Activity]: +1815 return iterators.Iterator( +1816 [ +1817 self.deserialize_activity(activity_) +1818 for activity_ in payload["activities"] +1819 ] +1820 ) +1821 +1822 def deserialize_extended_weapon_values( +1823 self, payload: typedefs.JSONObject +1824 ) -> activity.ExtendedWeaponValues: +1825 +1826 assists: typing.Optional[int] = None +1827 if raw_assists := payload["values"].get("uniqueWeaponAssists"): +1828 assists = raw_assists["basic"]["value"] +1829 assists_damage: typing.Optional[int] = None +1830 +1831 if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"): +1832 assists_damage = raw_assists_damage["basic"]["value"] +1833 +1834 return activity.ExtendedWeaponValues( +1835 reference_id=int(payload["referenceId"]), +1836 kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"], +1837 precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][ +1838 "value" +1839 ], +1840 assists=assists, +1841 assists_damage=assists_damage, +1842 precision_kills_percentage=( +1843 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"], +1844 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][ +1845 "displayValue" +1846 ], +1847 ), +1848 ) +1849 +1850 def _deserialize_extended_values( +1851 self, payload: typedefs.JSONObject +1852 ) -> activity.ExtendedValues: +1853 weapons: typing.Optional[ +1854 collections.Collection[activity.ExtendedWeaponValues] +1855 ] = None +1856 +1857 if raw_weapons := payload.get("weapons"): +1858 weapons = [ +1859 self.deserialize_extended_weapon_values(value) for value in raw_weapons +1860 ] +1861 +1862 return activity.ExtendedValues( +1863 precision_kills=payload["values"]["precisionKills"]["basic"]["value"], +1864 grenade_kills=payload["values"]["weaponKillsGrenade"]["basic"]["value"], +1865 melee_kills=payload["values"]["weaponKillsMelee"]["basic"]["value"], +1866 super_kills=payload["values"]["weaponKillsSuper"]["basic"]["value"], +1867 ability_kills=payload["values"]["weaponKillsAbility"]["basic"]["value"], +1868 weapons=weapons, +1869 ) +1870 +1871 def deserialize_post_activity_player( +1872 self, payload: typedefs.JSONObject, / +1873 ) -> activity.PostActivityPlayer: +1874 player = payload["player"] +1875 +1876 class_hash: typedefs.NoneOr[int] = None +1877 if (class_hash := player.get("classHash")) is not None: +1878 class_hash = class_hash +1879 +1880 race_hash: typedefs.NoneOr[int] = None +1881 if (race_hash := player.get("raceHash")) is not None: +1882 race_hash = race_hash +1883 +1884 gender_hash: typedefs.NoneOr[int] = None +1885 if (gender_hash := player.get("genderHash")) is not None: +1886 gender_hash = gender_hash +1887 +1888 character_class: undefined.UndefinedOr[str] = undefined.Undefined +1889 if ( +1890 character_class := player.get("characterClass") +1891 ) and not typedefs.is_unknown(character_class): +1892 character_class = character_class 1893 -1894 character_class: undefined.UndefinedOr[str] = undefined.Undefined -1895 if ( -1896 character_class := player.get("characterClass") -1897 ) and not typedefs.is_unknown(character_class): -1898 character_class = character_class -1899 -1900 character_level: typedefs.NoneOr[int] = None -1901 if (character_level := player.get("characterLevel")) is not None: -1902 character_level = character_level -1903 -1904 return activity.PostActivityPlayer( -1905 standing=int(payload["standing"]), -1906 score=int(payload["score"]["basic"]["value"]), -1907 character_id=payload["characterId"], -1908 destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]), -1909 character_class=character_class, -1910 character_level=character_level, -1911 race_hash=race_hash, -1912 gender_hash=gender_hash, -1913 class_hash=class_hash, -1914 light_level=int(player["lightLevel"]), -1915 emblem_hash=int(player["emblemHash"]), -1916 values=self._deserialize_activity_values(payload["values"]), -1917 extended_values=self._deserialize_extended_values(payload["extended"]), -1918 ) -1919 -1920 def _deserialize_post_activity_team( -1921 self, payload: typedefs.JSONObject -1922 ) -> activity.PostActivityTeam: -1923 return activity.PostActivityTeam( -1924 id=payload["teamId"], -1925 is_defeated=bool(payload["standing"]["basic"]["value"]), -1926 score=int(payload["score"]["basic"]["value"]), -1927 name=payload["teamName"], -1928 ) -1929 -1930 def deserialize_post_activity( -1931 self, payload: typedefs.JSONObject -1932 ) -> activity.PostActivity: -1933 period = time.clean_date(payload["period"]) -1934 details = payload["activityDetails"] -1935 ref_id = int(details["referenceId"]) -1936 instance_id = int(details["instanceId"]) -1937 mode = enums.GameMode(details["mode"]) -1938 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] -1939 is_private = details["isPrivate"] -1940 membership_type = enums.MembershipType(int(details["membershipType"])) -1941 return activity.PostActivity( -1942 net=self._net, -1943 hash=ref_id, -1944 membership_type=membership_type, -1945 instance_id=instance_id, -1946 mode=mode, -1947 modes=modes, -1948 is_private=is_private, -1949 occurred_at=period, -1950 starting_phase=int(payload["startingPhaseIndex"]), -1951 players=[ -1952 self.deserialize_post_activity_player(player) -1953 for player in payload["entries"] -1954 ], -1955 teams=[ -1956 self._deserialize_post_activity_team(team) for team in payload["teams"] -1957 ], -1958 ) +1894 character_level: typedefs.NoneOr[int] = None +1895 if (character_level := player.get("characterLevel")) is not None: +1896 character_level = character_level +1897 +1898 return activity.PostActivityPlayer( +1899 standing=int(payload["standing"]), +1900 score=int(payload["score"]["basic"]["value"]), +1901 character_id=payload["characterId"], +1902 destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]), +1903 character_class=character_class, +1904 character_level=character_level, +1905 race_hash=race_hash, +1906 gender_hash=gender_hash, +1907 class_hash=class_hash, +1908 light_level=int(player["lightLevel"]), +1909 emblem_hash=int(player["emblemHash"]), +1910 values=self._deserialize_activity_values(payload["values"]), +1911 extended_values=self._deserialize_extended_values(payload["extended"]), +1912 ) +1913 +1914 def _deserialize_post_activity_team( +1915 self, payload: typedefs.JSONObject +1916 ) -> activity.PostActivityTeam: +1917 return activity.PostActivityTeam( +1918 id=payload["teamId"], +1919 is_defeated=bool(payload["standing"]["basic"]["value"]), +1920 score=int(payload["score"]["basic"]["value"]), +1921 name=payload["teamName"], +1922 ) +1923 +1924 def deserialize_post_activity( +1925 self, payload: typedefs.JSONObject +1926 ) -> activity.PostActivity: +1927 period = time.clean_date(payload["period"]) +1928 details = payload["activityDetails"] +1929 ref_id = int(details["referenceId"]) +1930 instance_id = int(details["instanceId"]) +1931 mode = enums.GameMode(details["mode"]) +1932 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] +1933 is_private = details["isPrivate"] +1934 membership_type = enums.MembershipType(int(details["membershipType"])) +1935 return activity.PostActivity( +1936 net=self._net, +1937 hash=ref_id, +1938 membership_type=membership_type, +1939 instance_id=instance_id, +1940 mode=mode, +1941 modes=modes, +1942 is_private=is_private, +1943 occurred_at=period, +1944 starting_phase=int(payload["startingPhaseIndex"]), +1945 players=[ +1946 self.deserialize_post_activity_player(player) +1947 for player in payload["entries"] +1948 ], +1949 teams=[ +1950 self._deserialize_post_activity_team(team) for team in payload["teams"] +1951 ], +1952 ) +1953 +1954 def _deserialize_aggregated_activity_values( +1955 self, payload: typedefs.JSONObject +1956 ) -> activity.AggregatedActivityValues: +1957 # This ID is always the same for all aggregated values. +1958 activity_id = int(payload["fastestCompletionMsForActivity"]["activityId"]) 1959 -1960 def _deserialize_aggregated_activity_values( -1961 self, payload: typedefs.JSONObject -1962 ) -> activity.AggregatedActivityValues: -1963 # This ID is always the same for all aggregated values. -1964 activity_id = int(payload["fastestCompletionMsForActivity"]["activityId"]) -1965 -1966 return activity.AggregatedActivityValues( -1967 id=activity_id, -1968 fastest_completion_time=( -1969 int(payload["fastestCompletionMsForActivity"]["basic"]["value"]), -1970 payload["fastestCompletionMsForActivity"]["basic"]["displayValue"], -1971 ), -1972 completions=int(payload["activityCompletions"]["basic"]["value"]), -1973 kills=int(payload["activityKills"]["basic"]["value"]), -1974 deaths=int(payload["activityDeaths"]["basic"]["value"]), -1975 assists=int(payload["activityAssists"]["basic"]["value"]), -1976 seconds_played=( -1977 int(payload["activitySecondsPlayed"]["basic"]["value"]), -1978 payload["activitySecondsPlayed"]["basic"]["displayValue"], -1979 ), -1980 wins=int(payload["activityWins"]["basic"]["value"]), -1981 goals_missed=int(payload["activityGoalsMissed"]["basic"]["value"]), -1982 special_actions=int(payload["activitySpecialActions"]["basic"]["value"]), -1983 best_goals_hit=int(payload["activityBestGoalsHit"]["basic"]["value"]), -1984 best_single_score=int( -1985 payload["activityBestSingleGameScore"]["basic"]["value"] +1960 return activity.AggregatedActivityValues( +1961 id=activity_id, +1962 fastest_completion_time=( +1963 int(payload["fastestCompletionMsForActivity"]["basic"]["value"]), +1964 payload["fastestCompletionMsForActivity"]["basic"]["displayValue"], +1965 ), +1966 completions=int(payload["activityCompletions"]["basic"]["value"]), +1967 kills=int(payload["activityKills"]["basic"]["value"]), +1968 deaths=int(payload["activityDeaths"]["basic"]["value"]), +1969 assists=int(payload["activityAssists"]["basic"]["value"]), +1970 seconds_played=( +1971 int(payload["activitySecondsPlayed"]["basic"]["value"]), +1972 payload["activitySecondsPlayed"]["basic"]["displayValue"], +1973 ), +1974 wins=int(payload["activityWins"]["basic"]["value"]), +1975 goals_missed=int(payload["activityGoalsMissed"]["basic"]["value"]), +1976 special_actions=int(payload["activitySpecialActions"]["basic"]["value"]), +1977 best_goals_hit=int(payload["activityBestGoalsHit"]["basic"]["value"]), +1978 best_single_score=int( +1979 payload["activityBestSingleGameScore"]["basic"]["value"] +1980 ), +1981 goals_hit=int(payload["activityGoalsHit"]["basic"]["value"]), +1982 special_score=int(payload["activitySpecialScore"]["basic"]["value"]), +1983 kd_assists=int(payload["activityKillsDeathsAssists"]["basic"]["value"]), +1984 kd_ratio=float( +1985 payload["activityKillsDeathsAssists"]["basic"]["displayValue"] 1986 ), -1987 goals_hit=int(payload["activityGoalsHit"]["basic"]["value"]), -1988 special_score=int(payload["activitySpecialScore"]["basic"]["value"]), -1989 kd_assists=int(payload["activityKillsDeathsAssists"]["basic"]["value"]), -1990 kd_ratio=float( -1991 payload["activityKillsDeathsAssists"]["basic"]["displayValue"] -1992 ), -1993 precision_kills=int(payload["activityPrecisionKills"]["basic"]["value"]), -1994 ) -1995 -1996 def deserialize_aggregated_activity( -1997 self, payload: typedefs.JSONObject -1998 ) -> activity.AggregatedActivity: -1999 return activity.AggregatedActivity( -2000 hash=int(payload["activityHash"]), -2001 values=self._deserialize_aggregated_activity_values(payload["values"]), -2002 ) -2003 -2004 def deserialize_aggregated_activities( -2005 self, payload: typedefs.JSONObject -2006 ) -> iterators.FlatIterator[activity.AggregatedActivity]: -2007 return iterators.FlatIterator( -2008 [ -2009 self.deserialize_aggregated_activity(activity) -2010 for activity in payload["activities"] -2011 ] -2012 ) -2013 -2014 def deserialize_linked_profiles( -2015 self, payload: typedefs.JSONObject -2016 ) -> profile.LinkedProfile: -2017 bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"]) -2018 error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] -2019 profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] -2020 -2021 if raw_profile := payload.get("profiles"): -2022 for pfile in raw_profile: -2023 profiles_vec.append(self.deserialize_destiny_membership(pfile)) -2024 -2025 if raw_profiles_with_errors := payload.get("profilesWithErrors"): -2026 for raw_error_pfile in raw_profiles_with_errors: -2027 if error_pfile := raw_error_pfile.get("infoCard"): -2028 error_profiles_vec.append( -2029 self.deserialize_destiny_membership(error_pfile) -2030 ) -2031 -2032 return profile.LinkedProfile( -2033 net=self._net, -2034 bungie=bungie_user, -2035 profiles=profiles_vec, -2036 profiles_with_errors=error_profiles_vec, -2037 ) -2038 -2039 def deserialize_clan_banners( -2040 self, payload: typedefs.JSONObject -2041 ) -> collections.Sequence[clans.ClanBanner]: -2042 banners_seq: typing.MutableSequence[clans.ClanBanner] = [] -2043 if banners := payload.get("clanBannerDecals"): -2044 for k, v in banners.items(): -2045 banner_obj = clans.ClanBanner( -2046 id=int(k), -2047 foreground=assets.Image(v["foregroundPath"]), -2048 background=assets.Image(v["backgroundPath"]), -2049 ) -2050 banners_seq.append(banner_obj) -2051 return banners_seq -2052 -2053 def deserialize_public_milestone_content( -2054 self, payload: typedefs.JSONObject -2055 ) -> milestones.MilestoneContent: -2056 items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None -2057 if raw_categories := payload.get("itemCategories"): -2058 for item in raw_categories: -2059 title = undefined.Undefined -2060 if raw_title := item.get("title"): -2061 if raw_title != typedefs.Unknown: -2062 title = raw_title -2063 if raw_hashes := item.get("itemHashes"): -2064 hashes: collections.Sequence[int] = raw_hashes +1987 precision_kills=int(payload["activityPrecisionKills"]["basic"]["value"]), +1988 ) +1989 +1990 def deserialize_aggregated_activity( +1991 self, payload: typedefs.JSONObject +1992 ) -> activity.AggregatedActivity: +1993 return activity.AggregatedActivity( +1994 hash=int(payload["activityHash"]), +1995 values=self._deserialize_aggregated_activity_values(payload["values"]), +1996 ) +1997 +1998 def deserialize_aggregated_activities( +1999 self, payload: typedefs.JSONObject +2000 ) -> iterators.Iterator[activity.AggregatedActivity]: +2001 return iterators.Iterator( +2002 [ +2003 self.deserialize_aggregated_activity(activity) +2004 for activity in payload["activities"] +2005 ] +2006 ) +2007 +2008 def deserialize_linked_profiles( +2009 self, payload: typedefs.JSONObject +2010 ) -> profile.LinkedProfile: +2011 bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"]) +2012 error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] +2013 profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] +2014 +2015 if raw_profile := payload.get("profiles"): +2016 for pfile in raw_profile: +2017 profiles_vec.append(self.deserialize_destiny_membership(pfile)) +2018 +2019 if raw_profiles_with_errors := payload.get("profilesWithErrors"): +2020 for raw_error_pfile in raw_profiles_with_errors: +2021 if error_pfile := raw_error_pfile.get("infoCard"): +2022 error_profiles_vec.append( +2023 self.deserialize_destiny_membership(error_pfile) +2024 ) +2025 +2026 return profile.LinkedProfile( +2027 net=self._net, +2028 bungie=bungie_user, +2029 profiles=profiles_vec, +2030 profiles_with_errors=error_profiles_vec, +2031 ) +2032 +2033 def deserialize_clan_banners( +2034 self, payload: typedefs.JSONObject +2035 ) -> collections.Sequence[clans.ClanBanner]: +2036 banners_seq: typing.MutableSequence[clans.ClanBanner] = [] +2037 if banners := payload.get("clanBannerDecals"): +2038 for k, v in banners.items(): +2039 banner_obj = clans.ClanBanner( +2040 id=int(k), +2041 foreground=assets.Image(v["foregroundPath"]), +2042 background=assets.Image(v["backgroundPath"]), +2043 ) +2044 banners_seq.append(banner_obj) +2045 return banners_seq +2046 +2047 def deserialize_public_milestone_content( +2048 self, payload: typedefs.JSONObject +2049 ) -> milestones.MilestoneContent: +2050 items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None +2051 if raw_categories := payload.get("itemCategories"): +2052 for item in raw_categories: +2053 title = undefined.Undefined +2054 if raw_title := item.get("title"): +2055 if raw_title != typedefs.Unknown: +2056 title = raw_title +2057 if raw_hashes := item.get("itemHashes"): +2058 hashes: collections.Sequence[int] = raw_hashes +2059 +2060 items_categoris = milestones.MilestoneItems(title=title, hashes=hashes) +2061 +2062 about = undefined.Undefined +2063 if (raw_about := payload["about"]) != typedefs.Unknown: +2064 about = raw_about 2065 -2066 items_categoris = milestones.MilestoneItems(title=title, hashes=hashes) -2067 -2068 about = undefined.Undefined -2069 if (raw_about := payload["about"]) != typedefs.Unknown: -2070 about = raw_about -2071 -2072 status = undefined.Undefined -2073 if (raw_status := payload["status"]) != typedefs.Unknown: -2074 status = raw_status -2075 -2076 tips: typing.MutableSequence[undefined.UndefinedOr[str]] = [] -2077 if raw_tips := payload.get("tips"): -2078 for raw_tip in raw_tips: -2079 if raw_tip == typedefs.Unknown: -2080 raw_tip = undefined.Undefined -2081 tips.append(raw_tip) -2082 -2083 return milestones.MilestoneContent( -2084 about=about, status=status, tips=tips, items=items_categoris -2085 ) -2086 -2087 def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend: -2088 name = undefined.Undefined -2089 if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown: -2090 name = raw_name -2091 -2092 bungie_user: typedefs.NoneOr[user.BungieUser] = None -2093 -2094 if raw_bungie_user := payload.get("bungieNetUser"): -2095 bungie_user = self.deserialize_bungie_user(raw_bungie_user) -2096 -2097 return friends.Friend( -2098 net=self._net, -2099 id=int(payload["lastSeenAsMembershipId"]), -2100 name=name, -2101 code=payload.get("bungieGlobalDisplayNameCode"), -2102 relationship=enums.Relationship(payload["relationship"]), -2103 user=bungie_user, -2104 online_status=enums.Presence(payload["onlineStatus"]), -2105 online_title=payload["onlineTitle"], -2106 type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]), -2107 ) -2108 -2109 def deserialize_friends( -2110 self, payload: typedefs.JSONObject -2111 ) -> collections.Sequence[friends.Friend]: -2112 mut_seq: typing.MutableSequence[friends.Friend] = [] -2113 if raw_friends := payload.get("friends"): -2114 for friend in raw_friends: -2115 mut_seq.append(self.deserialize_friend(friend)) -2116 return mut_seq +2066 status = undefined.Undefined +2067 if (raw_status := payload["status"]) != typedefs.Unknown: +2068 status = raw_status +2069 +2070 tips: typing.MutableSequence[undefined.UndefinedOr[str]] = [] +2071 if raw_tips := payload.get("tips"): +2072 for raw_tip in raw_tips: +2073 if raw_tip == typedefs.Unknown: +2074 raw_tip = undefined.Undefined +2075 tips.append(raw_tip) +2076 +2077 return milestones.MilestoneContent( +2078 about=about, status=status, tips=tips, items=items_categoris +2079 ) +2080 +2081 def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend: +2082 name = undefined.Undefined +2083 if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown: +2084 name = raw_name +2085 +2086 bungie_user: typedefs.NoneOr[user.BungieUser] = None +2087 +2088 if raw_bungie_user := payload.get("bungieNetUser"): +2089 bungie_user = self.deserialize_bungie_user(raw_bungie_user) +2090 +2091 return friends.Friend( +2092 net=self._net, +2093 id=int(payload["lastSeenAsMembershipId"]), +2094 name=name, +2095 code=payload.get("bungieGlobalDisplayNameCode"), +2096 relationship=enums.Relationship(payload["relationship"]), +2097 user=bungie_user, +2098 online_status=enums.Presence(payload["onlineStatus"]), +2099 online_title=payload["onlineTitle"], +2100 type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]), +2101 ) +2102 +2103 def deserialize_friends( +2104 self, payload: typedefs.JSONObject +2105 ) -> collections.Sequence[friends.Friend]: +2106 mut_seq: typing.MutableSequence[friends.Friend] = [] +2107 if raw_friends := payload.get("friends"): +2108 for friend in raw_friends: +2109 mut_seq.append(self.deserialize_friend(friend)) +2110 return mut_seq +2111 +2112 def deserialize_friend_requests( +2113 self, payload: typedefs.JSONObject +2114 ) -> friends.FriendRequestView: +2115 incoming: typing.MutableSequence[friends.Friend] = [] +2116 outgoing: typing.MutableSequence[friends.Friend] = [] 2117 -2118 def deserialize_friend_requests( -2119 self, payload: typedefs.JSONObject -2120 ) -> friends.FriendRequestView: -2121 incoming: typing.MutableSequence[friends.Friend] = [] -2122 outgoing: typing.MutableSequence[friends.Friend] = [] -2123 -2124 if raw_incoming_requests := payload.get("incomingRequests"): -2125 for incoming_request in raw_incoming_requests: -2126 incoming.append(self.deserialize_friend(incoming_request)) +2118 if raw_incoming_requests := payload.get("incomingRequests"): +2119 for incoming_request in raw_incoming_requests: +2120 incoming.append(self.deserialize_friend(incoming_request)) +2121 +2122 if raw_outgoing_requests := payload.get("outgoingRequests"): +2123 for outgoing_request in raw_outgoing_requests: +2124 outgoing.append(self.deserialize_friend(outgoing_request)) +2125 +2126 return friends.FriendRequestView(incoming=incoming, outgoing=outgoing) 2127 -2128 if raw_outgoing_requests := payload.get("outgoingRequests"): -2129 for outgoing_request in raw_outgoing_requests: -2130 outgoing.append(self.deserialize_friend(outgoing_request)) -2131 -2132 return friends.FriendRequestView(incoming=incoming, outgoing=outgoing) -2133 -2134 def _set_fireteam_fields( -2135 self, payload: typedefs.JSONObject, total_results: typing.Optional[int] = None -2136 ) -> fireteams.Fireteam: -2137 activity_type = fireteams.FireteamActivity(payload["activityType"]) -2138 return fireteams.Fireteam( -2139 id=int(payload["fireteamId"]), -2140 group_id=int(payload["groupId"]), -2141 platform=fireteams.FireteamPlatform(payload["platform"]), -2142 is_immediate=payload["isImmediate"], -2143 activity_type=activity_type, -2144 owner_id=int(payload["ownerMembershipId"]), -2145 player_slot_count=payload["playerSlotCount"], -2146 available_player_slots=payload["availablePlayerSlotCount"], -2147 available_alternate_slots=payload["availableAlternateSlotCount"], -2148 title=payload["title"], -2149 date_created=time.clean_date(payload["dateCreated"]), -2150 is_public=payload["isPublic"], -2151 locale=fireteams.FireteamLanguage(payload["locale"]), -2152 is_valid=payload["isValid"], -2153 last_modified=time.clean_date(payload["datePlayerModified"]), -2154 total_results=total_results or 0, -2155 ) -2156 -2157 def deserialize_fireteams( -2158 self, payload: typedefs.JSONObject -2159 ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]: -2160 fireteams_: typing.MutableSequence[fireteams.Fireteam] = [] -2161 -2162 result: list[typedefs.JSONObject] -2163 if not (result := payload["results"]): -2164 return None -2165 for elem in result: -2166 fireteams_.append( -2167 self._set_fireteam_fields( -2168 elem, total_results=int(payload["totalResults"]) -2169 ) -2170 ) -2171 return fireteams_ -2172 -2173 def deserialize_fireteam_destiny_users( -2174 self, payload: typedefs.JSONObject -2175 ) -> fireteams.FireteamUser: -2176 destiny_obj = self.deserialize_destiny_membership(payload) -2177 # We could helpers.just return a DestinyMembership object but this is -2178 # missing the fireteam display name and id fields. -2179 return fireteams.FireteamUser( -2180 net=self._net, -2181 id=destiny_obj.id, -2182 code=destiny_obj.code, -2183 icon=destiny_obj.icon, -2184 types=destiny_obj.types, -2185 type=destiny_obj.type, -2186 is_public=destiny_obj.is_public, -2187 crossave_override=destiny_obj.crossave_override, -2188 name=destiny_obj.name, -2189 last_seen_name=destiny_obj.last_seen_name, -2190 fireteam_display_name=payload["FireteamDisplayName"], -2191 fireteam_membership_id=enums.MembershipType( -2192 payload["FireteamMembershipType"] -2193 ), -2194 ) -2195 -2196 def deserialize_fireteam_members( -2197 self, payload: typedefs.JSONObject, *, alternatives: bool = False -2198 ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]: -2199 members_: list[fireteams.FireteamMember] = [] -2200 if members := payload.get("Members" if not alternatives else "Alternates"): -2201 for member in members: -2202 bungie_fields = self.deserialize_partial_bungie_user(member) -2203 members_fields = fireteams.FireteamMember( -2204 destiny_user=self.deserialize_fireteam_destiny_users(member), -2205 has_microphone=member["hasMicrophone"], -2206 character_id=int(member["characterId"]), -2207 date_joined=time.clean_date(member["dateJoined"]), -2208 last_platform_invite_date=time.clean_date( -2209 member["lastPlatformInviteAttemptDate"] -2210 ), -2211 last_platform_invite_result=int( -2212 member["lastPlatformInviteAttemptResult"] -2213 ), -2214 net=self._net, -2215 name=bungie_fields.name, -2216 id=bungie_fields.id, -2217 icon=bungie_fields.icon, -2218 is_public=bungie_fields.is_public, -2219 crossave_override=bungie_fields.crossave_override, -2220 types=bungie_fields.types, -2221 type=bungie_fields.type, -2222 ) -2223 members_.append(members_fields) -2224 else: -2225 return None -2226 return members_ -2227 -2228 def deserialize_available_fireteams( -2229 self, -2230 data: typedefs.JSONObject, -2231 *, -2232 no_results: bool = False, -2233 ) -> typing.Union[ -2234 fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam] -2235 ]: -2236 fireteams_: list[fireteams.AvailableFireteam] = [] -2237 -2238 # This needs to be used outside the results -2239 # JSON key. -2240 if no_results is True: -2241 payload = data -2242 -2243 if result := payload.get("results"): -2244 -2245 for fireteam in result: -2246 found_fireteams = self._set_fireteam_fields(fireteam["Summary"]) -2247 fireteams_fields = fireteams.AvailableFireteam( -2248 id=found_fireteams.id, -2249 group_id=found_fireteams.group_id, -2250 platform=found_fireteams.platform, -2251 activity_type=found_fireteams.activity_type, -2252 is_immediate=found_fireteams.is_immediate, -2253 is_public=found_fireteams.is_public, -2254 is_valid=found_fireteams.is_valid, -2255 owner_id=found_fireteams.owner_id, -2256 player_slot_count=found_fireteams.player_slot_count, -2257 available_player_slots=found_fireteams.available_player_slots, -2258 available_alternate_slots=found_fireteams.available_alternate_slots, -2259 title=found_fireteams.title, -2260 date_created=found_fireteams.date_created, -2261 locale=found_fireteams.locale, -2262 last_modified=found_fireteams.last_modified, -2263 total_results=found_fireteams.total_results, -2264 members=self.deserialize_fireteam_members(payload), -2265 alternatives=self.deserialize_fireteam_members( -2266 payload, alternatives=True -2267 ), -2268 ) -2269 fireteams_.append(fireteams_fields) -2270 if no_results: -2271 return fireteams_fields -2272 return fireteams_ -2273 -2274 def deserialize_fireteam_party( -2275 self, payload: typedefs.JSONObject -2276 ) -> fireteams.FireteamParty: -2277 last_destination_hash: typing.Optional[int] = None -2278 if raw_dest_hash := payload.get("lastOrbitedDestinationHash"): -2279 last_destination_hash = int(raw_dest_hash) -2280 -2281 return fireteams.FireteamParty( -2282 members=[ -2283 self._deserialize_fireteam_party_member(member) -2284 for member in payload["partyMembers"] -2285 ], -2286 activity=self._deserialize_fireteam_party_current_activity( -2287 payload["currentActivity"] -2288 ), -2289 settings=self._deserialize_fireteam_party_settings(payload["joinability"]), -2290 last_destination_hash=last_destination_hash, -2291 tracking=payload["tracking"], -2292 ) -2293 -2294 def _deserialize_fireteam_party_member( -2295 self, payload: typedefs.JSONObject -2296 ) -> fireteams.FireteamPartyMember: -2297 -2298 status = fireteams.FireteamPartyMemberState(payload["status"]) -2299 displayname: undefined.UndefinedOr[str] = undefined.Undefined -2300 if raw_name := payload.get("displayName"): -2301 displayname = raw_name -2302 -2303 return fireteams.FireteamPartyMember( -2304 membership_id=int(payload["membershipId"]), -2305 emblem_hash=int(payload["emblemHash"]), -2306 status=status, -2307 display_name=displayname, -2308 ) -2309 -2310 def _deserialize_fireteam_party_current_activity( -2311 self, payload: typedefs.JSONObject -2312 ) -> fireteams.FireteamPartyCurrentActivity: -2313 start_date: typing.Optional[datetime.datetime] = None -2314 if raw_start_date := payload.get("startTime"): -2315 start_date = time.clean_date(raw_start_date) -2316 -2317 end_date: typing.Optional[datetime.datetime] = None -2318 if raw_end_date := payload.get("endTime"): -2319 end_date = time.clean_date(raw_end_date) -2320 return fireteams.FireteamPartyCurrentActivity( -2321 start_time=start_date, -2322 end_time=end_date, -2323 score=float(payload["score"]), -2324 highest_opposing_score=float(payload["highestOpposingFactionScore"]), -2325 opponenst_count=int(payload["numberOfOpponents"]), -2326 player_count=int(payload["numberOfPlayers"]), -2327 ) -2328 -2329 def _deserialize_fireteam_party_settings( -2330 self, payload: typedefs.JSONObject -2331 ) -> fireteams.FireteamPartySettings: -2332 closed_reasons = enums.ClosedReasons(payload["closedReasons"]) -2333 return fireteams.FireteamPartySettings( -2334 open_slots=int(payload["openSlots"]), -2335 privacy_setting=enums.PrivacySetting(int(payload["privacySetting"])), -2336 closed_reasons=closed_reasons, -2337 ) -2338 -2339 def deserialize_seasonal_artifact( -2340 self, payload: typedefs.JSONObject -2341 ) -> season.Artifact: -2342 if raw_artifact := payload.get("seasonalArtifact"): -2343 if points := raw_artifact.get("pointProgression"): -2344 points_prog = progressions.Progression( -2345 hash=points["progressionHash"], -2346 level=points["level"], -2347 cap=points["levelCap"], -2348 daily_limit=points["dailyLimit"], -2349 weekly_limit=points["weeklyLimit"], -2350 current_progress=points["currentProgress"], -2351 daily_progress=points["dailyProgress"], -2352 needed=points["progressToNextLevel"], -2353 next_level=points["nextLevelAt"], -2354 ) -2355 -2356 if bonus := raw_artifact.get("powerBonusProgression"): -2357 power_bonus_prog = progressions.Progression( -2358 hash=bonus["progressionHash"], -2359 level=bonus["level"], -2360 cap=bonus["levelCap"], -2361 daily_limit=bonus["dailyLimit"], -2362 weekly_limit=bonus["weeklyLimit"], -2363 current_progress=bonus["currentProgress"], -2364 daily_progress=bonus["dailyProgress"], -2365 needed=bonus["progressToNextLevel"], -2366 next_level=bonus["nextLevelAt"], -2367 ) -2368 artifact = season.Artifact( -2369 net=self._net, -2370 hash=raw_artifact["artifactHash"], -2371 power_bonus=raw_artifact["powerBonus"], -2372 acquired_points=raw_artifact["pointsAcquired"], -2373 bonus=power_bonus_prog, -2374 points=points_prog, -2375 ) -2376 return artifact -2377 -2378 def deserialize_profile_progression( -2379 self, payload: typedefs.JSONObject -2380 ) -> profile.ProfileProgression: -2381 return profile.ProfileProgression( -2382 artifact=self.deserialize_seasonal_artifact(payload["data"]), -2383 checklist={ -2384 int(check_id): checklists -2385 for check_id, checklists in payload["data"]["checklists"].items() -2386 }, -2387 ) -2388 -2389 def deserialize_instanced_item( -2390 self, payload: typedefs.JSONObject -2391 ) -> items.ItemInstance: -2392 damage_type_hash: typing.Optional[int] = None -2393 if raw_damagetype_hash := payload.get("damageTypeHash"): -2394 damage_type_hash = int(raw_damagetype_hash) -2395 -2396 required_hashes: typing.Optional[collections.Collection[int]] = None -2397 if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"): -2398 required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes] -2399 -2400 breaker_type: typing.Optional[items.ItemBreakerType] = None -2401 if raw_break_type := payload.get("breakerType"): -2402 breaker_type = items.ItemBreakerType(int(raw_break_type)) -2403 -2404 breaker_type_hash: typing.Optional[int] = None -2405 if raw_break_type_hash := payload.get("breakerTypeHash"): -2406 breaker_type_hash = int(raw_break_type_hash) -2407 -2408 energy: typing.Optional[items.ItemEnergy] = None -2409 if raw_energy := payload.get("energy"): -2410 energy = self.deserialize_item_energy(raw_energy) -2411 -2412 primary_stats = None -2413 if raw_primary_stats := payload.get("primaryStat"): -2414 primary_stats = self.deserialize_item_stats_view(raw_primary_stats) -2415 -2416 return items.ItemInstance( -2417 damage_type=enums.DamageType(int(payload["damageType"])), -2418 damage_type_hash=damage_type_hash, -2419 primary_stat=primary_stats, -2420 item_level=int(payload["itemLevel"]), -2421 quality=int(payload["quality"]), -2422 is_equipped=payload["isEquipped"], -2423 can_equip=payload["canEquip"], -2424 equip_required_level=int(payload["equipRequiredLevel"]), -2425 required_equip_unlock_hashes=required_hashes, -2426 cant_equip_reason=int(payload["cannotEquipReason"]), -2427 breaker_type=breaker_type, -2428 breaker_type_hash=breaker_type_hash, -2429 energy=energy, -2430 ) -2431 -2432 def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy: -2433 energy_hash: typing.Optional[int] = None -2434 if raw_energy_hash := payload.get("energyTypeHash"): -2435 energy_hash = int(raw_energy_hash) -2436 -2437 return items.ItemEnergy( -2438 hash=energy_hash, -2439 type=items.ItemEnergyType(int(payload["energyType"])), -2440 capacity=int(payload["energyCapacity"]), -2441 used_energy=int(payload["energyUsed"]), -2442 unused_energy=int(payload["energyUnused"]), -2443 ) -2444 -2445 def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk: -2446 perk_hash: typing.Optional[int] = None -2447 if raw_perk_hash := payload.get("perkHash"): -2448 perk_hash = int(raw_perk_hash) -2449 -2450 return items.ItemPerk( -2451 hash=perk_hash, -2452 icon=assets.Image(payload["iconPath"]), -2453 is_active=payload["isActive"], -2454 is_visible=payload["visible"], -2455 ) -2456 -2457 def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket: -2458 plug_hash: typing.Optional[int] = None -2459 if raw_plug_hash := payload.get("plugHash"): -2460 plug_hash = int(raw_plug_hash) -2461 -2462 enable_fail_indexes: typing.Optional[list[int]] = None -2463 if raw_indexes := payload.get("enableFailIndexes"): -2464 enable_fail_indexes = [int(index) for index in raw_indexes] -2465 -2466 return items.ItemSocket( -2467 plug_hash=plug_hash, -2468 is_enabled=payload["isEnabled"], -2469 enable_fail_indexes=enable_fail_indexes, -2470 is_visible=payload.get("visible"), -2471 ) -2472 -2473 def deserialize_item_stats_view( -2474 self, payload: typedefs.JSONObject -2475 ) -> items.ItemStatsView: -2476 return items.ItemStatsView( -2477 stat_hash=payload.get("statHash"), value=payload.get("value") -2478 ) -2479 -2480 def deserialize_plug_item_state( -2481 self, payload: typedefs.JSONObject -2482 ) -> items.PlugItemState: -2483 item_hash: typing.Optional[int] = None -2484 if raw_item_hash := payload.get("plugItemHash"): -2485 item_hash = int(raw_item_hash) -2486 -2487 insert_fail_indexes: typedefs.NoneOr[list[int]] = None -2488 if raw_fail_indexes := payload.get("insertFailIndexes"): -2489 insert_fail_indexes = [int(k) for k in raw_fail_indexes] -2490 -2491 enable_fail_indexes: typedefs.NoneOr[list[int]] = None -2492 if raw_enabled_indexes := payload.get("enableFailIndexes"): -2493 enable_fail_indexes = [int(k) for k in raw_enabled_indexes] -2494 -2495 return items.PlugItemState( -2496 item_hash=item_hash, -2497 insert_fail_indexes=insert_fail_indexes, -2498 enable_fail_indexes=enable_fail_indexes, -2499 is_enabled=payload["enabled"], -2500 can_insert=payload["canInsert"], -2501 ) +2128 def _set_fireteam_fields( +2129 self, payload: typedefs.JSONObject, total_results: typing.Optional[int] = None +2130 ) -> fireteams.Fireteam: +2131 activity_type = fireteams.FireteamActivity(payload["activityType"]) +2132 return fireteams.Fireteam( +2133 id=int(payload["fireteamId"]), +2134 group_id=int(payload["groupId"]), +2135 platform=fireteams.FireteamPlatform(payload["platform"]), +2136 is_immediate=payload["isImmediate"], +2137 activity_type=activity_type, +2138 owner_id=int(payload["ownerMembershipId"]), +2139 player_slot_count=payload["playerSlotCount"], +2140 available_player_slots=payload["availablePlayerSlotCount"], +2141 available_alternate_slots=payload["availableAlternateSlotCount"], +2142 title=payload["title"], +2143 date_created=time.clean_date(payload["dateCreated"]), +2144 is_public=payload["isPublic"], +2145 locale=fireteams.FireteamLanguage(payload["locale"]), +2146 is_valid=payload["isValid"], +2147 last_modified=time.clean_date(payload["datePlayerModified"]), +2148 total_results=total_results or 0, +2149 ) +2150 +2151 def deserialize_fireteams( +2152 self, payload: typedefs.JSONObject +2153 ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]: +2154 fireteams_: typing.MutableSequence[fireteams.Fireteam] = [] +2155 +2156 result: list[typedefs.JSONObject] +2157 if not (result := payload["results"]): +2158 return None +2159 for elem in result: +2160 fireteams_.append( +2161 self._set_fireteam_fields( +2162 elem, total_results=int(payload["totalResults"]) +2163 ) +2164 ) +2165 return fireteams_ +2166 +2167 def deserialize_fireteam_destiny_users( +2168 self, payload: typedefs.JSONObject +2169 ) -> fireteams.FireteamUser: +2170 destiny_obj = self.deserialize_destiny_membership(payload) +2171 # We could helpers.just return a DestinyMembership object but this is +2172 # missing the fireteam display name and id fields. +2173 return fireteams.FireteamUser( +2174 net=self._net, +2175 id=destiny_obj.id, +2176 code=destiny_obj.code, +2177 icon=destiny_obj.icon, +2178 types=destiny_obj.types, +2179 type=destiny_obj.type, +2180 is_public=destiny_obj.is_public, +2181 crossave_override=destiny_obj.crossave_override, +2182 name=destiny_obj.name, +2183 last_seen_name=destiny_obj.last_seen_name, +2184 fireteam_display_name=payload["FireteamDisplayName"], +2185 fireteam_membership_id=enums.MembershipType( +2186 payload["FireteamMembershipType"] +2187 ), +2188 ) +2189 +2190 def deserialize_fireteam_members( +2191 self, payload: typedefs.JSONObject, *, alternatives: bool = False +2192 ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]: +2193 members_: list[fireteams.FireteamMember] = [] +2194 if members := payload.get("Members" if not alternatives else "Alternates"): +2195 for member in members: +2196 bungie_fields = self.deserialize_partial_bungie_user(member) +2197 members_fields = fireteams.FireteamMember( +2198 destiny_user=self.deserialize_fireteam_destiny_users(member), +2199 has_microphone=member["hasMicrophone"], +2200 character_id=int(member["characterId"]), +2201 date_joined=time.clean_date(member["dateJoined"]), +2202 last_platform_invite_date=time.clean_date( +2203 member["lastPlatformInviteAttemptDate"] +2204 ), +2205 last_platform_invite_result=int( +2206 member["lastPlatformInviteAttemptResult"] +2207 ), +2208 net=self._net, +2209 name=bungie_fields.name, +2210 id=bungie_fields.id, +2211 icon=bungie_fields.icon, +2212 is_public=bungie_fields.is_public, +2213 crossave_override=bungie_fields.crossave_override, +2214 types=bungie_fields.types, +2215 type=bungie_fields.type, +2216 ) +2217 members_.append(members_fields) +2218 else: +2219 return None +2220 return members_ +2221 +2222 def deserialize_available_fireteams( +2223 self, +2224 data: typedefs.JSONObject, +2225 *, +2226 no_results: bool = False, +2227 ) -> typing.Union[ +2228 fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam] +2229 ]: +2230 fireteams_: list[fireteams.AvailableFireteam] = [] +2231 +2232 # This needs to be used outside the results +2233 # JSON key. +2234 if no_results is True: +2235 payload = data +2236 +2237 if result := payload.get("results"): +2238 +2239 for fireteam in result: +2240 found_fireteams = self._set_fireteam_fields(fireteam["Summary"]) +2241 fireteams_fields = fireteams.AvailableFireteam( +2242 id=found_fireteams.id, +2243 group_id=found_fireteams.group_id, +2244 platform=found_fireteams.platform, +2245 activity_type=found_fireteams.activity_type, +2246 is_immediate=found_fireteams.is_immediate, +2247 is_public=found_fireteams.is_public, +2248 is_valid=found_fireteams.is_valid, +2249 owner_id=found_fireteams.owner_id, +2250 player_slot_count=found_fireteams.player_slot_count, +2251 available_player_slots=found_fireteams.available_player_slots, +2252 available_alternate_slots=found_fireteams.available_alternate_slots, +2253 title=found_fireteams.title, +2254 date_created=found_fireteams.date_created, +2255 locale=found_fireteams.locale, +2256 last_modified=found_fireteams.last_modified, +2257 total_results=found_fireteams.total_results, +2258 members=self.deserialize_fireteam_members(payload), +2259 alternatives=self.deserialize_fireteam_members( +2260 payload, alternatives=True +2261 ), +2262 ) +2263 fireteams_.append(fireteams_fields) +2264 if no_results: +2265 return fireteams_fields +2266 return fireteams_ +2267 +2268 def deserialize_fireteam_party( +2269 self, payload: typedefs.JSONObject +2270 ) -> fireteams.FireteamParty: +2271 last_destination_hash: typing.Optional[int] = None +2272 if raw_dest_hash := payload.get("lastOrbitedDestinationHash"): +2273 last_destination_hash = int(raw_dest_hash) +2274 +2275 return fireteams.FireteamParty( +2276 members=[ +2277 self._deserialize_fireteam_party_member(member) +2278 for member in payload["partyMembers"] +2279 ], +2280 activity=self._deserialize_fireteam_party_current_activity( +2281 payload["currentActivity"] +2282 ), +2283 settings=self._deserialize_fireteam_party_settings(payload["joinability"]), +2284 last_destination_hash=last_destination_hash, +2285 tracking=payload["tracking"], +2286 ) +2287 +2288 def _deserialize_fireteam_party_member( +2289 self, payload: typedefs.JSONObject +2290 ) -> fireteams.FireteamPartyMember: +2291 +2292 status = fireteams.FireteamPartyMemberState(payload["status"]) +2293 displayname: undefined.UndefinedOr[str] = undefined.Undefined +2294 if raw_name := payload.get("displayName"): +2295 displayname = raw_name +2296 +2297 return fireteams.FireteamPartyMember( +2298 membership_id=int(payload["membershipId"]), +2299 emblem_hash=int(payload["emblemHash"]), +2300 status=status, +2301 display_name=displayname, +2302 ) +2303 +2304 def _deserialize_fireteam_party_current_activity( +2305 self, payload: typedefs.JSONObject +2306 ) -> fireteams.FireteamPartyCurrentActivity: +2307 start_date: typing.Optional[datetime.datetime] = None +2308 if raw_start_date := payload.get("startTime"): +2309 start_date = time.clean_date(raw_start_date) +2310 +2311 end_date: typing.Optional[datetime.datetime] = None +2312 if raw_end_date := payload.get("endTime"): +2313 end_date = time.clean_date(raw_end_date) +2314 return fireteams.FireteamPartyCurrentActivity( +2315 start_time=start_date, +2316 end_time=end_date, +2317 score=float(payload["score"]), +2318 highest_opposing_score=float(payload["highestOpposingFactionScore"]), +2319 opponenst_count=int(payload["numberOfOpponents"]), +2320 player_count=int(payload["numberOfPlayers"]), +2321 ) +2322 +2323 def _deserialize_fireteam_party_settings( +2324 self, payload: typedefs.JSONObject +2325 ) -> fireteams.FireteamPartySettings: +2326 closed_reasons = enums.ClosedReasons(payload["closedReasons"]) +2327 return fireteams.FireteamPartySettings( +2328 open_slots=int(payload["openSlots"]), +2329 privacy_setting=enums.PrivacySetting(int(payload["privacySetting"])), +2330 closed_reasons=closed_reasons, +2331 ) +2332 +2333 def deserialize_seasonal_artifact( +2334 self, payload: typedefs.JSONObject +2335 ) -> season.Artifact: +2336 if raw_artifact := payload.get("seasonalArtifact"): +2337 if points := raw_artifact.get("pointProgression"): +2338 points_prog = progressions.Progression( +2339 hash=points["progressionHash"], +2340 level=points["level"], +2341 cap=points["levelCap"], +2342 daily_limit=points["dailyLimit"], +2343 weekly_limit=points["weeklyLimit"], +2344 current_progress=points["currentProgress"], +2345 daily_progress=points["dailyProgress"], +2346 needed=points["progressToNextLevel"], +2347 next_level=points["nextLevelAt"], +2348 ) +2349 +2350 if bonus := raw_artifact.get("powerBonusProgression"): +2351 power_bonus_prog = progressions.Progression( +2352 hash=bonus["progressionHash"], +2353 level=bonus["level"], +2354 cap=bonus["levelCap"], +2355 daily_limit=bonus["dailyLimit"], +2356 weekly_limit=bonus["weeklyLimit"], +2357 current_progress=bonus["currentProgress"], +2358 daily_progress=bonus["dailyProgress"], +2359 needed=bonus["progressToNextLevel"], +2360 next_level=bonus["nextLevelAt"], +2361 ) +2362 artifact = season.Artifact( +2363 net=self._net, +2364 hash=raw_artifact["artifactHash"], +2365 power_bonus=raw_artifact["powerBonus"], +2366 acquired_points=raw_artifact["pointsAcquired"], +2367 bonus=power_bonus_prog, +2368 points=points_prog, +2369 ) +2370 return artifact +2371 +2372 def deserialize_profile_progression( +2373 self, payload: typedefs.JSONObject +2374 ) -> profile.ProfileProgression: +2375 return profile.ProfileProgression( +2376 artifact=self.deserialize_seasonal_artifact(payload["data"]), +2377 checklist={ +2378 int(check_id): checklists +2379 for check_id, checklists in payload["data"]["checklists"].items() +2380 }, +2381 ) +2382 +2383 def deserialize_instanced_item( +2384 self, payload: typedefs.JSONObject +2385 ) -> items.ItemInstance: +2386 damage_type_hash: typing.Optional[int] = None +2387 if raw_damagetype_hash := payload.get("damageTypeHash"): +2388 damage_type_hash = int(raw_damagetype_hash) +2389 +2390 required_hashes: typing.Optional[collections.Collection[int]] = None +2391 if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"): +2392 required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes] +2393 +2394 breaker_type: typing.Optional[items.ItemBreakerType] = None +2395 if raw_break_type := payload.get("breakerType"): +2396 breaker_type = items.ItemBreakerType(int(raw_break_type)) +2397 +2398 breaker_type_hash: typing.Optional[int] = None +2399 if raw_break_type_hash := payload.get("breakerTypeHash"): +2400 breaker_type_hash = int(raw_break_type_hash) +2401 +2402 energy: typing.Optional[items.ItemEnergy] = None +2403 if raw_energy := payload.get("energy"): +2404 energy = self.deserialize_item_energy(raw_energy) +2405 +2406 primary_stats = None +2407 if raw_primary_stats := payload.get("primaryStat"): +2408 primary_stats = self.deserialize_item_stats_view(raw_primary_stats) +2409 +2410 return items.ItemInstance( +2411 damage_type=enums.DamageType(int(payload["damageType"])), +2412 damage_type_hash=damage_type_hash, +2413 primary_stat=primary_stats, +2414 item_level=int(payload["itemLevel"]), +2415 quality=int(payload["quality"]), +2416 is_equipped=payload["isEquipped"], +2417 can_equip=payload["canEquip"], +2418 equip_required_level=int(payload["equipRequiredLevel"]), +2419 required_equip_unlock_hashes=required_hashes, +2420 cant_equip_reason=int(payload["cannotEquipReason"]), +2421 breaker_type=breaker_type, +2422 breaker_type_hash=breaker_type_hash, +2423 energy=energy, +2424 ) +2425 +2426 def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy: +2427 energy_hash: typing.Optional[int] = None +2428 if raw_energy_hash := payload.get("energyTypeHash"): +2429 energy_hash = int(raw_energy_hash) +2430 +2431 return items.ItemEnergy( +2432 hash=energy_hash, +2433 type=items.ItemEnergyType(int(payload["energyType"])), +2434 capacity=int(payload["energyCapacity"]), +2435 used_energy=int(payload["energyUsed"]), +2436 unused_energy=int(payload["energyUnused"]), +2437 ) +2438 +2439 def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk: +2440 perk_hash: typing.Optional[int] = None +2441 if raw_perk_hash := payload.get("perkHash"): +2442 perk_hash = int(raw_perk_hash) +2443 +2444 return items.ItemPerk( +2445 hash=perk_hash, +2446 icon=assets.Image(payload["iconPath"]), +2447 is_active=payload["isActive"], +2448 is_visible=payload["visible"], +2449 ) +2450 +2451 def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket: +2452 plug_hash: typing.Optional[int] = None +2453 if raw_plug_hash := payload.get("plugHash"): +2454 plug_hash = int(raw_plug_hash) +2455 +2456 enable_fail_indexes: typing.Optional[list[int]] = None +2457 if raw_indexes := payload.get("enableFailIndexes"): +2458 enable_fail_indexes = [int(index) for index in raw_indexes] +2459 +2460 return items.ItemSocket( +2461 plug_hash=plug_hash, +2462 is_enabled=payload["isEnabled"], +2463 enable_fail_indexes=enable_fail_indexes, +2464 is_visible=payload.get("visible"), +2465 ) +2466 +2467 def deserialize_item_stats_view( +2468 self, payload: typedefs.JSONObject +2469 ) -> items.ItemStatsView: +2470 return items.ItemStatsView( +2471 stat_hash=payload.get("statHash"), value=payload.get("value") +2472 ) +2473 +2474 def deserialize_plug_item_state( +2475 self, payload: typedefs.JSONObject +2476 ) -> items.PlugItemState: +2477 item_hash: typing.Optional[int] = None +2478 if raw_item_hash := payload.get("plugItemHash"): +2479 item_hash = int(raw_item_hash) +2480 +2481 insert_fail_indexes: typedefs.NoneOr[list[int]] = None +2482 if raw_fail_indexes := payload.get("insertFailIndexes"): +2483 insert_fail_indexes = [int(k) for k in raw_fail_indexes] +2484 +2485 enable_fail_indexes: typedefs.NoneOr[list[int]] = None +2486 if raw_enabled_indexes := payload.get("enableFailIndexes"): +2487 enable_fail_indexes = [int(k) for k in raw_enabled_indexes] +2488 +2489 return items.PlugItemState( +2490 item_hash=item_hash, +2491 insert_fail_indexes=insert_fail_indexes, +2492 enable_fail_indexes=enable_fail_indexes, +2493 is_enabled=payload["enabled"], +2494 can_insert=payload["canInsert"], +2495 )

          @@ -2930,2312 +2921,2306 @@

          194 for creds in payload 195 ] 196 - 197 @staticmethod - 198 def set_themese_attrs( - 199 payload: typedefs.JSONArray, / - 200 ) -> typing.Collection[user.UserThemes]: - 201 return [ - 202 user.UserThemes( - 203 id=int(entry["userThemeId"]), - 204 name=entry["userThemeName"] - 205 if "userThemeName" in entry - 206 else undefined.Undefined, - 207 description=entry["userThemeDescription"] - 208 if "userThemeDescription" in entry - 209 else undefined.Undefined, - 210 ) - 211 for entry in payload - 212 ] - 213 - 214 def deserialize_user_themes( - 215 self, payload: typedefs.JSONArray - 216 ) -> collections.Sequence[user.UserThemes]: - 217 return list(self.set_themese_attrs(payload)) - 218 - 219 def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan: - 220 - 221 # This is kinda redundant - 222 data = payload - 223 - 224 # This is always outside the details. - 225 current_user_map: typing.Optional[ - 226 collections.Mapping[str, clans.ClanMember] - 227 ] = None - 228 if raw_current_user_map := payload.get("currentUserMemberMap"): - 229 current_user_map = { - 230 membership_type: self.deserialize_clan_member(membership) - 231 for membership_type, membership in raw_current_user_map.items() - 232 } - 233 - 234 try: - 235 data = payload["detail"] - 236 except KeyError: - 237 pass - 238 - 239 id = data["groupId"] - 240 name = data["name"] - 241 created_at = data["creationDate"] - 242 member_count = data["memberCount"] - 243 about = data["about"] - 244 motto = data["motto"] - 245 is_public = data["isPublic"] - 246 banner = assets.Image(str(data["bannerPath"])) - 247 avatar = assets.Image(str(data["avatarPath"])) - 248 tags = data["tags"] - 249 type = data["groupType"] - 250 - 251 features = data["features"] - 252 features_obj = clans.ClanFeatures( - 253 max_members=features["maximumMembers"], - 254 max_membership_types=features["maximumMembershipsOfGroupType"], - 255 capabilities=features["capabilities"], - 256 membership_types=features["membershipTypes"], - 257 invite_permissions=features["invitePermissionOverride"], - 258 update_banner_permissions=features["updateBannerPermissionOverride"], - 259 update_culture_permissions=features["updateCulturePermissionOverride"], - 260 join_level=features["joinLevel"], - 261 ) + 197 def deserialize_user_themes( + 198 self, payload: typedefs.JSONArray + 199 ) -> collections.Sequence[user.UserThemes]: + 200 return [ + 201 user.UserThemes( + 202 id=int(entry["userThemeId"]), + 203 name=entry["userThemeName"] + 204 if "userThemeName" in entry + 205 else undefined.Undefined, + 206 description=entry["userThemeDescription"] + 207 if "userThemeDescription" in entry + 208 else undefined.Undefined, + 209 ) + 210 for entry in payload + 211 ] + 212 + 213 def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan: + 214 + 215 # This is kinda redundant + 216 data = payload + 217 + 218 # This is always outside the details. + 219 current_user_map: typing.Optional[ + 220 collections.Mapping[str, clans.ClanMember] + 221 ] = None + 222 if raw_current_user_map := payload.get("currentUserMemberMap"): + 223 current_user_map = { + 224 membership_type: self.deserialize_clan_member(membership) + 225 for membership_type, membership in raw_current_user_map.items() + 226 } + 227 + 228 try: + 229 data = payload["detail"] + 230 except KeyError: + 231 pass + 232 + 233 id = data["groupId"] + 234 name = data["name"] + 235 created_at = data["creationDate"] + 236 member_count = data["memberCount"] + 237 about = data["about"] + 238 motto = data["motto"] + 239 is_public = data["isPublic"] + 240 banner = assets.Image(str(data["bannerPath"])) + 241 avatar = assets.Image(str(data["avatarPath"])) + 242 tags = data["tags"] + 243 type = data["groupType"] + 244 + 245 features = data["features"] + 246 features_obj = clans.ClanFeatures( + 247 max_members=features["maximumMembers"], + 248 max_membership_types=features["maximumMembershipsOfGroupType"], + 249 capabilities=features["capabilities"], + 250 membership_types=features["membershipTypes"], + 251 invite_permissions=features["invitePermissionOverride"], + 252 update_banner_permissions=features["updateBannerPermissionOverride"], + 253 update_culture_permissions=features["updateCulturePermissionOverride"], + 254 join_level=features["joinLevel"], + 255 ) + 256 + 257 information: typedefs.JSONObject = data["clanInfo"] + 258 progression: collections.Mapping[int, progressions.Progression] = { + 259 int(prog_hash): self.deserialize_progressions(prog) + 260 for prog_hash, prog in information["d2ClanProgressions"].items() + 261 } 262 - 263 information: typedefs.JSONObject = data["clanInfo"] - 264 progression: collections.Mapping[int, progressions.Progression] = { - 265 int(prog_hash): self.deserialize_progressions(prog) - 266 for prog_hash, prog in information["d2ClanProgressions"].items() - 267 } - 268 - 269 founder: typedefs.NoneOr[clans.ClanMember] = None - 270 if raw_founder := payload.get("founder"): - 271 founder = self.deserialize_clan_member(raw_founder) - 272 - 273 return clans.Clan( - 274 net=self._net, - 275 id=int(id), - 276 name=name, - 277 type=enums.GroupType(type), - 278 created_at=time.clean_date(created_at), - 279 member_count=member_count, - 280 motto=motto, - 281 about=about, - 282 is_public=is_public, - 283 banner=banner, - 284 avatar=avatar, - 285 tags=tags, - 286 features=features_obj, - 287 owner=founder, - 288 progressions=progression, - 289 call_sign=information["clanCallsign"], - 290 banner_data=information["clanBannerData"], - 291 chat_security=data["chatSecurity"], - 292 conversation_id=int(data["conversationId"]), - 293 allow_chat=data["allowChat"], - 294 theme=data["theme"], - 295 current_user_membership=current_user_map, - 296 ) - 297 - 298 def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember: - 299 destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"]) - 300 return clans.ClanMember( - 301 net=self._net, - 302 last_seen_name=destiny_user.last_seen_name, - 303 id=destiny_user.id, - 304 name=destiny_user.name, - 305 icon=destiny_user.icon, - 306 last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])), - 307 group_id=int(data["groupId"]), - 308 joined_at=time.clean_date(data["joinDate"]), - 309 types=destiny_user.types, - 310 is_public=destiny_user.is_public, - 311 type=destiny_user.type, - 312 code=destiny_user.code, - 313 is_online=data["isOnline"], - 314 crossave_override=destiny_user.crossave_override, - 315 bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"]) - 316 if "bungieNetUserInfo" in data - 317 else None, - 318 member_type=enums.ClanMemberType(int(data["memberType"])), - 319 ) - 320 - 321 def deserialize_clan_members( - 322 self, data: typedefs.JSONObject, / - 323 ) -> iterators.FlatIterator[clans.ClanMember]: - 324 return iterators.FlatIterator( - 325 [self.deserialize_clan_member(member) for member in data["results"]] - 326 ) - 327 - 328 def deserialize_group_member( - 329 self, payload: typedefs.JSONObject - 330 ) -> clans.GroupMember: - 331 member = payload["member"] - 332 return clans.GroupMember( - 333 net=self._net, - 334 join_date=time.clean_date(member["joinDate"]), - 335 group_id=int(member["groupId"]), - 336 member_type=enums.ClanMemberType(member["memberType"]), - 337 is_online=member["isOnline"], - 338 last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])), - 339 inactive_memberships=payload.get("areAllMembershipsInactive", None), - 340 member=self.deserialize_destiny_membership(member["destinyUserInfo"]), - 341 group=self.deserialize_clan(payload["group"]), - 342 ) - 343 - 344 def _deserialize_clan_conversation( - 345 self, payload: typedefs.JSONObject - 346 ) -> clans.ClanConversation: - 347 return clans.ClanConversation( - 348 net=self._net, - 349 id=int(payload["conversationId"]), - 350 group_id=int(payload["groupId"]), - 351 name=( - 352 payload["chatName"] - 353 if not typedefs.is_unknown(payload["chatName"]) - 354 else undefined.Undefined - 355 ), - 356 chat_enabled=payload["chatEnabled"], - 357 security=payload["chatSecurity"], - 358 ) - 359 - 360 def deserialize_clan_conversations( - 361 self, payload: typedefs.JSONArray - 362 ) -> collections.Sequence[clans.ClanConversation]: - 363 return [self._deserialize_clan_conversation(conv) for conv in payload] - 364 - 365 def deserialize_app_owner( - 366 self, payload: typedefs.JSONObject - 367 ) -> application.ApplicationOwner: - 368 return application.ApplicationOwner( - 369 net=self._net, - 370 name=payload.get("bungieGlobalDisplayName", undefined.Undefined), - 371 id=int(payload["membershipId"]), - 372 type=enums.MembershipType(payload["membershipType"]), - 373 icon=assets.Image(str(payload["iconPath"])), - 374 is_public=payload["isPublic"], - 375 code=payload.get("bungieGlobalDisplayNameCode", None), - 376 ) - 377 - 378 def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application: - 379 return application.Application( - 380 id=int(payload["applicationId"]), - 381 name=payload["name"], - 382 link=payload["link"], - 383 status=payload["status"], - 384 redirect_url=payload.get("redirectUrl", None), - 385 created_at=time.clean_date(str(payload["creationDate"])), - 386 published_at=time.clean_date(str(payload["firstPublished"])), - 387 owner=self.deserialize_app_owner(payload["team"][0]["user"]), # type: ignore - 388 scope=payload.get("scope", undefined.Undefined), - 389 ) - 390 - 391 def _set_character_attrs(self, payload: typedefs.JSONObject) -> character.Character: - 392 total_time = time.format_played(int(payload["minutesPlayedTotal"]), suffix=True) - 393 return character.Character( - 394 net=self._net, - 395 id=int(payload["characterId"]), - 396 gender=enums.Gender(payload["genderType"]), - 397 race=enums.Race(payload["raceType"]), - 398 class_type=enums.Class(payload["classType"]), - 399 emblem=assets.Image(str(payload["emblemBackgroundPath"])), - 400 emblem_icon=assets.Image(str(payload["emblemPath"])), - 401 emblem_hash=int(payload["emblemHash"]), - 402 last_played=time.clean_date(payload["dateLastPlayed"]), - 403 total_played_time=total_time, - 404 member_id=int(payload["membershipId"]), - 405 member_type=enums.MembershipType(payload["membershipType"]), - 406 level=payload["baseCharacterLevel"], - 407 title_hash=payload.get("titleRecordHash", None), - 408 light=payload["light"], - 409 stats={enums.Stat(int(k)): v for k, v in payload["stats"].items()}, - 410 ) + 263 founder: typedefs.NoneOr[clans.ClanMember] = None + 264 if raw_founder := payload.get("founder"): + 265 founder = self.deserialize_clan_member(raw_founder) + 266 + 267 return clans.Clan( + 268 net=self._net, + 269 id=int(id), + 270 name=name, + 271 type=enums.GroupType(type), + 272 created_at=time.clean_date(created_at), + 273 member_count=member_count, + 274 motto=motto, + 275 about=about, + 276 is_public=is_public, + 277 banner=banner, + 278 avatar=avatar, + 279 tags=tags, + 280 features=features_obj, + 281 owner=founder, + 282 progressions=progression, + 283 call_sign=information["clanCallsign"], + 284 banner_data=information["clanBannerData"], + 285 chat_security=data["chatSecurity"], + 286 conversation_id=int(data["conversationId"]), + 287 allow_chat=data["allowChat"], + 288 theme=data["theme"], + 289 current_user_membership=current_user_map, + 290 ) + 291 + 292 def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember: + 293 destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"]) + 294 return clans.ClanMember( + 295 net=self._net, + 296 last_seen_name=destiny_user.last_seen_name, + 297 id=destiny_user.id, + 298 name=destiny_user.name, + 299 icon=destiny_user.icon, + 300 last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])), + 301 group_id=int(data["groupId"]), + 302 joined_at=time.clean_date(data["joinDate"]), + 303 types=destiny_user.types, + 304 is_public=destiny_user.is_public, + 305 type=destiny_user.type, + 306 code=destiny_user.code, + 307 is_online=data["isOnline"], + 308 crossave_override=destiny_user.crossave_override, + 309 bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"]) + 310 if "bungieNetUserInfo" in data + 311 else None, + 312 member_type=enums.ClanMemberType(int(data["memberType"])), + 313 ) + 314 + 315 def deserialize_clan_members( + 316 self, data: typedefs.JSONObject, / + 317 ) -> iterators.Iterator[clans.ClanMember]: + 318 return iterators.Iterator( + 319 [self.deserialize_clan_member(member) for member in data["results"]] + 320 ) + 321 + 322 def deserialize_group_member( + 323 self, payload: typedefs.JSONObject + 324 ) -> clans.GroupMember: + 325 member = payload["member"] + 326 return clans.GroupMember( + 327 net=self._net, + 328 join_date=time.clean_date(member["joinDate"]), + 329 group_id=int(member["groupId"]), + 330 member_type=enums.ClanMemberType(member["memberType"]), + 331 is_online=member["isOnline"], + 332 last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])), + 333 inactive_memberships=payload.get("areAllMembershipsInactive", None), + 334 member=self.deserialize_destiny_membership(member["destinyUserInfo"]), + 335 group=self.deserialize_clan(payload["group"]), + 336 ) + 337 + 338 def _deserialize_clan_conversation( + 339 self, payload: typedefs.JSONObject + 340 ) -> clans.ClanConversation: + 341 return clans.ClanConversation( + 342 net=self._net, + 343 id=int(payload["conversationId"]), + 344 group_id=int(payload["groupId"]), + 345 name=( + 346 payload["chatName"] + 347 if not typedefs.is_unknown(payload["chatName"]) + 348 else undefined.Undefined + 349 ), + 350 chat_enabled=payload["chatEnabled"], + 351 security=payload["chatSecurity"], + 352 ) + 353 + 354 def deserialize_clan_conversations( + 355 self, payload: typedefs.JSONArray + 356 ) -> collections.Sequence[clans.ClanConversation]: + 357 return [self._deserialize_clan_conversation(conv) for conv in payload] + 358 + 359 def deserialize_app_owner( + 360 self, payload: typedefs.JSONObject + 361 ) -> application.ApplicationOwner: + 362 return application.ApplicationOwner( + 363 net=self._net, + 364 name=payload.get("bungieGlobalDisplayName", undefined.Undefined), + 365 id=int(payload["membershipId"]), + 366 type=enums.MembershipType(payload["membershipType"]), + 367 icon=assets.Image(str(payload["iconPath"])), + 368 is_public=payload["isPublic"], + 369 code=payload.get("bungieGlobalDisplayNameCode", None), + 370 ) + 371 + 372 def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application: + 373 return application.Application( + 374 id=int(payload["applicationId"]), + 375 name=payload["name"], + 376 link=payload["link"], + 377 status=payload["status"], + 378 redirect_url=payload.get("redirectUrl", None), + 379 created_at=time.clean_date(str(payload["creationDate"])), + 380 published_at=time.clean_date(str(payload["firstPublished"])), + 381 owner=self.deserialize_app_owner(payload["team"][0]["user"]), # type: ignore + 382 scope=payload.get("scope", undefined.Undefined), + 383 ) + 384 + 385 def _set_character_attrs(self, payload: typedefs.JSONObject) -> character.Character: + 386 total_time = time.format_played(int(payload["minutesPlayedTotal"]), suffix=True) + 387 return character.Character( + 388 net=self._net, + 389 id=int(payload["characterId"]), + 390 gender=enums.Gender(payload["genderType"]), + 391 race=enums.Race(payload["raceType"]), + 392 class_type=enums.Class(payload["classType"]), + 393 emblem=assets.Image(str(payload["emblemBackgroundPath"])), + 394 emblem_icon=assets.Image(str(payload["emblemPath"])), + 395 emblem_hash=int(payload["emblemHash"]), + 396 last_played=time.clean_date(payload["dateLastPlayed"]), + 397 total_played_time=total_time, + 398 member_id=int(payload["membershipId"]), + 399 member_type=enums.MembershipType(payload["membershipType"]), + 400 level=payload["baseCharacterLevel"], + 401 title_hash=payload.get("titleRecordHash", None), + 402 light=payload["light"], + 403 stats={enums.Stat(int(k)): v for k, v in payload["stats"].items()}, + 404 ) + 405 + 406 def deserialize_profile( + 407 self, payload: typedefs.JSONObject, / + 408 ) -> typing.Optional[profile.Profile]: + 409 if (raw_profile := payload.get("data")) is None: + 410 return None 411 - 412 def deserialize_profile( - 413 self, payload: typedefs.JSONObject, / - 414 ) -> typing.Optional[profile.Profile]: - 415 if (raw_profile := payload.get("data")) is None: - 416 return None - 417 - 418 payload = raw_profile - 419 id = int(payload["userInfo"]["membershipId"]) - 420 name = payload["userInfo"]["displayName"] - 421 is_public = payload["userInfo"]["isPublic"] - 422 type = enums.MembershipType(payload["userInfo"]["membershipType"]) - 423 last_played = time.clean_date(str(payload["dateLastPlayed"])) - 424 character_ids = [int(cid) for cid in payload["characterIds"]] - 425 power_cap = payload["currentSeasonRewardPowerCap"] - 426 - 427 return profile.Profile( - 428 id=int(id), - 429 name=name, - 430 is_public=is_public, - 431 type=type, - 432 last_played=last_played, - 433 character_ids=character_ids, - 434 power_cap=power_cap, - 435 net=self._net, - 436 ) - 437 - 438 def deserialize_profile_item( - 439 self, payload: typedefs.JSONObject - 440 ) -> profile.ProfileItemImpl: - 441 - 442 instance_id: typing.Optional[int] = None - 443 if raw_instance_id := payload.get("itemInstanceId"): - 444 instance_id = int(raw_instance_id) + 412 payload = raw_profile + 413 id = int(payload["userInfo"]["membershipId"]) + 414 name = payload["userInfo"]["displayName"] + 415 is_public = payload["userInfo"]["isPublic"] + 416 type = enums.MembershipType(payload["userInfo"]["membershipType"]) + 417 last_played = time.clean_date(str(payload["dateLastPlayed"])) + 418 character_ids = [int(cid) for cid in payload["characterIds"]] + 419 power_cap = payload["currentSeasonRewardPowerCap"] + 420 + 421 return profile.Profile( + 422 id=int(id), + 423 name=name, + 424 is_public=is_public, + 425 type=type, + 426 last_played=last_played, + 427 character_ids=character_ids, + 428 power_cap=power_cap, + 429 net=self._net, + 430 ) + 431 + 432 def deserialize_profile_item( + 433 self, payload: typedefs.JSONObject + 434 ) -> profile.ProfileItemImpl: + 435 + 436 instance_id: typing.Optional[int] = None + 437 if raw_instance_id := payload.get("itemInstanceId"): + 438 instance_id = int(raw_instance_id) + 439 + 440 version_number: typing.Optional[int] = None + 441 if raw_version := payload.get("versionNumber"): + 442 version_number = int(raw_version) + 443 + 444 transfer_status = enums.TransferStatus(payload["transferStatus"]) 445 - 446 version_number: typing.Optional[int] = None - 447 if raw_version := payload.get("versionNumber"): - 448 version_number = int(raw_version) - 449 - 450 transfer_status = enums.TransferStatus(payload["transferStatus"]) - 451 - 452 return profile.ProfileItemImpl( - 453 net=self._net, - 454 hash=payload["itemHash"], - 455 quantity=payload["quantity"], - 456 bind_status=enums.ItemBindStatus(payload["bindStatus"]), - 457 location=enums.ItemLocation(payload["location"]), - 458 bucket=payload["bucketHash"], - 459 transfer_status=transfer_status, - 460 lockable=payload["lockable"], - 461 state=enums.ItemState(payload["state"]), - 462 dismantel_permissions=payload["dismantlePermission"], - 463 is_wrapper=payload["isWrapper"], - 464 instance_id=instance_id, - 465 version_number=version_number, - 466 ornament_id=payload.get("overrideStyleItemHash"), - 467 ) - 468 - 469 def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective: - 470 return records.Objective( - 471 net=self._net, - 472 hash=payload["objectiveHash"], - 473 visible=payload["visible"], - 474 complete=payload["complete"], - 475 completion_value=payload["completionValue"], - 476 progress=payload.get("progress"), - 477 destination_hash=payload.get("destinationHash"), - 478 activity_hash=payload.get("activityHash"), - 479 ) - 480 - 481 def deserialize_records( - 482 self, - 483 payload: typedefs.JSONObject, - 484 scores: typing.Optional[records.RecordScores] = None, - 485 **nodes: int, - 486 ) -> records.Record: - 487 objectives: typing.Optional[list[records.Objective]] = None - 488 interval_objectives: typing.Optional[list[records.Objective]] = None - 489 record_state: typedefs.IntAnd[records.RecordState] - 490 - 491 record_state = records.RecordState(payload["state"]) - 492 - 493 if raw_objs := payload.get("objectives"): - 494 objectives = [self.deserialize_objectives(obj) for obj in raw_objs] - 495 - 496 if raw_interval_objs := payload.get("intervalObjectives"): - 497 interval_objectives = [ - 498 self.deserialize_objectives(obj) for obj in raw_interval_objs - 499 ] - 500 - 501 return records.Record( - 502 scores=scores, - 503 categories_node_hash=nodes.get("categories_hash", undefined.Undefined), - 504 seals_node_hash=nodes.get("seals_hash", undefined.Undefined), - 505 state=record_state, - 506 objectives=objectives, - 507 interval_objectives=interval_objectives, - 508 redeemed_count=payload.get("intervalsRedeemedCount", 0), - 509 completion_times=payload.get("completedCount", None), - 510 reward_visibility=payload.get("rewardVisibilty", None), - 511 ) - 512 - 513 def deserialize_character_records( - 514 self, - 515 payload: typedefs.JSONObject, - 516 scores: typing.Optional[records.RecordScores] = None, - 517 record_hashes: typing.Optional[list[int]] = None, - 518 ) -> records.CharacterRecord: - 519 - 520 record = self.deserialize_records(payload, scores) - 521 return records.CharacterRecord( - 522 scores=scores, - 523 categories_node_hash=record.categories_node_hash, - 524 seals_node_hash=record.seals_node_hash, - 525 state=record.state, - 526 objectives=record.objectives, - 527 interval_objectives=record.interval_objectives, - 528 redeemed_count=payload.get("intervalsRedeemedCount", 0), - 529 completion_times=payload.get("completedCount"), - 530 reward_visibility=payload.get("rewardVisibilty"), - 531 record_hashes=record_hashes or [], - 532 ) - 533 - 534 def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye: - 535 return character.Dye( - 536 channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"] - 537 ) - 538 - 539 def deserialize_character_customization( - 540 self, payload: typedefs.JSONObject - 541 ) -> character.CustomizationOptions: - 542 return character.CustomizationOptions( - 543 personality=payload["personality"], - 544 face=payload["face"], - 545 skin_color=payload["skinColor"], - 546 lip_color=payload["lipColor"], - 547 eye_color=payload["eyeColor"], - 548 hair_colors=payload.get("hairColors", []), - 549 feature_colors=payload.get("featureColors", []), - 550 decal_color=payload["decalColor"], - 551 wear_helmet=payload["wearHelmet"], - 552 hair_index=payload["hairIndex"], - 553 feature_index=payload["featureIndex"], - 554 decal_index=payload["decalIndex"], - 555 ) - 556 - 557 def deserialize_character_minimal_equipments( - 558 self, payload: typedefs.JSONObject - 559 ) -> character.MinimalEquipments: - 560 dyes = None - 561 if raw_dyes := payload.get("dyes"): - 562 if raw_dyes: - 563 dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes] - 564 return character.MinimalEquipments( - 565 net=self._net, item_hash=payload["itemHash"], dyes=dyes - 566 ) - 567 - 568 def deserialize_character_render_data( - 569 self, payload: typedefs.JSONObject, / - 570 ) -> character.RenderedData: - 571 return character.RenderedData( - 572 net=self._net, - 573 customization=self.deserialize_character_customization( - 574 payload["customization"] - 575 ), - 576 custom_dyes=[ - 577 self.deserialize_character_dye(dye) - 578 for dye in payload["customDyes"] - 579 if dye - 580 ], - 581 equipment=[ - 582 self.deserialize_character_minimal_equipments(equipment) - 583 for equipment in payload["peerView"]["equipment"] - 584 ], - 585 ) - 586 - 587 def deserialize_available_activity( - 588 self, payload: typedefs.JSONObject - 589 ) -> activity.AvailableActivity: - 590 return activity.AvailableActivity( - 591 hash=payload["activityHash"], - 592 is_new=payload["isNew"], - 593 is_completed=payload["isCompleted"], - 594 is_visible=payload["isVisible"], - 595 display_level=payload.get("displayLevel"), - 596 recommended_light=payload.get("recommendedLight"), - 597 difficulty=activity.Difficulty(payload["difficultyTier"]), - 598 can_join=payload["canJoin"], - 599 can_lead=payload["canLead"], - 600 ) - 601 - 602 def deserialize_character_activity( - 603 self, payload: typedefs.JSONObject - 604 ) -> activity.CharacterActivity: - 605 current_mode: typing.Optional[enums.GameMode] = None - 606 if raw_current_mode := payload.get("currentActivityModeType"): - 607 current_mode = enums.GameMode(raw_current_mode) - 608 - 609 current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None - 610 if raw_current_modes := payload.get("currentActivityModeTypes"): - 611 current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes] - 612 - 613 return activity.CharacterActivity( - 614 date_started=time.clean_date(payload["dateActivityStarted"]), - 615 current_hash=payload["currentActivityHash"], - 616 current_mode_hash=payload["currentActivityModeHash"], - 617 current_mode=current_mode, - 618 current_mode_hashes=payload.get("currentActivityModeHashes"), - 619 current_mode_types=current_mode_types, - 620 current_playlist_hash=payload.get("currentPlaylistActivityHash"), - 621 last_story_hash=payload["lastCompletedStoryHash"], - 622 available_activities=[ - 623 self.deserialize_available_activity(activity_) - 624 for activity_ in payload["availableActivities"] - 625 ], - 626 ) - 627 - 628 def deserialize_profile_items( - 629 self, payload: typedefs.JSONObject, / - 630 ) -> list[profile.ProfileItemImpl]: - 631 return [self.deserialize_profile_item(item) for item in payload["items"]] - 632 - 633 def _deserialize_node(self, payload: typedefs.JSONObject) -> records.Node: - 634 return records.Node( - 635 state=int(payload["state"]), - 636 objective=self.deserialize_objectives(payload["objective"]) - 637 if "objective" in payload - 638 else None, - 639 progress_value=int(payload["progressValue"]), - 640 completion_value=int(payload["completionValue"]), - 641 record_category_score=int(payload["recordCategoryScore"]) - 642 if "recordCategoryScore" in payload - 643 else None, - 644 ) - 645 - 646 @staticmethod - 647 def _deserialize_collectible(payload: typedefs.JSONObject) -> items.Collectible: - 648 recent_collectibles: typing.Optional[collections.Collection[int]] = None - 649 if raw_recent_collectibles := payload.get("recentCollectibleHashes"): - 650 recent_collectibles = [ - 651 int(item_hash) for item_hash in raw_recent_collectibles - 652 ] - 653 - 654 collectibles: dict[int, int] = {} - 655 for item_hash, mapping in payload["collectibles"].items(): - 656 collectibles[int(item_hash)] = int(mapping["state"]) - 657 - 658 return items.Collectible( - 659 recent_collectibles=recent_collectibles, - 660 collectibles=collectibles, - 661 collection_categorie_hash=int(payload["collectionCategoriesRootNodeHash"]), - 662 collection_badges_hash=int(payload["collectionBadgesRootNodeHash"]), - 663 ) - 664 - 665 @staticmethod - 666 def _deserialize_currencies( - 667 payload: typedefs.JSONObject, - 668 ) -> collections.Sequence[items.Currency]: - 669 return [ - 670 items.Currency(hash=int(item_hash), amount=int(amount)) - 671 for item_hash, amount in payload["itemQuantities"].items() - 672 ] - 673 - 674 def deserialize_progressions( - 675 self, payload: typedefs.JSONObject - 676 ) -> progressions.Progression: - 677 return progressions.Progression( - 678 hash=int(payload["progressionHash"]), - 679 level=int(payload["level"]), - 680 cap=int(payload["levelCap"]), - 681 daily_limit=int(payload["dailyLimit"]), - 682 weekly_limit=int(payload["weeklyLimit"]), - 683 current_progress=int(payload["currentProgress"]), - 684 daily_progress=int(payload["dailyProgress"]), - 685 needed=int(payload["progressToNextLevel"]), - 686 next_level=int(payload["nextLevelAt"]), - 687 ) - 688 - 689 def _deserialize_factions( - 690 self, payload: typedefs.JSONObject - 691 ) -> progressions.Factions: - 692 progs = self.deserialize_progressions(payload) - 693 return progressions.Factions( - 694 hash=progs.hash, - 695 level=progs.level, - 696 cap=progs.cap, - 697 daily_limit=progs.daily_limit, - 698 weekly_limit=progs.weekly_limit, - 699 current_progress=progs.current_progress, - 700 daily_progress=progs.daily_progress, - 701 needed=progs.needed, - 702 next_level=progs.next_level, - 703 faction_hash=payload["factionHash"], - 704 faction_vendor_hash=payload["factionVendorIndex"], - 705 ) - 706 - 707 def _deserialize_milestone_available_quest( - 708 self, payload: typedefs.JSONObject - 709 ) -> milestones.MilestoneQuest: - 710 return milestones.MilestoneQuest( - 711 item_hash=payload["questItemHash"], - 712 status=self._deserialize_milestone_quest_status(payload["status"]), - 713 ) - 714 - 715 def _deserialize_milestone_activity( - 716 self, payload: typedefs.JSONObject - 717 ) -> milestones.MilestoneActivity: - 718 - 719 phases: typing.Optional[ - 720 collections.Sequence[milestones.MilestoneActivityPhase] - 721 ] = None - 722 if raw_phases := payload.get("phases"): - 723 phases = [ - 724 milestones.MilestoneActivityPhase( - 725 is_completed=obj["complete"], hash=obj["phaseHash"] - 726 ) - 727 for obj in raw_phases - 728 ] - 729 - 730 return milestones.MilestoneActivity( - 731 hash=payload["activityHash"], - 732 challenges=[ - 733 self.deserialize_objectives(obj["objective"]) - 734 for obj in payload["challenges"] - 735 ], - 736 modifier_hashes=payload.get("modifierHashes"), - 737 boolean_options=payload.get("booleanActivityOptions"), - 738 phases=phases, - 739 ) - 740 - 741 def _deserialize_milestone_quest_status( - 742 self, payload: typedefs.JSONObject - 743 ) -> milestones.QuestStatus: - 744 return milestones.QuestStatus( - 745 net=self._net, - 746 quest_hash=payload["questHash"], - 747 step_hash=payload["stepHash"], - 748 step_objectives=[ - 749 self.deserialize_objectives(objective) - 750 for objective in payload["stepObjectives"] - 751 ], - 752 is_tracked=payload["tracked"], - 753 is_completed=payload["completed"], - 754 started=payload["started"], - 755 item_instance_id=payload["itemInstanceId"], - 756 vendor_hash=payload.get("vendorHash"), - 757 is_redeemed=payload["redeemed"], - 758 ) - 759 - 760 def _deserialize_milestone_rewards( - 761 self, payload: typedefs.JSONObject - 762 ) -> milestones.MilestoneReward: - 763 return milestones.MilestoneReward( - 764 category_hash=payload["rewardCategoryHash"], - 765 entries=[ - 766 milestones.MilestoneRewardEntry( - 767 entry_hash=entry["rewardEntryHash"], - 768 is_earned=entry["earned"], - 769 is_redeemed=entry["redeemed"], - 770 ) - 771 for entry in payload["entries"] - 772 ], - 773 ) - 774 - 775 def deserialize_milestone( - 776 self, payload: typedefs.JSONObject - 777 ) -> milestones.Milestone: - 778 start_date: typing.Optional[datetime.datetime] = None - 779 if raw_start_date := payload.get("startDate"): - 780 start_date = time.clean_date(raw_start_date) - 781 - 782 end_date: typing.Optional[datetime.datetime] = None - 783 if raw_end_date := payload.get("endDate"): - 784 end_date = time.clean_date(raw_end_date) - 785 - 786 rewards: typing.Optional[ - 787 collections.Collection[milestones.MilestoneReward] - 788 ] = None - 789 if raw_rewards := payload.get("rewards"): - 790 rewards = [ - 791 self._deserialize_milestone_rewards(reward) for reward in raw_rewards - 792 ] - 793 - 794 activities: typing.Optional[ - 795 collections.Sequence[milestones.MilestoneActivity] - 796 ] = None - 797 if raw_activities := payload.get("activities"): - 798 activities = [ - 799 self._deserialize_milestone_activity(active) - 800 for active in raw_activities - 801 ] - 802 - 803 quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None - 804 if raw_quests := payload.get("availableQuests"): - 805 quests = [ - 806 self._deserialize_milestone_available_quest(quest) - 807 for quest in raw_quests - 808 ] - 809 - 810 vendors: typing.Optional[ - 811 collections.Sequence[milestones.MilestoneVendor] - 812 ] = None - 813 if raw_vendors := payload.get("vendors"): - 814 vendors = [ - 815 milestones.MilestoneVendor( - 816 vendor_hash=vendor["vendorHash"], - 817 preview_itemhash=vendor.get("previewItemHash"), - 818 ) - 819 for vendor in raw_vendors - 820 ] - 821 - 822 return milestones.Milestone( - 823 hash=payload["milestoneHash"], - 824 start_date=start_date, - 825 end_date=end_date, - 826 order=payload["order"], - 827 rewards=rewards, - 828 available_quests=quests, - 829 activities=activities, - 830 vendors=vendors, - 831 ) - 832 - 833 def _deserialize_artifact_tiers( - 834 self, payload: typedefs.JSONObject - 835 ) -> season.ArtifactTier: - 836 return season.ArtifactTier( - 837 hash=payload["tierHash"], - 838 is_unlocked=payload["isUnlocked"], - 839 points_to_unlock=payload["pointsToUnlock"], - 840 items=[ - 841 season.ArtifactTierItem( - 842 hash=item["itemHash"], is_active=item["isActive"] - 843 ) - 844 for item in payload["items"] - 845 ], - 846 ) - 847 - 848 def deserialize_characters( - 849 self, payload: typedefs.JSONObject - 850 ) -> collections.Mapping[int, character.Character]: - 851 return { - 852 int(char_id): self._set_character_attrs(char) - 853 for char_id, char in payload["data"].items() - 854 } - 855 - 856 def deserialize_character( - 857 self, payload: typedefs.JSONObject - 858 ) -> character.Character: - 859 return self._set_character_attrs(payload) - 860 - 861 def deserialize_character_equipments( - 862 self, payload: typedefs.JSONObject - 863 ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]: - 864 return { - 865 int(char_id): self.deserialize_profile_items(item) - 866 for char_id, item in payload["data"].items() - 867 } - 868 - 869 def deserialize_character_activities( - 870 self, payload: typedefs.JSONObject - 871 ) -> collections.Mapping[int, activity.CharacterActivity]: - 872 return { - 873 int(char_id): self.deserialize_character_activity(data) - 874 for char_id, data in payload["data"].items() - 875 } - 876 - 877 def deserialize_characters_render_data( - 878 self, payload: typedefs.JSONObject - 879 ) -> collections.Mapping[int, character.RenderedData]: - 880 return { - 881 int(char_id): self.deserialize_character_render_data(data) - 882 for char_id, data in payload["data"].items() - 883 } - 884 - 885 def deserialize_character_progressions( - 886 self, payload: typedefs.JSONObject - 887 ) -> character.CharacterProgression: - 888 progressions_ = { - 889 int(prog_id): self.deserialize_progressions(prog) - 890 for prog_id, prog in payload["progressions"].items() - 891 } - 892 - 893 factions = { - 894 int(faction_id): self._deserialize_factions(faction) - 895 for faction_id, faction in payload["factions"].items() - 896 } - 897 - 898 milestones_ = { - 899 int(milestone_hash): self.deserialize_milestone(milestone) - 900 for milestone_hash, milestone in payload["milestones"].items() - 901 } - 902 - 903 uninstanced_item_objectives = { - 904 int(item_hash): [self.deserialize_objectives(ins) for ins in obj] - 905 for item_hash, obj in payload["uninstancedItemObjectives"].items() - 906 } - 907 - 908 artifact = payload["seasonalArtifact"] - 909 seasonal_artifact = season.CharacterScopedArtifact( - 910 hash=artifact["artifactHash"], - 911 points_used=artifact["pointsUsed"], - 912 reset_count=artifact["resetCount"], - 913 tiers=[ - 914 self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"] - 915 ], - 916 ) - 917 checklists = payload["checklists"] - 918 - 919 return character.CharacterProgression( - 920 progressions=progressions_, - 921 factions=factions, - 922 checklists=checklists, - 923 milestones=milestones_, - 924 seasonal_artifact=seasonal_artifact, - 925 uninstanced_item_objectives=uninstanced_item_objectives, - 926 ) - 927 - 928 def deserialize_character_progressions_mapping( - 929 self, payload: typedefs.JSONObject - 930 ) -> collections.Mapping[int, character.CharacterProgression]: - 931 character_progressions: collections.Mapping[ - 932 int, character.CharacterProgression - 933 ] = {} - 934 for char_id, data in payload["data"].items(): - 935 # A little hack to stop mypy complaining about Mapping <-> dict - 936 character_progressions[int(char_id)] = self.deserialize_character_progressions(data) # type: ignore[index] - 937 return character_progressions - 938 - 939 def deserialize_characters_records( - 940 self, - 941 payload: typedefs.JSONObject, - 942 ) -> collections.Mapping[int, records.CharacterRecord]: - 943 - 944 return { - 945 int(rec_id): self.deserialize_character_records( - 946 rec, record_hashes=payload.get("featuredRecordHashes") - 947 ) - 948 for rec_id, rec in payload["records"].items() - 949 } - 950 - 951 def deserialize_profile_records( - 952 self, payload: typedefs.JSONObject - 953 ) -> collections.Mapping[int, records.Record]: - 954 raw_profile_records = payload["data"] - 955 scores = records.RecordScores( - 956 current_score=raw_profile_records["score"], - 957 legacy_score=raw_profile_records["legacyScore"], - 958 lifetime_score=raw_profile_records["lifetimeScore"], - 959 ) - 960 return { - 961 int(record_id): self.deserialize_records( - 962 record, - 963 scores, - 964 categories_hash=raw_profile_records["recordCategoriesRootNodeHash"], - 965 seals_hash=raw_profile_records["recordSealsRootNodeHash"], - 966 ) - 967 for record_id, record in raw_profile_records["records"].items() - 968 } - 969 - 970 def _deserialize_craftable_socket_plug( - 971 self, payload: typedefs.JSONObject - 972 ) -> items.CraftableSocketPlug: - 973 return items.CraftableSocketPlug( - 974 item_hash=int(payload["plugItemHash"]), - 975 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), - 976 ) - 977 - 978 def _deserialize_craftable_socket( - 979 self, payload: typedefs.JSONObject - 980 ) -> items.CraftableSocket: + 446 return profile.ProfileItemImpl( + 447 net=self._net, + 448 hash=payload["itemHash"], + 449 quantity=payload["quantity"], + 450 bind_status=enums.ItemBindStatus(payload["bindStatus"]), + 451 location=enums.ItemLocation(payload["location"]), + 452 bucket=payload["bucketHash"], + 453 transfer_status=transfer_status, + 454 lockable=payload["lockable"], + 455 state=enums.ItemState(payload["state"]), + 456 dismantel_permissions=payload["dismantlePermission"], + 457 is_wrapper=payload["isWrapper"], + 458 instance_id=instance_id, + 459 version_number=version_number, + 460 ornament_id=payload.get("overrideStyleItemHash"), + 461 ) + 462 + 463 def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective: + 464 return records.Objective( + 465 net=self._net, + 466 hash=payload["objectiveHash"], + 467 visible=payload["visible"], + 468 complete=payload["complete"], + 469 completion_value=payload["completionValue"], + 470 progress=payload.get("progress"), + 471 destination_hash=payload.get("destinationHash"), + 472 activity_hash=payload.get("activityHash"), + 473 ) + 474 + 475 def deserialize_records( + 476 self, + 477 payload: typedefs.JSONObject, + 478 scores: typing.Optional[records.RecordScores] = None, + 479 **nodes: int, + 480 ) -> records.Record: + 481 objectives: typing.Optional[list[records.Objective]] = None + 482 interval_objectives: typing.Optional[list[records.Objective]] = None + 483 record_state: typedefs.IntAnd[records.RecordState] + 484 + 485 record_state = records.RecordState(payload["state"]) + 486 + 487 if raw_objs := payload.get("objectives"): + 488 objectives = [self.deserialize_objectives(obj) for obj in raw_objs] + 489 + 490 if raw_interval_objs := payload.get("intervalObjectives"): + 491 interval_objectives = [ + 492 self.deserialize_objectives(obj) for obj in raw_interval_objs + 493 ] + 494 + 495 return records.Record( + 496 scores=scores, + 497 categories_node_hash=nodes.get("categories_hash", undefined.Undefined), + 498 seals_node_hash=nodes.get("seals_hash", undefined.Undefined), + 499 state=record_state, + 500 objectives=objectives, + 501 interval_objectives=interval_objectives, + 502 redeemed_count=payload.get("intervalsRedeemedCount", 0), + 503 completion_times=payload.get("completedCount", None), + 504 reward_visibility=payload.get("rewardVisibilty", None), + 505 ) + 506 + 507 def deserialize_character_records( + 508 self, + 509 payload: typedefs.JSONObject, + 510 scores: typing.Optional[records.RecordScores] = None, + 511 record_hashes: typing.Optional[list[int]] = None, + 512 ) -> records.CharacterRecord: + 513 + 514 record = self.deserialize_records(payload, scores) + 515 return records.CharacterRecord( + 516 scores=scores, + 517 categories_node_hash=record.categories_node_hash, + 518 seals_node_hash=record.seals_node_hash, + 519 state=record.state, + 520 objectives=record.objectives, + 521 interval_objectives=record.interval_objectives, + 522 redeemed_count=payload.get("intervalsRedeemedCount", 0), + 523 completion_times=payload.get("completedCount"), + 524 reward_visibility=payload.get("rewardVisibilty"), + 525 record_hashes=record_hashes or [], + 526 ) + 527 + 528 def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye: + 529 return character.Dye( + 530 channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"] + 531 ) + 532 + 533 def deserialize_character_customization( + 534 self, payload: typedefs.JSONObject + 535 ) -> character.CustomizationOptions: + 536 return character.CustomizationOptions( + 537 personality=payload["personality"], + 538 face=payload["face"], + 539 skin_color=payload["skinColor"], + 540 lip_color=payload["lipColor"], + 541 eye_color=payload["eyeColor"], + 542 hair_colors=payload.get("hairColors", []), + 543 feature_colors=payload.get("featureColors", []), + 544 decal_color=payload["decalColor"], + 545 wear_helmet=payload["wearHelmet"], + 546 hair_index=payload["hairIndex"], + 547 feature_index=payload["featureIndex"], + 548 decal_index=payload["decalIndex"], + 549 ) + 550 + 551 def deserialize_character_minimal_equipments( + 552 self, payload: typedefs.JSONObject + 553 ) -> character.MinimalEquipments: + 554 dyes = None + 555 if raw_dyes := payload.get("dyes"): + 556 if raw_dyes: + 557 dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes] + 558 return character.MinimalEquipments( + 559 net=self._net, item_hash=payload["itemHash"], dyes=dyes + 560 ) + 561 + 562 def deserialize_character_render_data( + 563 self, payload: typedefs.JSONObject, / + 564 ) -> character.RenderedData: + 565 return character.RenderedData( + 566 net=self._net, + 567 customization=self.deserialize_character_customization( + 568 payload["customization"] + 569 ), + 570 custom_dyes=[ + 571 self.deserialize_character_dye(dye) + 572 for dye in payload["customDyes"] + 573 if dye + 574 ], + 575 equipment=[ + 576 self.deserialize_character_minimal_equipments(equipment) + 577 for equipment in payload["peerView"]["equipment"] + 578 ], + 579 ) + 580 + 581 def deserialize_available_activity( + 582 self, payload: typedefs.JSONObject + 583 ) -> activity.AvailableActivity: + 584 return activity.AvailableActivity( + 585 hash=payload["activityHash"], + 586 is_new=payload["isNew"], + 587 is_completed=payload["isCompleted"], + 588 is_visible=payload["isVisible"], + 589 display_level=payload.get("displayLevel"), + 590 recommended_light=payload.get("recommendedLight"), + 591 difficulty=activity.Difficulty(payload["difficultyTier"]), + 592 can_join=payload["canJoin"], + 593 can_lead=payload["canLead"], + 594 ) + 595 + 596 def deserialize_character_activity( + 597 self, payload: typedefs.JSONObject + 598 ) -> activity.CharacterActivity: + 599 current_mode: typing.Optional[enums.GameMode] = None + 600 if raw_current_mode := payload.get("currentActivityModeType"): + 601 current_mode = enums.GameMode(raw_current_mode) + 602 + 603 current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None + 604 if raw_current_modes := payload.get("currentActivityModeTypes"): + 605 current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes] + 606 + 607 return activity.CharacterActivity( + 608 date_started=time.clean_date(payload["dateActivityStarted"]), + 609 current_hash=payload["currentActivityHash"], + 610 current_mode_hash=payload["currentActivityModeHash"], + 611 current_mode=current_mode, + 612 current_mode_hashes=payload.get("currentActivityModeHashes"), + 613 current_mode_types=current_mode_types, + 614 current_playlist_hash=payload.get("currentPlaylistActivityHash"), + 615 last_story_hash=payload["lastCompletedStoryHash"], + 616 available_activities=[ + 617 self.deserialize_available_activity(activity_) + 618 for activity_ in payload["availableActivities"] + 619 ], + 620 ) + 621 + 622 def deserialize_profile_items( + 623 self, payload: typedefs.JSONObject, / + 624 ) -> list[profile.ProfileItemImpl]: + 625 return [self.deserialize_profile_item(item) for item in payload["items"]] + 626 + 627 def _deserialize_node(self, payload: typedefs.JSONObject) -> records.Node: + 628 return records.Node( + 629 state=int(payload["state"]), + 630 objective=self.deserialize_objectives(payload["objective"]) + 631 if "objective" in payload + 632 else None, + 633 progress_value=int(payload["progressValue"]), + 634 completion_value=int(payload["completionValue"]), + 635 record_category_score=int(payload["recordCategoryScore"]) + 636 if "recordCategoryScore" in payload + 637 else None, + 638 ) + 639 + 640 @staticmethod + 641 def _deserialize_collectible(payload: typedefs.JSONObject) -> items.Collectible: + 642 recent_collectibles: typing.Optional[collections.Collection[int]] = None + 643 if raw_recent_collectibles := payload.get("recentCollectibleHashes"): + 644 recent_collectibles = [ + 645 int(item_hash) for item_hash in raw_recent_collectibles + 646 ] + 647 + 648 collectibles: dict[int, int] = {} + 649 for item_hash, mapping in payload["collectibles"].items(): + 650 collectibles[int(item_hash)] = int(mapping["state"]) + 651 + 652 return items.Collectible( + 653 recent_collectibles=recent_collectibles, + 654 collectibles=collectibles, + 655 collection_categorie_hash=int(payload["collectionCategoriesRootNodeHash"]), + 656 collection_badges_hash=int(payload["collectionBadgesRootNodeHash"]), + 657 ) + 658 + 659 @staticmethod + 660 def _deserialize_currencies( + 661 payload: typedefs.JSONObject, + 662 ) -> collections.Sequence[items.Currency]: + 663 return [ + 664 items.Currency(hash=int(item_hash), amount=int(amount)) + 665 for item_hash, amount in payload["itemQuantities"].items() + 666 ] + 667 + 668 def deserialize_progressions( + 669 self, payload: typedefs.JSONObject + 670 ) -> progressions.Progression: + 671 return progressions.Progression( + 672 hash=int(payload["progressionHash"]), + 673 level=int(payload["level"]), + 674 cap=int(payload["levelCap"]), + 675 daily_limit=int(payload["dailyLimit"]), + 676 weekly_limit=int(payload["weeklyLimit"]), + 677 current_progress=int(payload["currentProgress"]), + 678 daily_progress=int(payload["dailyProgress"]), + 679 needed=int(payload["progressToNextLevel"]), + 680 next_level=int(payload["nextLevelAt"]), + 681 ) + 682 + 683 def _deserialize_factions( + 684 self, payload: typedefs.JSONObject + 685 ) -> progressions.Factions: + 686 progs = self.deserialize_progressions(payload) + 687 return progressions.Factions( + 688 hash=progs.hash, + 689 level=progs.level, + 690 cap=progs.cap, + 691 daily_limit=progs.daily_limit, + 692 weekly_limit=progs.weekly_limit, + 693 current_progress=progs.current_progress, + 694 daily_progress=progs.daily_progress, + 695 needed=progs.needed, + 696 next_level=progs.next_level, + 697 faction_hash=payload["factionHash"], + 698 faction_vendor_hash=payload["factionVendorIndex"], + 699 ) + 700 + 701 def _deserialize_milestone_available_quest( + 702 self, payload: typedefs.JSONObject + 703 ) -> milestones.MilestoneQuest: + 704 return milestones.MilestoneQuest( + 705 item_hash=payload["questItemHash"], + 706 status=self._deserialize_milestone_quest_status(payload["status"]), + 707 ) + 708 + 709 def _deserialize_milestone_activity( + 710 self, payload: typedefs.JSONObject + 711 ) -> milestones.MilestoneActivity: + 712 + 713 phases: typing.Optional[ + 714 collections.Sequence[milestones.MilestoneActivityPhase] + 715 ] = None + 716 if raw_phases := payload.get("phases"): + 717 phases = [ + 718 milestones.MilestoneActivityPhase( + 719 is_completed=obj["complete"], hash=obj["phaseHash"] + 720 ) + 721 for obj in raw_phases + 722 ] + 723 + 724 return milestones.MilestoneActivity( + 725 hash=payload["activityHash"], + 726 challenges=[ + 727 self.deserialize_objectives(obj["objective"]) + 728 for obj in payload["challenges"] + 729 ], + 730 modifier_hashes=payload.get("modifierHashes"), + 731 boolean_options=payload.get("booleanActivityOptions"), + 732 phases=phases, + 733 ) + 734 + 735 def _deserialize_milestone_quest_status( + 736 self, payload: typedefs.JSONObject + 737 ) -> milestones.QuestStatus: + 738 return milestones.QuestStatus( + 739 net=self._net, + 740 quest_hash=payload["questHash"], + 741 step_hash=payload["stepHash"], + 742 step_objectives=[ + 743 self.deserialize_objectives(objective) + 744 for objective in payload["stepObjectives"] + 745 ], + 746 is_tracked=payload["tracked"], + 747 is_completed=payload["completed"], + 748 started=payload["started"], + 749 item_instance_id=payload["itemInstanceId"], + 750 vendor_hash=payload.get("vendorHash"), + 751 is_redeemed=payload["redeemed"], + 752 ) + 753 + 754 def _deserialize_milestone_rewards( + 755 self, payload: typedefs.JSONObject + 756 ) -> milestones.MilestoneReward: + 757 return milestones.MilestoneReward( + 758 category_hash=payload["rewardCategoryHash"], + 759 entries=[ + 760 milestones.MilestoneRewardEntry( + 761 entry_hash=entry["rewardEntryHash"], + 762 is_earned=entry["earned"], + 763 is_redeemed=entry["redeemed"], + 764 ) + 765 for entry in payload["entries"] + 766 ], + 767 ) + 768 + 769 def deserialize_milestone( + 770 self, payload: typedefs.JSONObject + 771 ) -> milestones.Milestone: + 772 start_date: typing.Optional[datetime.datetime] = None + 773 if raw_start_date := payload.get("startDate"): + 774 start_date = time.clean_date(raw_start_date) + 775 + 776 end_date: typing.Optional[datetime.datetime] = None + 777 if raw_end_date := payload.get("endDate"): + 778 end_date = time.clean_date(raw_end_date) + 779 + 780 rewards: typing.Optional[ + 781 collections.Collection[milestones.MilestoneReward] + 782 ] = None + 783 if raw_rewards := payload.get("rewards"): + 784 rewards = [ + 785 self._deserialize_milestone_rewards(reward) for reward in raw_rewards + 786 ] + 787 + 788 activities: typing.Optional[ + 789 collections.Sequence[milestones.MilestoneActivity] + 790 ] = None + 791 if raw_activities := payload.get("activities"): + 792 activities = [ + 793 self._deserialize_milestone_activity(active) + 794 for active in raw_activities + 795 ] + 796 + 797 quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None + 798 if raw_quests := payload.get("availableQuests"): + 799 quests = [ + 800 self._deserialize_milestone_available_quest(quest) + 801 for quest in raw_quests + 802 ] + 803 + 804 vendors: typing.Optional[ + 805 collections.Sequence[milestones.MilestoneVendor] + 806 ] = None + 807 if raw_vendors := payload.get("vendors"): + 808 vendors = [ + 809 milestones.MilestoneVendor( + 810 vendor_hash=vendor["vendorHash"], + 811 preview_itemhash=vendor.get("previewItemHash"), + 812 ) + 813 for vendor in raw_vendors + 814 ] + 815 + 816 return milestones.Milestone( + 817 hash=payload["milestoneHash"], + 818 start_date=start_date, + 819 end_date=end_date, + 820 order=payload["order"], + 821 rewards=rewards, + 822 available_quests=quests, + 823 activities=activities, + 824 vendors=vendors, + 825 ) + 826 + 827 def _deserialize_artifact_tiers( + 828 self, payload: typedefs.JSONObject + 829 ) -> season.ArtifactTier: + 830 return season.ArtifactTier( + 831 hash=payload["tierHash"], + 832 is_unlocked=payload["isUnlocked"], + 833 points_to_unlock=payload["pointsToUnlock"], + 834 items=[ + 835 season.ArtifactTierItem( + 836 hash=item["itemHash"], is_active=item["isActive"] + 837 ) + 838 for item in payload["items"] + 839 ], + 840 ) + 841 + 842 def deserialize_characters( + 843 self, payload: typedefs.JSONObject + 844 ) -> collections.Mapping[int, character.Character]: + 845 return { + 846 int(char_id): self._set_character_attrs(char) + 847 for char_id, char in payload["data"].items() + 848 } + 849 + 850 def deserialize_character( + 851 self, payload: typedefs.JSONObject + 852 ) -> character.Character: + 853 return self._set_character_attrs(payload) + 854 + 855 def deserialize_character_equipments( + 856 self, payload: typedefs.JSONObject + 857 ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]: + 858 return { + 859 int(char_id): self.deserialize_profile_items(item) + 860 for char_id, item in payload["data"].items() + 861 } + 862 + 863 def deserialize_character_activities( + 864 self, payload: typedefs.JSONObject + 865 ) -> collections.Mapping[int, activity.CharacterActivity]: + 866 return { + 867 int(char_id): self.deserialize_character_activity(data) + 868 for char_id, data in payload["data"].items() + 869 } + 870 + 871 def deserialize_characters_render_data( + 872 self, payload: typedefs.JSONObject + 873 ) -> collections.Mapping[int, character.RenderedData]: + 874 return { + 875 int(char_id): self.deserialize_character_render_data(data) + 876 for char_id, data in payload["data"].items() + 877 } + 878 + 879 def deserialize_character_progressions( + 880 self, payload: typedefs.JSONObject + 881 ) -> character.CharacterProgression: + 882 progressions_ = { + 883 int(prog_id): self.deserialize_progressions(prog) + 884 for prog_id, prog in payload["progressions"].items() + 885 } + 886 + 887 factions = { + 888 int(faction_id): self._deserialize_factions(faction) + 889 for faction_id, faction in payload["factions"].items() + 890 } + 891 + 892 milestones_ = { + 893 int(milestone_hash): self.deserialize_milestone(milestone) + 894 for milestone_hash, milestone in payload["milestones"].items() + 895 } + 896 + 897 uninstanced_item_objectives = { + 898 int(item_hash): [self.deserialize_objectives(ins) for ins in obj] + 899 for item_hash, obj in payload["uninstancedItemObjectives"].items() + 900 } + 901 + 902 artifact = payload["seasonalArtifact"] + 903 seasonal_artifact = season.CharacterScopedArtifact( + 904 hash=artifact["artifactHash"], + 905 points_used=artifact["pointsUsed"], + 906 reset_count=artifact["resetCount"], + 907 tiers=[ + 908 self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"] + 909 ], + 910 ) + 911 checklists = payload["checklists"] + 912 + 913 return character.CharacterProgression( + 914 progressions=progressions_, + 915 factions=factions, + 916 checklists=checklists, + 917 milestones=milestones_, + 918 seasonal_artifact=seasonal_artifact, + 919 uninstanced_item_objectives=uninstanced_item_objectives, + 920 ) + 921 + 922 def deserialize_character_progressions_mapping( + 923 self, payload: typedefs.JSONObject + 924 ) -> collections.Mapping[int, character.CharacterProgression]: + 925 character_progressions: collections.Mapping[ + 926 int, character.CharacterProgression + 927 ] = {} + 928 for char_id, data in payload["data"].items(): + 929 # A little hack to stop mypy complaining about Mapping <-> dict + 930 character_progressions[int(char_id)] = self.deserialize_character_progressions(data) # type: ignore[index] + 931 return character_progressions + 932 + 933 def deserialize_characters_records( + 934 self, + 935 payload: typedefs.JSONObject, + 936 ) -> collections.Mapping[int, records.CharacterRecord]: + 937 + 938 return { + 939 int(rec_id): self.deserialize_character_records( + 940 rec, record_hashes=payload.get("featuredRecordHashes") + 941 ) + 942 for rec_id, rec in payload["records"].items() + 943 } + 944 + 945 def deserialize_profile_records( + 946 self, payload: typedefs.JSONObject + 947 ) -> collections.Mapping[int, records.Record]: + 948 raw_profile_records = payload["data"] + 949 scores = records.RecordScores( + 950 current_score=raw_profile_records["score"], + 951 legacy_score=raw_profile_records["legacyScore"], + 952 lifetime_score=raw_profile_records["lifetimeScore"], + 953 ) + 954 return { + 955 int(record_id): self.deserialize_records( + 956 record, + 957 scores, + 958 categories_hash=raw_profile_records["recordCategoriesRootNodeHash"], + 959 seals_hash=raw_profile_records["recordSealsRootNodeHash"], + 960 ) + 961 for record_id, record in raw_profile_records["records"].items() + 962 } + 963 + 964 def _deserialize_craftable_socket_plug( + 965 self, payload: typedefs.JSONObject + 966 ) -> items.CraftableSocketPlug: + 967 return items.CraftableSocketPlug( + 968 item_hash=int(payload["plugItemHash"]), + 969 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), + 970 ) + 971 + 972 def _deserialize_craftable_socket( + 973 self, payload: typedefs.JSONObject + 974 ) -> items.CraftableSocket: + 975 + 976 plugs: list[items.CraftableSocketPlug] = [] + 977 if raw_plug := payload.get("plug"): + 978 plugs.extend( + 979 self._deserialize_craftable_socket_plug(plug) for plug in raw_plug + 980 ) 981 - 982 plugs: list[items.CraftableSocketPlug] = [] - 983 if raw_plug := payload.get("plug"): - 984 plugs.extend( - 985 self._deserialize_craftable_socket_plug(plug) for plug in raw_plug - 986 ) - 987 - 988 return items.CraftableSocket( - 989 plug_set_hash=int(payload["plugSetHash"]), plugs=plugs - 990 ) - 991 - 992 def _deserialize_craftable_item( - 993 self, payload: typedefs.JSONObject - 994 ) -> items.CraftableItem: - 995 - 996 return items.CraftableItem( - 997 is_visible=payload["visible"], - 998 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), - 999 sockets=[ -1000 self._deserialize_craftable_socket(socket) -1001 for socket in payload["sockets"] -1002 ], -1003 ) -1004 -1005 def deserialize_craftables_component( -1006 self, payload: typedefs.JSONObject -1007 ) -> components.CraftablesComponent: -1008 return components.CraftablesComponent( -1009 net=self._net, -1010 craftables={ -1011 int(item_id): self._deserialize_craftable_item(item) -1012 for item_id, item in payload["craftables"].items() -1013 if item is not None -1014 }, -1015 crafting_root_node_hash=payload["craftingRootNodeHash"], -1016 ) -1017 -1018 def deserialize_components( # noqa: C901 Too complex. -1019 self, payload: typedefs.JSONObject -1020 ) -> components.Component: -1021 -1022 profile_: typing.Optional[profile.Profile] = None -1023 if raw_profile := payload.get("profile"): -1024 profile_ = self.deserialize_profile(raw_profile) + 982 return items.CraftableSocket( + 983 plug_set_hash=int(payload["plugSetHash"]), plugs=plugs + 984 ) + 985 + 986 def _deserialize_craftable_item( + 987 self, payload: typedefs.JSONObject + 988 ) -> items.CraftableItem: + 989 + 990 return items.CraftableItem( + 991 is_visible=payload["visible"], + 992 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), + 993 sockets=[ + 994 self._deserialize_craftable_socket(socket) + 995 for socket in payload["sockets"] + 996 ], + 997 ) + 998 + 999 def deserialize_craftables_component( +1000 self, payload: typedefs.JSONObject +1001 ) -> components.CraftablesComponent: +1002 return components.CraftablesComponent( +1003 net=self._net, +1004 craftables={ +1005 int(item_id): self._deserialize_craftable_item(item) +1006 for item_id, item in payload["craftables"].items() +1007 if item is not None +1008 }, +1009 crafting_root_node_hash=payload["craftingRootNodeHash"], +1010 ) +1011 +1012 def deserialize_components( # noqa: C901 Too complex. +1013 self, payload: typedefs.JSONObject +1014 ) -> components.Component: +1015 +1016 profile_: typing.Optional[profile.Profile] = None +1017 if raw_profile := payload.get("profile"): +1018 profile_ = self.deserialize_profile(raw_profile) +1019 +1020 profile_progression: typing.Optional[profile.ProfileProgression] = None +1021 if raw_profile_progression := payload.get("profileProgression"): +1022 profile_progression = self.deserialize_profile_progression( +1023 raw_profile_progression +1024 ) 1025 -1026 profile_progression: typing.Optional[profile.ProfileProgression] = None -1027 if raw_profile_progression := payload.get("profileProgression"): -1028 profile_progression = self.deserialize_profile_progression( -1029 raw_profile_progression -1030 ) -1031 -1032 profile_currencies: typing.Optional[ -1033 collections.Sequence[profile.ProfileItemImpl] -1034 ] = None -1035 if raw_profile_currencies := payload.get("profileCurrencies"): -1036 if "data" in raw_profile_currencies: -1037 profile_currencies = self.deserialize_profile_items( -1038 raw_profile_currencies["data"] -1039 ) -1040 -1041 profile_inventories: typing.Optional[ -1042 collections.Sequence[profile.ProfileItemImpl] -1043 ] = None -1044 if raw_profile_inventories := payload.get("profileInventory"): -1045 if "data" in raw_profile_inventories: -1046 profile_inventories = self.deserialize_profile_items( -1047 raw_profile_inventories["data"] -1048 ) -1049 -1050 profile_records: typing.Optional[ -1051 collections.Mapping[int, records.Record] -1052 ] = None -1053 -1054 if raw_profile_records_ := payload.get("profileRecords"): -1055 profile_records = self.deserialize_profile_records(raw_profile_records_) -1056 -1057 characters: typing.Optional[typing.Mapping[int, character.Character]] = None -1058 if raw_characters := payload.get("characters"): -1059 characters = self.deserialize_characters(raw_characters) -1060 -1061 character_records: typing.Optional[ -1062 collections.Mapping[int, records.CharacterRecord] -1063 ] = None -1064 -1065 if raw_character_records := payload.get("characterRecords"): -1066 # Had to do it in two steps.. -1067 to_update: typedefs.JSONObject = {} -1068 for _, data in raw_character_records["data"].items(): -1069 for record_id, record in data.items(): -1070 to_update[record_id] = record -1071 -1072 character_records = { -1073 int(rec_id): self.deserialize_character_records( -1074 rec, record_hashes=to_update.get("featuredRecordHashes") -1075 ) -1076 for rec_id, rec in to_update["records"].items() -1077 } -1078 -1079 character_equipments: typing.Optional[ -1080 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] -1081 ] = None -1082 if raw_character_equips := payload.get("characterEquipment"): -1083 character_equipments = self.deserialize_character_equipments( -1084 raw_character_equips -1085 ) -1086 -1087 character_inventories: typing.Optional[ -1088 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] -1089 ] = None -1090 if raw_character_inventories := payload.get("characterInventories"): -1091 if "data" in raw_character_inventories: -1092 character_inventories = self.deserialize_character_equipments( -1093 raw_character_inventories -1094 ) +1026 profile_currencies: typing.Optional[ +1027 collections.Sequence[profile.ProfileItemImpl] +1028 ] = None +1029 if raw_profile_currencies := payload.get("profileCurrencies"): +1030 if "data" in raw_profile_currencies: +1031 profile_currencies = self.deserialize_profile_items( +1032 raw_profile_currencies["data"] +1033 ) +1034 +1035 profile_inventories: typing.Optional[ +1036 collections.Sequence[profile.ProfileItemImpl] +1037 ] = None +1038 if raw_profile_inventories := payload.get("profileInventory"): +1039 if "data" in raw_profile_inventories: +1040 profile_inventories = self.deserialize_profile_items( +1041 raw_profile_inventories["data"] +1042 ) +1043 +1044 profile_records: typing.Optional[ +1045 collections.Mapping[int, records.Record] +1046 ] = None +1047 +1048 if raw_profile_records_ := payload.get("profileRecords"): +1049 profile_records = self.deserialize_profile_records(raw_profile_records_) +1050 +1051 characters: typing.Optional[typing.Mapping[int, character.Character]] = None +1052 if raw_characters := payload.get("characters"): +1053 characters = self.deserialize_characters(raw_characters) +1054 +1055 character_records: typing.Optional[ +1056 collections.Mapping[int, records.CharacterRecord] +1057 ] = None +1058 +1059 if raw_character_records := payload.get("characterRecords"): +1060 # Had to do it in two steps.. +1061 to_update: typedefs.JSONObject = {} +1062 for _, data in raw_character_records["data"].items(): +1063 for record_id, record in data.items(): +1064 to_update[record_id] = record +1065 +1066 character_records = { +1067 int(rec_id): self.deserialize_character_records( +1068 rec, record_hashes=to_update.get("featuredRecordHashes") +1069 ) +1070 for rec_id, rec in to_update["records"].items() +1071 } +1072 +1073 character_equipments: typing.Optional[ +1074 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] +1075 ] = None +1076 if raw_character_equips := payload.get("characterEquipment"): +1077 character_equipments = self.deserialize_character_equipments( +1078 raw_character_equips +1079 ) +1080 +1081 character_inventories: typing.Optional[ +1082 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] +1083 ] = None +1084 if raw_character_inventories := payload.get("characterInventories"): +1085 if "data" in raw_character_inventories: +1086 character_inventories = self.deserialize_character_equipments( +1087 raw_character_inventories +1088 ) +1089 +1090 character_activities: typing.Optional[ +1091 collections.Mapping[int, activity.CharacterActivity] +1092 ] = None +1093 if raw_char_acts := payload.get("characterActivities"): +1094 character_activities = self.deserialize_character_activities(raw_char_acts) 1095 -1096 character_activities: typing.Optional[ -1097 collections.Mapping[int, activity.CharacterActivity] +1096 character_render_data: typing.Optional[ +1097 collections.Mapping[int, character.RenderedData] 1098 ] = None -1099 if raw_char_acts := payload.get("characterActivities"): -1100 character_activities = self.deserialize_character_activities(raw_char_acts) -1101 -1102 character_render_data: typing.Optional[ -1103 collections.Mapping[int, character.RenderedData] -1104 ] = None -1105 if raw_character_render_data := payload.get("characterRenderData"): -1106 character_render_data = self.deserialize_characters_render_data( -1107 raw_character_render_data -1108 ) -1109 -1110 character_progressions: typing.Optional[ -1111 collections.Mapping[int, character.CharacterProgression] -1112 ] = None -1113 -1114 if raw_character_progressions := payload.get("characterProgressions"): -1115 character_progressions = self.deserialize_character_progressions_mapping( -1116 raw_character_progressions -1117 ) -1118 -1119 profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None -1120 if raw_profile_string_vars := payload.get("profileStringVariables"): -1121 profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"] -1122 -1123 character_string_vars: typing.Optional[ -1124 collections.Mapping[int, collections.Mapping[int, int]] -1125 ] = None -1126 if raw_character_string_vars := payload.get("characterStringVariables"): -1127 character_string_vars = { -1128 int(char_id): data["integerValuesByHash"] -1129 for char_id, data in raw_character_string_vars["data"].items() -1130 } -1131 -1132 metrics: typing.Optional[ -1133 collections.Sequence[ -1134 collections.Mapping[ -1135 int, tuple[bool, typing.Optional[records.Objective]] -1136 ] -1137 ] -1138 ] = None -1139 root_node_hash: typing.Optional[int] = None -1140 -1141 if raw_metrics := payload.get("metrics"): -1142 root_node_hash = raw_metrics["data"]["metricsRootNodeHash"] -1143 metrics = [ -1144 { -1145 int(metrics_hash): ( -1146 data["invisible"], -1147 self.deserialize_objectives(data["objectiveProgress"]) -1148 if "objectiveProgress" in data -1149 else None, -1150 ) -1151 for metrics_hash, data in raw_metrics["data"]["metrics"].items() -1152 } -1153 ] -1154 transitory: typing.Optional[fireteams.FireteamParty] = None -1155 if raw_transitory := payload.get("profileTransitoryData"): -1156 if "data" in raw_transitory: -1157 transitory = self.deserialize_fireteam_party(raw_transitory["data"]) -1158 -1159 item_components: typing.Optional[components.ItemsComponent] = None -1160 if raw_item_components := payload.get("itemComponents"): -1161 item_components = self.deserialize_items_component(raw_item_components) -1162 -1163 profile_plugsets: typing.Optional[ -1164 collections.Mapping[int, collections.Sequence[items.PlugItemState]] -1165 ] = None +1099 if raw_character_render_data := payload.get("characterRenderData"): +1100 character_render_data = self.deserialize_characters_render_data( +1101 raw_character_render_data +1102 ) +1103 +1104 character_progressions: typing.Optional[ +1105 collections.Mapping[int, character.CharacterProgression] +1106 ] = None +1107 +1108 if raw_character_progressions := payload.get("characterProgressions"): +1109 character_progressions = self.deserialize_character_progressions_mapping( +1110 raw_character_progressions +1111 ) +1112 +1113 profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None +1114 if raw_profile_string_vars := payload.get("profileStringVariables"): +1115 profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"] +1116 +1117 character_string_vars: typing.Optional[ +1118 collections.Mapping[int, collections.Mapping[int, int]] +1119 ] = None +1120 if raw_character_string_vars := payload.get("characterStringVariables"): +1121 character_string_vars = { +1122 int(char_id): data["integerValuesByHash"] +1123 for char_id, data in raw_character_string_vars["data"].items() +1124 } +1125 +1126 metrics: typing.Optional[ +1127 collections.Sequence[ +1128 collections.Mapping[ +1129 int, tuple[bool, typing.Optional[records.Objective]] +1130 ] +1131 ] +1132 ] = None +1133 root_node_hash: typing.Optional[int] = None +1134 +1135 if raw_metrics := payload.get("metrics"): +1136 root_node_hash = raw_metrics["data"]["metricsRootNodeHash"] +1137 metrics = [ +1138 { +1139 int(metrics_hash): ( +1140 data["invisible"], +1141 self.deserialize_objectives(data["objectiveProgress"]) +1142 if "objectiveProgress" in data +1143 else None, +1144 ) +1145 for metrics_hash, data in raw_metrics["data"]["metrics"].items() +1146 } +1147 ] +1148 transitory: typing.Optional[fireteams.FireteamParty] = None +1149 if raw_transitory := payload.get("profileTransitoryData"): +1150 if "data" in raw_transitory: +1151 transitory = self.deserialize_fireteam_party(raw_transitory["data"]) +1152 +1153 item_components: typing.Optional[components.ItemsComponent] = None +1154 if raw_item_components := payload.get("itemComponents"): +1155 item_components = self.deserialize_items_component(raw_item_components) +1156 +1157 profile_plugsets: typing.Optional[ +1158 collections.Mapping[int, collections.Sequence[items.PlugItemState]] +1159 ] = None +1160 +1161 if raw_profile_plugs := payload.get("profilePlugSets"): +1162 profile_plugsets = { +1163 int(index): [self.deserialize_plug_item_state(state) for state in data] +1164 for index, data in raw_profile_plugs["data"]["plugs"].items() +1165 } 1166 -1167 if raw_profile_plugs := payload.get("profilePlugSets"): -1168 profile_plugsets = { -1169 int(index): [self.deserialize_plug_item_state(state) for state in data] -1170 for index, data in raw_profile_plugs["data"]["plugs"].items() -1171 } -1172 -1173 character_plugsets: typing.Optional[ -1174 collections.Mapping[ -1175 int, collections.Mapping[int, collections.Sequence[items.PlugItemState]] -1176 ] -1177 ] = None -1178 if raw_char_plugsets := payload.get("characterPlugSets"): -1179 character_plugsets = { -1180 int(char_id): { -1181 int(index): [ -1182 self.deserialize_plug_item_state(state) for state in data -1183 ] -1184 for index, data in inner["plugs"].items() -1185 } -1186 for char_id, inner in raw_char_plugsets["data"].items() -1187 } -1188 -1189 character_collectibles: typing.Optional[ -1190 collections.Mapping[int, items.Collectible] -1191 ] = None -1192 if raw_character_collectibles := payload.get("characterCollectibles"): -1193 character_collectibles = { -1194 int(char_id): self._deserialize_collectible(data) -1195 for char_id, data in raw_character_collectibles["data"].items() -1196 } +1167 character_plugsets: typing.Optional[ +1168 collections.Mapping[ +1169 int, collections.Mapping[int, collections.Sequence[items.PlugItemState]] +1170 ] +1171 ] = None +1172 if raw_char_plugsets := payload.get("characterPlugSets"): +1173 character_plugsets = { +1174 int(char_id): { +1175 int(index): [ +1176 self.deserialize_plug_item_state(state) for state in data +1177 ] +1178 for index, data in inner["plugs"].items() +1179 } +1180 for char_id, inner in raw_char_plugsets["data"].items() +1181 } +1182 +1183 character_collectibles: typing.Optional[ +1184 collections.Mapping[int, items.Collectible] +1185 ] = None +1186 if raw_character_collectibles := payload.get("characterCollectibles"): +1187 character_collectibles = { +1188 int(char_id): self._deserialize_collectible(data) +1189 for char_id, data in raw_character_collectibles["data"].items() +1190 } +1191 +1192 profile_collectibles: typing.Optional[items.Collectible] = None +1193 if raw_profile_collectibles := payload.get("profileCollectibles"): +1194 profile_collectibles = self._deserialize_collectible( +1195 raw_profile_collectibles["data"] +1196 ) 1197 -1198 profile_collectibles: typing.Optional[items.Collectible] = None -1199 if raw_profile_collectibles := payload.get("profileCollectibles"): -1200 profile_collectibles = self._deserialize_collectible( -1201 raw_profile_collectibles["data"] -1202 ) -1203 -1204 profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None -1205 if raw_profile_nodes := payload.get("profilePresentationNodes"): -1206 profile_nodes = { -1207 int(node_hash): self._deserialize_node(node) -1208 for node_hash, node in raw_profile_nodes["data"]["nodes"].items() -1209 } -1210 -1211 character_nodes: typing.Optional[ -1212 collections.Mapping[int, collections.Mapping[int, records.Node]] -1213 ] = None -1214 if raw_character_nodes := payload.get("characterPresentationNodes"): -1215 character_nodes = { -1216 int(char_id): { -1217 int(node_hash): self._deserialize_node(node) -1218 for node_hash, node in each_character["nodes"].items() -1219 } -1220 for char_id, each_character in raw_character_nodes["data"].items() -1221 } -1222 -1223 platform_silver: typing.Optional[ -1224 collections.Mapping[str, profile.ProfileItemImpl] -1225 ] = None -1226 if raw_platform_silver := payload.get("platformSilver"): -1227 if "data" in raw_platform_silver: -1228 platform_silver = { -1229 platform_name: self.deserialize_profile_item(item) -1230 for platform_name, item in raw_platform_silver["data"][ -1231 "platformSilver" -1232 ].items() -1233 } -1234 -1235 character_currency_lookups: typing.Optional[ -1236 collections.Mapping[int, collections.Sequence[items.Currency]] -1237 ] = None -1238 if raw_char_lookups := payload.get("characterCurrencyLookups"): -1239 if "data" in raw_char_lookups: -1240 character_currency_lookups = { -1241 int(char_id): self._deserialize_currencies(currencie) -1242 for char_id, currencie in raw_char_lookups["data"].items() -1243 } -1244 -1245 character_craftables: typing.Optional[ -1246 collections.Mapping[int, components.CraftablesComponent] -1247 ] = None -1248 if raw_character_craftables := payload.get("characterCraftables"): +1198 profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None +1199 if raw_profile_nodes := payload.get("profilePresentationNodes"): +1200 profile_nodes = { +1201 int(node_hash): self._deserialize_node(node) +1202 for node_hash, node in raw_profile_nodes["data"]["nodes"].items() +1203 } +1204 +1205 character_nodes: typing.Optional[ +1206 collections.Mapping[int, collections.Mapping[int, records.Node]] +1207 ] = None +1208 if raw_character_nodes := payload.get("characterPresentationNodes"): +1209 character_nodes = { +1210 int(char_id): { +1211 int(node_hash): self._deserialize_node(node) +1212 for node_hash, node in each_character["nodes"].items() +1213 } +1214 for char_id, each_character in raw_character_nodes["data"].items() +1215 } +1216 +1217 platform_silver: typing.Optional[ +1218 collections.Mapping[str, profile.ProfileItemImpl] +1219 ] = None +1220 if raw_platform_silver := payload.get("platformSilver"): +1221 if "data" in raw_platform_silver: +1222 platform_silver = { +1223 platform_name: self.deserialize_profile_item(item) +1224 for platform_name, item in raw_platform_silver["data"][ +1225 "platformSilver" +1226 ].items() +1227 } +1228 +1229 character_currency_lookups: typing.Optional[ +1230 collections.Mapping[int, collections.Sequence[items.Currency]] +1231 ] = None +1232 if raw_char_lookups := payload.get("characterCurrencyLookups"): +1233 if "data" in raw_char_lookups: +1234 character_currency_lookups = { +1235 int(char_id): self._deserialize_currencies(currencie) +1236 for char_id, currencie in raw_char_lookups["data"].items() +1237 } +1238 +1239 character_craftables: typing.Optional[ +1240 collections.Mapping[int, components.CraftablesComponent] +1241 ] = None +1242 if raw_character_craftables := payload.get("characterCraftables"): +1243 +1244 if "data" in raw_character_craftables: +1245 character_craftables = { +1246 int(char_id): self.deserialize_craftables_component(craftable) +1247 for char_id, craftable in raw_character_craftables["data"].items() +1248 } 1249 -1250 if "data" in raw_character_craftables: -1251 character_craftables = { -1252 int(char_id): self.deserialize_craftables_component(craftable) -1253 for char_id, craftable in raw_character_craftables["data"].items() -1254 } -1255 -1256 return components.Component( -1257 profiles=profile_, -1258 profile_progression=profile_progression, -1259 profile_currencies=profile_currencies, -1260 profile_inventories=profile_inventories, -1261 profile_records=profile_records, -1262 characters=characters, -1263 character_records=character_records, -1264 character_equipments=character_equipments, -1265 character_inventories=character_inventories, -1266 character_activities=character_activities, -1267 character_render_data=character_render_data, -1268 character_progressions=character_progressions, -1269 profile_string_variables=profile_string_vars, -1270 character_string_variables=character_string_vars, -1271 metrics=metrics, -1272 root_node_hash=root_node_hash, -1273 transitory=transitory, -1274 item_components=item_components, -1275 profile_plugsets=profile_plugsets, -1276 character_plugsets=character_plugsets, -1277 character_collectibles=character_collectibles, -1278 profile_collectibles=profile_collectibles, -1279 profile_nodes=profile_nodes, -1280 character_nodes=character_nodes, -1281 platform_silver=platform_silver, -1282 character_currency_lookups=character_currency_lookups, -1283 character_craftables=character_craftables, -1284 ) -1285 -1286 def deserialize_items_component( -1287 self, payload: typedefs.JSONObject -1288 ) -> components.ItemsComponent: -1289 instances: typing.Optional[ -1290 collections.Sequence[collections.Mapping[int, items.ItemInstance]] -1291 ] = None -1292 if raw_instances := payload.get("instances"): -1293 instances = [ -1294 { -1295 int(ins_id): self.deserialize_instanced_item(item) -1296 for ins_id, item in raw_instances["data"].items() -1297 } -1298 ] -1299 -1300 render_data: typing.Optional[ -1301 collections.Mapping[int, tuple[bool, dict[int, int]]] -1302 ] = None -1303 if raw_render_data := payload.get("renderData"): -1304 render_data = { -1305 int(ins_id): (data["useCustomDyes"], data["artRegions"]) -1306 for ins_id, data in raw_render_data["data"].items() -1307 } -1308 -1309 stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None -1310 if raw_stats := payload.get("stats"): -1311 builder: collections.Mapping[int, items.ItemStatsView] = {} -1312 for ins_id, stat in raw_stats["data"].items(): -1313 for _, items_ in stat.items(): -1314 builder[int(ins_id)] = self.deserialize_item_stats_view(items_) # type: ignore[index] -1315 stats = builder -1316 -1317 sockets: typing.Optional[ -1318 collections.Mapping[int, collections.Sequence[items.ItemSocket]] -1319 ] = None -1320 if raw_sockets := payload.get("sockets"): -1321 sockets = { -1322 int(ins_id): [ -1323 self.deserialize_item_socket(socket) for socket in item["sockets"] -1324 ] -1325 for ins_id, item in raw_sockets["data"].items() -1326 } -1327 -1328 objeectives: typing.Optional[ -1329 collections.Mapping[int, collections.Sequence[records.Objective]] -1330 ] = None -1331 if raw_objectives := payload.get("objectives"): -1332 objeectives = { -1333 int(ins_id): [self.deserialize_objectives(objective)] -1334 for ins_id, data in raw_objectives["data"].items() -1335 for objective in data["objectives"] -1336 } -1337 -1338 perks: typing.Optional[ -1339 collections.Mapping[int, collections.Collection[items.ItemPerk]] -1340 ] = None -1341 if raw_perks := payload.get("perks"): -1342 perks = { -1343 int(ins_id): [ -1344 self.deserialize_item_perk(perk) for perk in item["perks"] -1345 ] -1346 for ins_id, item in raw_perks["data"].items() -1347 } -1348 -1349 plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None -1350 if raw_plug_states := payload.get("plugStates"): -1351 pending_states: list[items.PlugItemState] = [] -1352 for _, plug in raw_plug_states["data"].items(): -1353 pending_states.append(self.deserialize_plug_item_state(plug)) -1354 plug_states = pending_states -1355 -1356 reusable_plugs: typing.Optional[ -1357 collections.Mapping[int, collections.Sequence[items.PlugItemState]] -1358 ] = None -1359 if raw_re_plugs := payload.get("reusablePlugs"): -1360 reusable_plugs = { -1361 int(ins_id): [ -1362 self.deserialize_plug_item_state(state) for state in inner -1363 ] -1364 for ins_id, plug in raw_re_plugs["data"].items() -1365 for inner in list(plug["plugs"].values()) -1366 } -1367 -1368 plug_objectives: typing.Optional[ -1369 collections.Mapping[ -1370 int, collections.Mapping[int, collections.Collection[records.Objective]] -1371 ] -1372 ] = None -1373 if raw_plug_objectives := payload.get("plugObjectives"): -1374 plug_objectives = { -1375 int(ins_id): { -1376 int(obj_hash): [self.deserialize_objectives(obj) for obj in objs] -1377 for obj_hash, objs in inner["objectivesPerPlug"].items() -1378 } -1379 for ins_id, inner in raw_plug_objectives["data"].items() -1380 } -1381 -1382 return components.ItemsComponent( -1383 sockets=sockets, -1384 stats=stats, -1385 render_data=render_data, -1386 instances=instances, -1387 objectives=objeectives, -1388 perks=perks, -1389 plug_states=plug_states, -1390 reusable_plugs=reusable_plugs, -1391 plug_objectives=plug_objectives, -1392 ) -1393 -1394 def deserialize_character_component( # type: ignore[call-arg] -1395 self, payload: typedefs.JSONObject -1396 ) -> components.CharacterComponent: -1397 -1398 character_: typing.Optional[character.Character] = None -1399 if raw_singuler_character := payload.get("character"): -1400 character_ = self.deserialize_character(raw_singuler_character["data"]) -1401 -1402 inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None -1403 if raw_inventory := payload.get("inventory"): -1404 if "data" in raw_inventory: -1405 inventory = self.deserialize_profile_items(raw_inventory["data"]) -1406 -1407 activities: typing.Optional[activity.CharacterActivity] = None -1408 if raw_activities := payload.get("activities"): -1409 activities = self.deserialize_character_activity(raw_activities["data"]) -1410 -1411 equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None -1412 if raw_equipments := payload.get("equipment"): -1413 equipment = self.deserialize_profile_items(raw_equipments["data"]) +1250 return components.Component( +1251 profiles=profile_, +1252 profile_progression=profile_progression, +1253 profile_currencies=profile_currencies, +1254 profile_inventories=profile_inventories, +1255 profile_records=profile_records, +1256 characters=characters, +1257 character_records=character_records, +1258 character_equipments=character_equipments, +1259 character_inventories=character_inventories, +1260 character_activities=character_activities, +1261 character_render_data=character_render_data, +1262 character_progressions=character_progressions, +1263 profile_string_variables=profile_string_vars, +1264 character_string_variables=character_string_vars, +1265 metrics=metrics, +1266 root_node_hash=root_node_hash, +1267 transitory=transitory, +1268 item_components=item_components, +1269 profile_plugsets=profile_plugsets, +1270 character_plugsets=character_plugsets, +1271 character_collectibles=character_collectibles, +1272 profile_collectibles=profile_collectibles, +1273 profile_nodes=profile_nodes, +1274 character_nodes=character_nodes, +1275 platform_silver=platform_silver, +1276 character_currency_lookups=character_currency_lookups, +1277 character_craftables=character_craftables, +1278 ) +1279 +1280 def deserialize_items_component( +1281 self, payload: typedefs.JSONObject +1282 ) -> components.ItemsComponent: +1283 instances: typing.Optional[ +1284 collections.Sequence[collections.Mapping[int, items.ItemInstance]] +1285 ] = None +1286 if raw_instances := payload.get("instances"): +1287 instances = [ +1288 { +1289 int(ins_id): self.deserialize_instanced_item(item) +1290 for ins_id, item in raw_instances["data"].items() +1291 } +1292 ] +1293 +1294 render_data: typing.Optional[ +1295 collections.Mapping[int, tuple[bool, dict[int, int]]] +1296 ] = None +1297 if raw_render_data := payload.get("renderData"): +1298 render_data = { +1299 int(ins_id): (data["useCustomDyes"], data["artRegions"]) +1300 for ins_id, data in raw_render_data["data"].items() +1301 } +1302 +1303 stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None +1304 if raw_stats := payload.get("stats"): +1305 builder: collections.Mapping[int, items.ItemStatsView] = {} +1306 for ins_id, stat in raw_stats["data"].items(): +1307 for _, items_ in stat.items(): +1308 builder[int(ins_id)] = self.deserialize_item_stats_view(items_) # type: ignore[index] +1309 stats = builder +1310 +1311 sockets: typing.Optional[ +1312 collections.Mapping[int, collections.Sequence[items.ItemSocket]] +1313 ] = None +1314 if raw_sockets := payload.get("sockets"): +1315 sockets = { +1316 int(ins_id): [ +1317 self.deserialize_item_socket(socket) for socket in item["sockets"] +1318 ] +1319 for ins_id, item in raw_sockets["data"].items() +1320 } +1321 +1322 objeectives: typing.Optional[ +1323 collections.Mapping[int, collections.Sequence[records.Objective]] +1324 ] = None +1325 if raw_objectives := payload.get("objectives"): +1326 objeectives = { +1327 int(ins_id): [self.deserialize_objectives(objective)] +1328 for ins_id, data in raw_objectives["data"].items() +1329 for objective in data["objectives"] +1330 } +1331 +1332 perks: typing.Optional[ +1333 collections.Mapping[int, collections.Collection[items.ItemPerk]] +1334 ] = None +1335 if raw_perks := payload.get("perks"): +1336 perks = { +1337 int(ins_id): [ +1338 self.deserialize_item_perk(perk) for perk in item["perks"] +1339 ] +1340 for ins_id, item in raw_perks["data"].items() +1341 } +1342 +1343 plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None +1344 if raw_plug_states := payload.get("plugStates"): +1345 pending_states: list[items.PlugItemState] = [] +1346 for _, plug in raw_plug_states["data"].items(): +1347 pending_states.append(self.deserialize_plug_item_state(plug)) +1348 plug_states = pending_states +1349 +1350 reusable_plugs: typing.Optional[ +1351 collections.Mapping[int, collections.Sequence[items.PlugItemState]] +1352 ] = None +1353 if raw_re_plugs := payload.get("reusablePlugs"): +1354 reusable_plugs = { +1355 int(ins_id): [ +1356 self.deserialize_plug_item_state(state) for state in inner +1357 ] +1358 for ins_id, plug in raw_re_plugs["data"].items() +1359 for inner in list(plug["plugs"].values()) +1360 } +1361 +1362 plug_objectives: typing.Optional[ +1363 collections.Mapping[ +1364 int, collections.Mapping[int, collections.Collection[records.Objective]] +1365 ] +1366 ] = None +1367 if raw_plug_objectives := payload.get("plugObjectives"): +1368 plug_objectives = { +1369 int(ins_id): { +1370 int(obj_hash): [self.deserialize_objectives(obj) for obj in objs] +1371 for obj_hash, objs in inner["objectivesPerPlug"].items() +1372 } +1373 for ins_id, inner in raw_plug_objectives["data"].items() +1374 } +1375 +1376 return components.ItemsComponent( +1377 sockets=sockets, +1378 stats=stats, +1379 render_data=render_data, +1380 instances=instances, +1381 objectives=objeectives, +1382 perks=perks, +1383 plug_states=plug_states, +1384 reusable_plugs=reusable_plugs, +1385 plug_objectives=plug_objectives, +1386 ) +1387 +1388 def deserialize_character_component( # type: ignore[call-arg] +1389 self, payload: typedefs.JSONObject +1390 ) -> components.CharacterComponent: +1391 +1392 character_: typing.Optional[character.Character] = None +1393 if raw_singuler_character := payload.get("character"): +1394 character_ = self.deserialize_character(raw_singuler_character["data"]) +1395 +1396 inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None +1397 if raw_inventory := payload.get("inventory"): +1398 if "data" in raw_inventory: +1399 inventory = self.deserialize_profile_items(raw_inventory["data"]) +1400 +1401 activities: typing.Optional[activity.CharacterActivity] = None +1402 if raw_activities := payload.get("activities"): +1403 activities = self.deserialize_character_activity(raw_activities["data"]) +1404 +1405 equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None +1406 if raw_equipments := payload.get("equipment"): +1407 equipment = self.deserialize_profile_items(raw_equipments["data"]) +1408 +1409 progressions_: typing.Optional[character.CharacterProgression] = None +1410 if raw_progressions := payload.get("progressions"): +1411 progressions_ = self.deserialize_character_progressions( +1412 raw_progressions["data"] +1413 ) 1414 -1415 progressions_: typing.Optional[character.CharacterProgression] = None -1416 if raw_progressions := payload.get("progressions"): -1417 progressions_ = self.deserialize_character_progressions( -1418 raw_progressions["data"] +1415 render_data: typing.Optional[character.RenderedData] = None +1416 if raw_render_data := payload.get("renderData"): +1417 render_data = self.deserialize_character_render_data( +1418 raw_render_data["data"] 1419 ) 1420 -1421 render_data: typing.Optional[character.RenderedData] = None -1422 if raw_render_data := payload.get("renderData"): -1423 render_data = self.deserialize_character_render_data( -1424 raw_render_data["data"] -1425 ) -1426 -1427 character_records: typing.Optional[ -1428 collections.Mapping[int, records.CharacterRecord] -1429 ] = None -1430 if raw_char_records := payload.get("records"): -1431 character_records = self.deserialize_characters_records( -1432 raw_char_records["data"] -1433 ) -1434 -1435 item_components: typing.Optional[components.ItemsComponent] = None -1436 if raw_item_components := payload.get("itemComponents"): -1437 item_components = self.deserialize_items_component(raw_item_components) -1438 -1439 nodes: typing.Optional[collections.Mapping[int, records.Node]] = None -1440 if raw_nodes := payload.get("presentationNodes"): -1441 nodes = { -1442 int(node_hash): self._deserialize_node(node) -1443 for node_hash, node in raw_nodes["data"]["nodes"].items() -1444 } -1445 -1446 collectibles: typing.Optional[items.Collectible] = None -1447 if raw_collectibles := payload.get("collectibles"): -1448 collectibles = self._deserialize_collectible(raw_collectibles["data"]) -1449 -1450 currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None -1451 if raw_currencies := payload.get("currencyLookups"): -1452 if "data" in raw_currencies: -1453 currency_lookups = self._deserialize_currencies(raw_currencies) -1454 -1455 return components.CharacterComponent( -1456 activities=activities, -1457 equipment=equipment, -1458 inventory=inventory, -1459 progressions=progressions_, -1460 render_data=render_data, -1461 character=character_, -1462 character_records=character_records, -1463 profile_records=None, -1464 item_components=item_components, -1465 currency_lookups=currency_lookups, -1466 collectibles=collectibles, -1467 nodes=nodes, -1468 ) -1469 -1470 def _set_entity_attrs( -1471 self, payload: typedefs.JSONObject, *, key: str = "displayProperties" -1472 ) -> entity.Entity: -1473 -1474 name: undefined.UndefinedOr[str] = undefined.Undefined -1475 description: undefined.UndefinedOr[str] = undefined.Undefined -1476 -1477 if properties := payload[key]: -1478 if (raw_name := properties["name"]) is not typedefs.Unknown: -1479 name = raw_name -1480 -1481 if ( -1482 raw_description := properties["description"] -1483 ) and not typedefs.is_unknown(raw_description): -1484 description = raw_description -1485 -1486 return entity.Entity( -1487 net=self._net, -1488 hash=payload["hash"], -1489 index=payload["index"], -1490 name=name, -1491 description=description, -1492 has_icon=properties["hasIcon"], -1493 icon=assets.Image(properties["icon"] if "icon" in properties else None), -1494 ) -1495 -1496 def deserialize_inventory_results( -1497 self, payload: typedefs.JSONObject -1498 ) -> iterators.FlatIterator[entity.SearchableEntity]: -1499 suggested_words: list[str] = payload["suggestedWords"] -1500 -1501 def _check_unknown(s: str) -> undefined.UndefinedOr[str]: -1502 return s if not typedefs.is_unknown(s) else undefined.Undefined -1503 -1504 return iterators.FlatIterator( -1505 [ -1506 entity.SearchableEntity( -1507 net=self._net, -1508 hash=data["hash"], -1509 entity_type=data["entityType"], -1510 weight=data["weight"], -1511 suggested_words=suggested_words, -1512 name=data["displayProperties"]["name"], -1513 has_icon=data["displayProperties"]["hasIcon"], -1514 description=_check_unknown( -1515 data["displayProperties"]["description"] -1516 ), -1517 icon=assets.Image(data["displayProperties"]["icon"]), -1518 ) -1519 for data in payload["results"]["results"] -1520 ] -1521 ) -1522 -1523 def _deserialize_inventory_item_objects( -1524 self, payload: typedefs.JSONObject -1525 ) -> entity.InventoryEntityObjects: -1526 return entity.InventoryEntityObjects( -1527 action=payload.get("action"), -1528 set_data=payload.get("setData"), -1529 stats=payload.get("stats"), -1530 equipping_block=payload.get("equippingBlock"), -1531 translation_block=payload.get("translationBlock"), -1532 preview=payload.get("preview"), -1533 quality=payload.get("quality"), -1534 value=payload.get("value"), -1535 source_data=payload.get("sourceData"), -1536 objectives=payload.get("objectives"), -1537 plug=payload.get("plug"), -1538 metrics=payload.get("metrics"), -1539 gearset=payload.get("gearset"), -1540 sack=payload.get("sack"), -1541 sockets=payload.get("sockets"), -1542 summary=payload.get("summary"), -1543 talent_gird=payload.get("talentGrid"), -1544 investments_stats=payload.get("investmentStats"), -1545 perks=payload.get("perks"), -1546 animations=payload.get("animations", []), -1547 links=payload.get("links", []), -1548 ) -1549 -1550 def deserialize_inventory_entity( # noqa: C901 Too complex. -1551 self, payload: typedefs.JSONObject, / -1552 ) -> entity.InventoryEntity: -1553 -1554 props = self._set_entity_attrs(payload) -1555 objects = self._deserialize_inventory_item_objects(payload) -1556 -1557 collectible_hash: typing.Optional[int] = None -1558 if raw_collectible_hash := payload.get("collectibleHash"): -1559 collectible_hash = int(raw_collectible_hash) -1560 -1561 secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.Undefined -1562 if raw_second_icon := payload.get("secondaryIcon"): -1563 secondary_icon = assets.Image(raw_second_icon) -1564 -1565 secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.Undefined -1566 if raw_second_overlay := payload.get("secondaryOverlay"): -1567 secondary_overlay = assets.Image(raw_second_overlay) -1568 -1569 secondary_special: undefined.UndefinedOr[assets.Image] = undefined.Undefined -1570 if raw_second_special := payload.get("secondarySpecial"): -1571 secondary_special = assets.Image(raw_second_special) -1572 -1573 screenshot: undefined.UndefinedOr[assets.Image] = undefined.Undefined -1574 if raw_screenshot := payload.get("screenshot"): -1575 screenshot = assets.Image(raw_screenshot) -1576 -1577 watermark_icon: typing.Optional[assets.Image] = None -1578 if raw_watermark_icon := payload.get("iconWatermark"): -1579 watermark_icon = assets.Image(raw_watermark_icon) -1580 -1581 watermark_shelved: typing.Optional[assets.Image] = None -1582 if raw_watermark_shelved := payload.get("iconWatermarkShelved"): -1583 watermark_shelved = assets.Image(raw_watermark_shelved) +1421 character_records: typing.Optional[ +1422 collections.Mapping[int, records.CharacterRecord] +1423 ] = None +1424 if raw_char_records := payload.get("records"): +1425 character_records = self.deserialize_characters_records( +1426 raw_char_records["data"] +1427 ) +1428 +1429 item_components: typing.Optional[components.ItemsComponent] = None +1430 if raw_item_components := payload.get("itemComponents"): +1431 item_components = self.deserialize_items_component(raw_item_components) +1432 +1433 nodes: typing.Optional[collections.Mapping[int, records.Node]] = None +1434 if raw_nodes := payload.get("presentationNodes"): +1435 nodes = { +1436 int(node_hash): self._deserialize_node(node) +1437 for node_hash, node in raw_nodes["data"]["nodes"].items() +1438 } +1439 +1440 collectibles: typing.Optional[items.Collectible] = None +1441 if raw_collectibles := payload.get("collectibles"): +1442 collectibles = self._deserialize_collectible(raw_collectibles["data"]) +1443 +1444 currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None +1445 if raw_currencies := payload.get("currencyLookups"): +1446 if "data" in raw_currencies: +1447 currency_lookups = self._deserialize_currencies(raw_currencies) +1448 +1449 return components.CharacterComponent( +1450 activities=activities, +1451 equipment=equipment, +1452 inventory=inventory, +1453 progressions=progressions_, +1454 render_data=render_data, +1455 character=character_, +1456 character_records=character_records, +1457 profile_records=None, +1458 item_components=item_components, +1459 currency_lookups=currency_lookups, +1460 collectibles=collectibles, +1461 nodes=nodes, +1462 ) +1463 +1464 def _set_entity_attrs( +1465 self, payload: typedefs.JSONObject, *, key: str = "displayProperties" +1466 ) -> entity.Entity: +1467 +1468 name: undefined.UndefinedOr[str] = undefined.Undefined +1469 description: undefined.UndefinedOr[str] = undefined.Undefined +1470 +1471 if properties := payload[key]: +1472 if (raw_name := properties["name"]) is not typedefs.Unknown: +1473 name = raw_name +1474 +1475 if ( +1476 raw_description := properties["description"] +1477 ) and not typedefs.is_unknown(raw_description): +1478 description = raw_description +1479 +1480 return entity.Entity( +1481 net=self._net, +1482 hash=payload["hash"], +1483 index=payload["index"], +1484 name=name, +1485 description=description, +1486 has_icon=properties["hasIcon"], +1487 icon=assets.Image(properties["icon"] if "icon" in properties else None), +1488 ) +1489 +1490 def deserialize_inventory_results( +1491 self, payload: typedefs.JSONObject +1492 ) -> iterators.Iterator[entity.SearchableEntity]: +1493 suggested_words: list[str] = payload["suggestedWords"] +1494 +1495 def _check_unknown(s: str) -> undefined.UndefinedOr[str]: +1496 return s if not typedefs.is_unknown(s) else undefined.Undefined +1497 +1498 return iterators.Iterator( +1499 [ +1500 entity.SearchableEntity( +1501 net=self._net, +1502 hash=data["hash"], +1503 entity_type=data["entityType"], +1504 weight=data["weight"], +1505 suggested_words=suggested_words, +1506 name=data["displayProperties"]["name"], +1507 has_icon=data["displayProperties"]["hasIcon"], +1508 description=_check_unknown( +1509 data["displayProperties"]["description"] +1510 ), +1511 icon=assets.Image(data["displayProperties"]["icon"]), +1512 ) +1513 for data in payload["results"]["results"] +1514 ] +1515 ) +1516 +1517 def _deserialize_inventory_item_objects( +1518 self, payload: typedefs.JSONObject +1519 ) -> entity.InventoryEntityObjects: +1520 return entity.InventoryEntityObjects( +1521 action=payload.get("action"), +1522 set_data=payload.get("setData"), +1523 stats=payload.get("stats"), +1524 equipping_block=payload.get("equippingBlock"), +1525 translation_block=payload.get("translationBlock"), +1526 preview=payload.get("preview"), +1527 quality=payload.get("quality"), +1528 value=payload.get("value"), +1529 source_data=payload.get("sourceData"), +1530 objectives=payload.get("objectives"), +1531 plug=payload.get("plug"), +1532 metrics=payload.get("metrics"), +1533 gearset=payload.get("gearset"), +1534 sack=payload.get("sack"), +1535 sockets=payload.get("sockets"), +1536 summary=payload.get("summary"), +1537 talent_gird=payload.get("talentGrid"), +1538 investments_stats=payload.get("investmentStats"), +1539 perks=payload.get("perks"), +1540 animations=payload.get("animations", []), +1541 links=payload.get("links", []), +1542 ) +1543 +1544 def deserialize_inventory_entity( # noqa: C901 Too complex. +1545 self, payload: typedefs.JSONObject, / +1546 ) -> entity.InventoryEntity: +1547 +1548 props = self._set_entity_attrs(payload) +1549 objects = self._deserialize_inventory_item_objects(payload) +1550 +1551 collectible_hash: typing.Optional[int] = None +1552 if raw_collectible_hash := payload.get("collectibleHash"): +1553 collectible_hash = int(raw_collectible_hash) +1554 +1555 secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.Undefined +1556 if raw_second_icon := payload.get("secondaryIcon"): +1557 secondary_icon = assets.Image(raw_second_icon) +1558 +1559 secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.Undefined +1560 if raw_second_overlay := payload.get("secondaryOverlay"): +1561 secondary_overlay = assets.Image(raw_second_overlay) +1562 +1563 secondary_special: undefined.UndefinedOr[assets.Image] = undefined.Undefined +1564 if raw_second_special := payload.get("secondarySpecial"): +1565 secondary_special = assets.Image(raw_second_special) +1566 +1567 screenshot: undefined.UndefinedOr[assets.Image] = undefined.Undefined +1568 if raw_screenshot := payload.get("screenshot"): +1569 screenshot = assets.Image(raw_screenshot) +1570 +1571 watermark_icon: typing.Optional[assets.Image] = None +1572 if raw_watermark_icon := payload.get("iconWatermark"): +1573 watermark_icon = assets.Image(raw_watermark_icon) +1574 +1575 watermark_shelved: typing.Optional[assets.Image] = None +1576 if raw_watermark_shelved := payload.get("iconWatermarkShelved"): +1577 watermark_shelved = assets.Image(raw_watermark_shelved) +1578 +1579 about: undefined.UndefinedOr[str] = undefined.Undefined +1580 if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown( +1581 raw_about +1582 ): +1583 about = raw_about 1584 -1585 about: undefined.UndefinedOr[str] = undefined.Undefined -1586 if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown( -1587 raw_about -1588 ): -1589 about = raw_about +1585 ui_item_style: undefined.UndefinedOr[str] = undefined.Undefined +1586 if ( +1587 raw_ui_style := payload.get("uiItemDisplayStyle") +1588 ) and not typedefs.is_unknown(raw_ui_style): +1589 ui_item_style = raw_ui_style 1590 -1591 ui_item_style: undefined.UndefinedOr[str] = undefined.Undefined +1591 tier_and_name: undefined.UndefinedOr[str] = undefined.Undefined 1592 if ( -1593 raw_ui_style := payload.get("uiItemDisplayStyle") -1594 ) and not typedefs.is_unknown(raw_ui_style): -1595 ui_item_style = raw_ui_style +1593 raw_tier_and_name := payload.get("itemTypeAndTierDisplayName") +1594 ) and not typedefs.is_unknown(raw_tier_and_name): +1595 tier_and_name = raw_tier_and_name 1596 -1597 tier_and_name: undefined.UndefinedOr[str] = undefined.Undefined +1597 type_name: undefined.UndefinedOr[str] = undefined.Undefined 1598 if ( -1599 raw_tier_and_name := payload.get("itemTypeAndTierDisplayName") -1600 ) and not typedefs.is_unknown(raw_tier_and_name): -1601 tier_and_name = raw_tier_and_name +1599 raw_type_name := payload.get("itemTypeDisplayName") +1600 ) and not typedefs.is_unknown(raw_type_name): +1601 type_name = raw_type_name 1602 -1603 type_name: undefined.UndefinedOr[str] = undefined.Undefined +1603 display_source: undefined.UndefinedOr[str] = undefined.Undefined 1604 if ( -1605 raw_type_name := payload.get("itemTypeDisplayName") -1606 ) and not typedefs.is_unknown(raw_type_name): -1607 type_name = raw_type_name +1605 raw_display_source := payload.get("displaySource") +1606 ) and not typedefs.is_unknown(raw_display_source): +1607 display_source = raw_display_source 1608 -1609 display_source: undefined.UndefinedOr[str] = undefined.Undefined -1610 if ( -1611 raw_display_source := payload.get("displaySource") -1612 ) and not typedefs.is_unknown(raw_display_source): -1613 display_source = raw_display_source -1614 -1615 lorehash: typing.Optional[int] = None -1616 if raw_lore_hash := payload.get("loreHash"): -1617 lorehash = int(raw_lore_hash) -1618 -1619 summary_hash: typing.Optional[int] = None -1620 if raw_summary_hash := payload.get("summaryItemHash"): -1621 summary_hash = raw_summary_hash -1622 -1623 breaker_type_hash: typing.Optional[int] = None -1624 if raw_breaker_type_hash := payload.get("breakerTypeHash"): -1625 breaker_type_hash = int(raw_breaker_type_hash) -1626 -1627 damage_types: typing.Optional[collections.Sequence[int]] = None -1628 if raw_damage_types := payload.get("damageTypes"): -1629 damage_types = [int(type_) for type_ in raw_damage_types] -1630 -1631 damagetype_hashes: typing.Optional[collections.Sequence[int]] = None -1632 if raw_damagetype_hashes := payload.get("damageTypeHashes"): -1633 damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes] -1634 -1635 default_damagetype_hash: typing.Optional[int] = None -1636 if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"): -1637 default_damagetype_hash = int(raw_defaultdmg_hash) -1638 -1639 emblem_objective_hash: typing.Optional[int] = None -1640 if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"): -1641 emblem_objective_hash = int(raw_emblem_obj_hash) -1642 -1643 tier_type: typing.Optional[enums.TierType] = None -1644 tier: typing.Optional[enums.ItemTier] = None -1645 bucket_hash: typing.Optional[int] = None -1646 recovery_hash: typing.Optional[int] = None -1647 tier_name: undefined.UndefinedOr[str] = undefined.Undefined -1648 isinstance_item: bool = False -1649 expire_tool_tip: undefined.UndefinedOr[str] = undefined.Undefined -1650 expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.Undefined -1651 suppress_expiration: bool = False -1652 max_stack_size: typing.Optional[int] = None -1653 stack_label: undefined.UndefinedOr[str] = undefined.Undefined -1654 -1655 if inventory := payload.get("inventory"): -1656 tier_type = enums.TierType(int(inventory["tierType"])) -1657 tier = enums.ItemTier(int(inventory["tierTypeHash"])) -1658 bucket_hash = int(inventory["bucketTypeHash"]) -1659 recovery_hash = int(inventory["recoveryBucketTypeHash"]) -1660 tier_name = inventory["tierTypeName"] -1661 isinstance_item = inventory["isInstanceItem"] -1662 suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"] -1663 max_stack_size = int(inventory["maxStackSize"]) -1664 -1665 try: -1666 stack_label = inventory["stackUniqueLabel"] -1667 except KeyError: -1668 pass -1669 -1670 return entity.InventoryEntity( -1671 net=self._net, -1672 collectible_hash=collectible_hash, -1673 name=props.name, -1674 about=about, -1675 emblem_objective_hash=emblem_objective_hash, -1676 suppress_expiration=suppress_expiration, -1677 max_stack_size=max_stack_size, -1678 stack_label=stack_label, -1679 tier=tier, -1680 tier_type=tier_type, -1681 tier_name=tier_name, -1682 bucket_hash=bucket_hash, -1683 recovery_bucket_hash=recovery_hash, -1684 isinstance_item=isinstance_item, -1685 expire_in_orbit_message=expire_in_orbit_message, -1686 expiration_tooltip=expire_tool_tip, -1687 lore_hash=lorehash, -1688 type_and_tier_name=tier_and_name, -1689 summary_hash=summary_hash, -1690 ui_display_style=ui_item_style, -1691 type_name=type_name, -1692 breaker_type_hash=breaker_type_hash, -1693 description=props.description, -1694 display_source=display_source, -1695 hash=props.hash, -1696 damage_types=damage_types, -1697 index=props.index, -1698 icon=props.icon, -1699 has_icon=props.has_icon, -1700 screenshot=screenshot, -1701 watermark_icon=watermark_icon, -1702 watermark_shelved=watermark_shelved, -1703 secondary_icon=secondary_icon, -1704 secondary_overlay=secondary_overlay, -1705 secondary_special=secondary_special, -1706 type=enums.ItemType(int(payload["itemType"])), -1707 trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])], -1708 trait_ids=[trait for trait in payload.get("traitIds", [])], -1709 category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]], -1710 item_class=enums.Class(int(payload["classType"])), -1711 sub_type=enums.ItemSubType(int(payload["itemSubType"])), -1712 breaker_type=int(payload["breakerType"]), -1713 default_damagetype=int(payload["defaultDamageType"]), -1714 default_damagetype_hash=default_damagetype_hash, -1715 damagetype_hashes=damagetype_hashes, -1716 tooltip_notifications=payload["tooltipNotifications"], -1717 not_transferable=payload["nonTransferrable"], -1718 allow_actions=payload["allowActions"], -1719 is_equippable=payload["equippable"], -1720 objects=objects, -1721 background_colors=payload.get("backgroundColor", {}), -1722 season_hash=payload.get("seasonHash"), -1723 has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"], -1724 ) -1725 -1726 def deserialize_objective_entity( -1727 self, payload: typedefs.JSONObject, / -1728 ) -> entity.ObjectiveEntity: -1729 props = self._set_entity_attrs(payload) -1730 return entity.ObjectiveEntity( -1731 net=self._net, -1732 hash=props.hash, -1733 index=props.index, -1734 description=props.description, -1735 name=props.name, -1736 has_icon=props.has_icon, -1737 icon=props.icon, -1738 unlock_value_hash=payload["unlockValueHash"], -1739 completion_value=payload["completionValue"], -1740 scope=entity.GatingScope(int(payload["scope"])), -1741 location_hash=payload["locationHash"], -1742 allowed_negative_value=payload["allowNegativeValue"], -1743 allowed_value_change=payload["allowValueChangeWhenCompleted"], -1744 counting_downward=payload["isCountingDownward"], -1745 value_style=entity.ValueUIStyle(int(payload["valueStyle"])), -1746 progress_description=payload["progressDescription"], -1747 perks=payload["perks"], -1748 stats=payload["stats"], -1749 minimum_visibility=payload["minimumVisibilityThreshold"], -1750 allow_over_completion=payload["allowOvercompletion"], -1751 show_value_style=payload["showValueOnComplete"], -1752 display_only_objective=payload["isDisplayOnlyObjective"], -1753 complete_value_style=entity.ValueUIStyle( -1754 int(payload["completedValueStyle"]) -1755 ), -1756 progress_value_style=entity.ValueUIStyle( -1757 int(payload["inProgressValueStyle"]) -1758 ), -1759 ui_label=payload["uiLabel"], -1760 ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])), -1761 ) -1762 -1763 def _deserialize_activity_values( -1764 self, payload: typedefs.JSONObject, / -1765 ) -> activity.ActivityValues: -1766 team: typing.Optional[int] = None -1767 if raw_team := payload.get("team"): -1768 team = raw_team["basic"]["value"] -1769 return activity.ActivityValues( -1770 assists=payload["assists"]["basic"]["value"], -1771 deaths=payload["deaths"]["basic"]["value"], -1772 kills=payload["kills"]["basic"]["value"], -1773 is_completed=bool(payload["completed"]["basic"]["value"]), -1774 opponents_defeated=payload["opponentsDefeated"]["basic"]["value"], -1775 efficiency=payload["efficiency"]["basic"]["value"], -1776 kd_ratio=payload["killsDeathsRatio"]["basic"]["value"], -1777 kd_assists=payload["killsDeathsAssists"]["basic"]["value"], -1778 score=payload["score"]["basic"]["value"], -1779 duration=payload["activityDurationSeconds"]["basic"]["displayValue"], -1780 team=team, -1781 completion_reason=payload["completionReason"]["basic"]["displayValue"], -1782 fireteam_id=payload["fireteamId"]["basic"]["value"], -1783 start_seconds=payload["startSeconds"]["basic"]["value"], -1784 played_time=payload["timePlayedSeconds"]["basic"]["displayValue"], -1785 player_count=payload["playerCount"]["basic"]["value"], -1786 team_score=payload["teamScore"]["basic"]["value"], -1787 ) -1788 -1789 def deserialize_activity( -1790 self, -1791 payload: typedefs.JSONObject, -1792 /, -1793 ) -> activity.Activity: -1794 period = time.clean_date(payload["period"]) -1795 details = payload["activityDetails"] -1796 ref_id = int(details["referenceId"]) -1797 instance_id = int(details["instanceId"]) -1798 mode = enums.GameMode(details["mode"]) -1799 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] -1800 is_private = details["isPrivate"] -1801 membership_type = enums.MembershipType(int(details["membershipType"])) -1802 -1803 # Since we're using the same fields for post activity method -1804 # this check is required since post activity doesn't values values -1805 values = self._deserialize_activity_values(payload["values"]) -1806 -1807 return activity.Activity( -1808 net=self._net, -1809 hash=ref_id, -1810 instance_id=instance_id, -1811 mode=mode, -1812 modes=modes, -1813 is_private=is_private, -1814 membership_type=membership_type, -1815 occurred_at=period, -1816 values=values, -1817 ) -1818 -1819 def deserialize_activities( -1820 self, payload: typedefs.JSONObject -1821 ) -> iterators.FlatIterator[activity.Activity]: -1822 return iterators.FlatIterator( -1823 [ -1824 self.deserialize_activity(activity_) -1825 for activity_ in payload["activities"] -1826 ] -1827 ) -1828 -1829 def deserialize_extended_weapon_values( -1830 self, payload: typedefs.JSONObject -1831 ) -> activity.ExtendedWeaponValues: -1832 -1833 assists: typing.Optional[int] = None -1834 if raw_assists := payload["values"].get("uniqueWeaponAssists"): -1835 assists = raw_assists["basic"]["value"] -1836 assists_damage: typing.Optional[int] = None -1837 -1838 if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"): -1839 assists_damage = raw_assists_damage["basic"]["value"] -1840 -1841 return activity.ExtendedWeaponValues( -1842 reference_id=int(payload["referenceId"]), -1843 kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"], -1844 precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][ -1845 "value" -1846 ], -1847 assists=assists, -1848 assists_damage=assists_damage, -1849 precision_kills_percentage=( -1850 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"], -1851 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][ -1852 "displayValue" -1853 ], -1854 ), -1855 ) -1856 -1857 def _deserialize_extended_values( -1858 self, payload: typedefs.JSONObject -1859 ) -> activity.ExtendedValues: -1860 weapons: typing.Optional[ -1861 collections.Collection[activity.ExtendedWeaponValues] -1862 ] = None -1863 -1864 if raw_weapons := payload.get("weapons"): -1865 weapons = [ -1866 self.deserialize_extended_weapon_values(value) for value in raw_weapons -1867 ] -1868 -1869 return activity.ExtendedValues( -1870 precision_kills=payload["values"]["precisionKills"]["basic"]["value"], -1871 grenade_kills=payload["values"]["weaponKillsGrenade"]["basic"]["value"], -1872 melee_kills=payload["values"]["weaponKillsMelee"]["basic"]["value"], -1873 super_kills=payload["values"]["weaponKillsSuper"]["basic"]["value"], -1874 ability_kills=payload["values"]["weaponKillsAbility"]["basic"]["value"], -1875 weapons=weapons, -1876 ) -1877 -1878 def deserialize_post_activity_player( -1879 self, payload: typedefs.JSONObject, / -1880 ) -> activity.PostActivityPlayer: -1881 player = payload["player"] -1882 -1883 class_hash: typedefs.NoneOr[int] = None -1884 if (class_hash := player.get("classHash")) is not None: -1885 class_hash = class_hash -1886 -1887 race_hash: typedefs.NoneOr[int] = None -1888 if (race_hash := player.get("raceHash")) is not None: -1889 race_hash = race_hash -1890 -1891 gender_hash: typedefs.NoneOr[int] = None -1892 if (gender_hash := player.get("genderHash")) is not None: -1893 gender_hash = gender_hash +1609 lorehash: typing.Optional[int] = None +1610 if raw_lore_hash := payload.get("loreHash"): +1611 lorehash = int(raw_lore_hash) +1612 +1613 summary_hash: typing.Optional[int] = None +1614 if raw_summary_hash := payload.get("summaryItemHash"): +1615 summary_hash = raw_summary_hash +1616 +1617 breaker_type_hash: typing.Optional[int] = None +1618 if raw_breaker_type_hash := payload.get("breakerTypeHash"): +1619 breaker_type_hash = int(raw_breaker_type_hash) +1620 +1621 damage_types: typing.Optional[collections.Sequence[int]] = None +1622 if raw_damage_types := payload.get("damageTypes"): +1623 damage_types = [int(type_) for type_ in raw_damage_types] +1624 +1625 damagetype_hashes: typing.Optional[collections.Sequence[int]] = None +1626 if raw_damagetype_hashes := payload.get("damageTypeHashes"): +1627 damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes] +1628 +1629 default_damagetype_hash: typing.Optional[int] = None +1630 if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"): +1631 default_damagetype_hash = int(raw_defaultdmg_hash) +1632 +1633 emblem_objective_hash: typing.Optional[int] = None +1634 if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"): +1635 emblem_objective_hash = int(raw_emblem_obj_hash) +1636 +1637 tier_type: typing.Optional[enums.TierType] = None +1638 tier: typing.Optional[enums.ItemTier] = None +1639 bucket_hash: typing.Optional[int] = None +1640 recovery_hash: typing.Optional[int] = None +1641 tier_name: undefined.UndefinedOr[str] = undefined.Undefined +1642 isinstance_item: bool = False +1643 expire_tool_tip: undefined.UndefinedOr[str] = undefined.Undefined +1644 expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.Undefined +1645 suppress_expiration: bool = False +1646 max_stack_size: typing.Optional[int] = None +1647 stack_label: undefined.UndefinedOr[str] = undefined.Undefined +1648 +1649 if inventory := payload.get("inventory"): +1650 tier_type = enums.TierType(int(inventory["tierType"])) +1651 tier = enums.ItemTier(int(inventory["tierTypeHash"])) +1652 bucket_hash = int(inventory["bucketTypeHash"]) +1653 recovery_hash = int(inventory["recoveryBucketTypeHash"]) +1654 tier_name = inventory["tierTypeName"] +1655 isinstance_item = inventory["isInstanceItem"] +1656 suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"] +1657 max_stack_size = int(inventory["maxStackSize"]) +1658 +1659 try: +1660 stack_label = inventory["stackUniqueLabel"] +1661 except KeyError: +1662 pass +1663 +1664 return entity.InventoryEntity( +1665 net=self._net, +1666 collectible_hash=collectible_hash, +1667 name=props.name, +1668 about=about, +1669 emblem_objective_hash=emblem_objective_hash, +1670 suppress_expiration=suppress_expiration, +1671 max_stack_size=max_stack_size, +1672 stack_label=stack_label, +1673 tier=tier, +1674 tier_type=tier_type, +1675 tier_name=tier_name, +1676 bucket_hash=bucket_hash, +1677 recovery_bucket_hash=recovery_hash, +1678 isinstance_item=isinstance_item, +1679 expire_in_orbit_message=expire_in_orbit_message, +1680 expiration_tooltip=expire_tool_tip, +1681 lore_hash=lorehash, +1682 type_and_tier_name=tier_and_name, +1683 summary_hash=summary_hash, +1684 ui_display_style=ui_item_style, +1685 type_name=type_name, +1686 breaker_type_hash=breaker_type_hash, +1687 description=props.description, +1688 display_source=display_source, +1689 hash=props.hash, +1690 damage_types=damage_types, +1691 index=props.index, +1692 icon=props.icon, +1693 has_icon=props.has_icon, +1694 screenshot=screenshot, +1695 watermark_icon=watermark_icon, +1696 watermark_shelved=watermark_shelved, +1697 secondary_icon=secondary_icon, +1698 secondary_overlay=secondary_overlay, +1699 secondary_special=secondary_special, +1700 type=enums.ItemType(int(payload["itemType"])), +1701 trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])], +1702 trait_ids=[trait for trait in payload.get("traitIds", [])], +1703 category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]], +1704 item_class=enums.Class(int(payload["classType"])), +1705 sub_type=enums.ItemSubType(int(payload["itemSubType"])), +1706 breaker_type=int(payload["breakerType"]), +1707 default_damagetype=int(payload["defaultDamageType"]), +1708 default_damagetype_hash=default_damagetype_hash, +1709 damagetype_hashes=damagetype_hashes, +1710 tooltip_notifications=payload["tooltipNotifications"], +1711 not_transferable=payload["nonTransferrable"], +1712 allow_actions=payload["allowActions"], +1713 is_equippable=payload["equippable"], +1714 objects=objects, +1715 background_colors=payload.get("backgroundColor", {}), +1716 season_hash=payload.get("seasonHash"), +1717 has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"], +1718 ) +1719 +1720 def deserialize_objective_entity( +1721 self, payload: typedefs.JSONObject, / +1722 ) -> entity.ObjectiveEntity: +1723 props = self._set_entity_attrs(payload) +1724 return entity.ObjectiveEntity( +1725 net=self._net, +1726 hash=props.hash, +1727 index=props.index, +1728 description=props.description, +1729 name=props.name, +1730 has_icon=props.has_icon, +1731 icon=props.icon, +1732 unlock_value_hash=payload["unlockValueHash"], +1733 completion_value=payload["completionValue"], +1734 scope=entity.GatingScope(int(payload["scope"])), +1735 location_hash=payload["locationHash"], +1736 allowed_negative_value=payload["allowNegativeValue"], +1737 allowed_value_change=payload["allowValueChangeWhenCompleted"], +1738 counting_downward=payload["isCountingDownward"], +1739 value_style=entity.ValueUIStyle(int(payload["valueStyle"])), +1740 progress_description=payload["progressDescription"], +1741 perks=payload["perks"], +1742 stats=payload["stats"], +1743 minimum_visibility=payload["minimumVisibilityThreshold"], +1744 allow_over_completion=payload["allowOvercompletion"], +1745 show_value_style=payload["showValueOnComplete"], +1746 display_only_objective=payload["isDisplayOnlyObjective"], +1747 complete_value_style=entity.ValueUIStyle( +1748 int(payload["completedValueStyle"]) +1749 ), +1750 progress_value_style=entity.ValueUIStyle( +1751 int(payload["inProgressValueStyle"]) +1752 ), +1753 ui_label=payload["uiLabel"], +1754 ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])), +1755 ) +1756 +1757 def _deserialize_activity_values( +1758 self, payload: typedefs.JSONObject, / +1759 ) -> activity.ActivityValues: +1760 team: typing.Optional[int] = None +1761 if raw_team := payload.get("team"): +1762 team = raw_team["basic"]["value"] +1763 return activity.ActivityValues( +1764 assists=payload["assists"]["basic"]["value"], +1765 deaths=payload["deaths"]["basic"]["value"], +1766 kills=payload["kills"]["basic"]["value"], +1767 is_completed=bool(payload["completed"]["basic"]["value"]), +1768 opponents_defeated=payload["opponentsDefeated"]["basic"]["value"], +1769 efficiency=payload["efficiency"]["basic"]["value"], +1770 kd_ratio=payload["killsDeathsRatio"]["basic"]["value"], +1771 kd_assists=payload["killsDeathsAssists"]["basic"]["value"], +1772 score=payload["score"]["basic"]["value"], +1773 duration=payload["activityDurationSeconds"]["basic"]["displayValue"], +1774 team=team, +1775 completion_reason=payload["completionReason"]["basic"]["displayValue"], +1776 fireteam_id=payload["fireteamId"]["basic"]["value"], +1777 start_seconds=payload["startSeconds"]["basic"]["value"], +1778 played_time=payload["timePlayedSeconds"]["basic"]["displayValue"], +1779 player_count=payload["playerCount"]["basic"]["value"], +1780 team_score=payload["teamScore"]["basic"]["value"], +1781 ) +1782 +1783 def deserialize_activity( +1784 self, +1785 payload: typedefs.JSONObject, +1786 /, +1787 ) -> activity.Activity: +1788 period = time.clean_date(payload["period"]) +1789 details = payload["activityDetails"] +1790 ref_id = int(details["referenceId"]) +1791 instance_id = int(details["instanceId"]) +1792 mode = enums.GameMode(details["mode"]) +1793 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] +1794 is_private = details["isPrivate"] +1795 membership_type = enums.MembershipType(int(details["membershipType"])) +1796 +1797 # Since we're using the same fields for post activity method +1798 # this check is required since post activity doesn't values values +1799 values = self._deserialize_activity_values(payload["values"]) +1800 +1801 return activity.Activity( +1802 net=self._net, +1803 hash=ref_id, +1804 instance_id=instance_id, +1805 mode=mode, +1806 modes=modes, +1807 is_private=is_private, +1808 membership_type=membership_type, +1809 occurred_at=period, +1810 values=values, +1811 ) +1812 +1813 def deserialize_activities( +1814 self, payload: typedefs.JSONObject +1815 ) -> iterators.Iterator[activity.Activity]: +1816 return iterators.Iterator( +1817 [ +1818 self.deserialize_activity(activity_) +1819 for activity_ in payload["activities"] +1820 ] +1821 ) +1822 +1823 def deserialize_extended_weapon_values( +1824 self, payload: typedefs.JSONObject +1825 ) -> activity.ExtendedWeaponValues: +1826 +1827 assists: typing.Optional[int] = None +1828 if raw_assists := payload["values"].get("uniqueWeaponAssists"): +1829 assists = raw_assists["basic"]["value"] +1830 assists_damage: typing.Optional[int] = None +1831 +1832 if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"): +1833 assists_damage = raw_assists_damage["basic"]["value"] +1834 +1835 return activity.ExtendedWeaponValues( +1836 reference_id=int(payload["referenceId"]), +1837 kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"], +1838 precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][ +1839 "value" +1840 ], +1841 assists=assists, +1842 assists_damage=assists_damage, +1843 precision_kills_percentage=( +1844 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"], +1845 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][ +1846 "displayValue" +1847 ], +1848 ), +1849 ) +1850 +1851 def _deserialize_extended_values( +1852 self, payload: typedefs.JSONObject +1853 ) -> activity.ExtendedValues: +1854 weapons: typing.Optional[ +1855 collections.Collection[activity.ExtendedWeaponValues] +1856 ] = None +1857 +1858 if raw_weapons := payload.get("weapons"): +1859 weapons = [ +1860 self.deserialize_extended_weapon_values(value) for value in raw_weapons +1861 ] +1862 +1863 return activity.ExtendedValues( +1864 precision_kills=payload["values"]["precisionKills"]["basic"]["value"], +1865 grenade_kills=payload["values"]["weaponKillsGrenade"]["basic"]["value"], +1866 melee_kills=payload["values"]["weaponKillsMelee"]["basic"]["value"], +1867 super_kills=payload["values"]["weaponKillsSuper"]["basic"]["value"], +1868 ability_kills=payload["values"]["weaponKillsAbility"]["basic"]["value"], +1869 weapons=weapons, +1870 ) +1871 +1872 def deserialize_post_activity_player( +1873 self, payload: typedefs.JSONObject, / +1874 ) -> activity.PostActivityPlayer: +1875 player = payload["player"] +1876 +1877 class_hash: typedefs.NoneOr[int] = None +1878 if (class_hash := player.get("classHash")) is not None: +1879 class_hash = class_hash +1880 +1881 race_hash: typedefs.NoneOr[int] = None +1882 if (race_hash := player.get("raceHash")) is not None: +1883 race_hash = race_hash +1884 +1885 gender_hash: typedefs.NoneOr[int] = None +1886 if (gender_hash := player.get("genderHash")) is not None: +1887 gender_hash = gender_hash +1888 +1889 character_class: undefined.UndefinedOr[str] = undefined.Undefined +1890 if ( +1891 character_class := player.get("characterClass") +1892 ) and not typedefs.is_unknown(character_class): +1893 character_class = character_class 1894 -1895 character_class: undefined.UndefinedOr[str] = undefined.Undefined -1896 if ( -1897 character_class := player.get("characterClass") -1898 ) and not typedefs.is_unknown(character_class): -1899 character_class = character_class -1900 -1901 character_level: typedefs.NoneOr[int] = None -1902 if (character_level := player.get("characterLevel")) is not None: -1903 character_level = character_level -1904 -1905 return activity.PostActivityPlayer( -1906 standing=int(payload["standing"]), -1907 score=int(payload["score"]["basic"]["value"]), -1908 character_id=payload["characterId"], -1909 destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]), -1910 character_class=character_class, -1911 character_level=character_level, -1912 race_hash=race_hash, -1913 gender_hash=gender_hash, -1914 class_hash=class_hash, -1915 light_level=int(player["lightLevel"]), -1916 emblem_hash=int(player["emblemHash"]), -1917 values=self._deserialize_activity_values(payload["values"]), -1918 extended_values=self._deserialize_extended_values(payload["extended"]), -1919 ) -1920 -1921 def _deserialize_post_activity_team( -1922 self, payload: typedefs.JSONObject -1923 ) -> activity.PostActivityTeam: -1924 return activity.PostActivityTeam( -1925 id=payload["teamId"], -1926 is_defeated=bool(payload["standing"]["basic"]["value"]), -1927 score=int(payload["score"]["basic"]["value"]), -1928 name=payload["teamName"], -1929 ) -1930 -1931 def deserialize_post_activity( -1932 self, payload: typedefs.JSONObject -1933 ) -> activity.PostActivity: -1934 period = time.clean_date(payload["period"]) -1935 details = payload["activityDetails"] -1936 ref_id = int(details["referenceId"]) -1937 instance_id = int(details["instanceId"]) -1938 mode = enums.GameMode(details["mode"]) -1939 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] -1940 is_private = details["isPrivate"] -1941 membership_type = enums.MembershipType(int(details["membershipType"])) -1942 return activity.PostActivity( -1943 net=self._net, -1944 hash=ref_id, -1945 membership_type=membership_type, -1946 instance_id=instance_id, -1947 mode=mode, -1948 modes=modes, -1949 is_private=is_private, -1950 occurred_at=period, -1951 starting_phase=int(payload["startingPhaseIndex"]), -1952 players=[ -1953 self.deserialize_post_activity_player(player) -1954 for player in payload["entries"] -1955 ], -1956 teams=[ -1957 self._deserialize_post_activity_team(team) for team in payload["teams"] -1958 ], -1959 ) +1895 character_level: typedefs.NoneOr[int] = None +1896 if (character_level := player.get("characterLevel")) is not None: +1897 character_level = character_level +1898 +1899 return activity.PostActivityPlayer( +1900 standing=int(payload["standing"]), +1901 score=int(payload["score"]["basic"]["value"]), +1902 character_id=payload["characterId"], +1903 destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]), +1904 character_class=character_class, +1905 character_level=character_level, +1906 race_hash=race_hash, +1907 gender_hash=gender_hash, +1908 class_hash=class_hash, +1909 light_level=int(player["lightLevel"]), +1910 emblem_hash=int(player["emblemHash"]), +1911 values=self._deserialize_activity_values(payload["values"]), +1912 extended_values=self._deserialize_extended_values(payload["extended"]), +1913 ) +1914 +1915 def _deserialize_post_activity_team( +1916 self, payload: typedefs.JSONObject +1917 ) -> activity.PostActivityTeam: +1918 return activity.PostActivityTeam( +1919 id=payload["teamId"], +1920 is_defeated=bool(payload["standing"]["basic"]["value"]), +1921 score=int(payload["score"]["basic"]["value"]), +1922 name=payload["teamName"], +1923 ) +1924 +1925 def deserialize_post_activity( +1926 self, payload: typedefs.JSONObject +1927 ) -> activity.PostActivity: +1928 period = time.clean_date(payload["period"]) +1929 details = payload["activityDetails"] +1930 ref_id = int(details["referenceId"]) +1931 instance_id = int(details["instanceId"]) +1932 mode = enums.GameMode(details["mode"]) +1933 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] +1934 is_private = details["isPrivate"] +1935 membership_type = enums.MembershipType(int(details["membershipType"])) +1936 return activity.PostActivity( +1937 net=self._net, +1938 hash=ref_id, +1939 membership_type=membership_type, +1940 instance_id=instance_id, +1941 mode=mode, +1942 modes=modes, +1943 is_private=is_private, +1944 occurred_at=period, +1945 starting_phase=int(payload["startingPhaseIndex"]), +1946 players=[ +1947 self.deserialize_post_activity_player(player) +1948 for player in payload["entries"] +1949 ], +1950 teams=[ +1951 self._deserialize_post_activity_team(team) for team in payload["teams"] +1952 ], +1953 ) +1954 +1955 def _deserialize_aggregated_activity_values( +1956 self, payload: typedefs.JSONObject +1957 ) -> activity.AggregatedActivityValues: +1958 # This ID is always the same for all aggregated values. +1959 activity_id = int(payload["fastestCompletionMsForActivity"]["activityId"]) 1960 -1961 def _deserialize_aggregated_activity_values( -1962 self, payload: typedefs.JSONObject -1963 ) -> activity.AggregatedActivityValues: -1964 # This ID is always the same for all aggregated values. -1965 activity_id = int(payload["fastestCompletionMsForActivity"]["activityId"]) -1966 -1967 return activity.AggregatedActivityValues( -1968 id=activity_id, -1969 fastest_completion_time=( -1970 int(payload["fastestCompletionMsForActivity"]["basic"]["value"]), -1971 payload["fastestCompletionMsForActivity"]["basic"]["displayValue"], -1972 ), -1973 completions=int(payload["activityCompletions"]["basic"]["value"]), -1974 kills=int(payload["activityKills"]["basic"]["value"]), -1975 deaths=int(payload["activityDeaths"]["basic"]["value"]), -1976 assists=int(payload["activityAssists"]["basic"]["value"]), -1977 seconds_played=( -1978 int(payload["activitySecondsPlayed"]["basic"]["value"]), -1979 payload["activitySecondsPlayed"]["basic"]["displayValue"], -1980 ), -1981 wins=int(payload["activityWins"]["basic"]["value"]), -1982 goals_missed=int(payload["activityGoalsMissed"]["basic"]["value"]), -1983 special_actions=int(payload["activitySpecialActions"]["basic"]["value"]), -1984 best_goals_hit=int(payload["activityBestGoalsHit"]["basic"]["value"]), -1985 best_single_score=int( -1986 payload["activityBestSingleGameScore"]["basic"]["value"] +1961 return activity.AggregatedActivityValues( +1962 id=activity_id, +1963 fastest_completion_time=( +1964 int(payload["fastestCompletionMsForActivity"]["basic"]["value"]), +1965 payload["fastestCompletionMsForActivity"]["basic"]["displayValue"], +1966 ), +1967 completions=int(payload["activityCompletions"]["basic"]["value"]), +1968 kills=int(payload["activityKills"]["basic"]["value"]), +1969 deaths=int(payload["activityDeaths"]["basic"]["value"]), +1970 assists=int(payload["activityAssists"]["basic"]["value"]), +1971 seconds_played=( +1972 int(payload["activitySecondsPlayed"]["basic"]["value"]), +1973 payload["activitySecondsPlayed"]["basic"]["displayValue"], +1974 ), +1975 wins=int(payload["activityWins"]["basic"]["value"]), +1976 goals_missed=int(payload["activityGoalsMissed"]["basic"]["value"]), +1977 special_actions=int(payload["activitySpecialActions"]["basic"]["value"]), +1978 best_goals_hit=int(payload["activityBestGoalsHit"]["basic"]["value"]), +1979 best_single_score=int( +1980 payload["activityBestSingleGameScore"]["basic"]["value"] +1981 ), +1982 goals_hit=int(payload["activityGoalsHit"]["basic"]["value"]), +1983 special_score=int(payload["activitySpecialScore"]["basic"]["value"]), +1984 kd_assists=int(payload["activityKillsDeathsAssists"]["basic"]["value"]), +1985 kd_ratio=float( +1986 payload["activityKillsDeathsAssists"]["basic"]["displayValue"] 1987 ), -1988 goals_hit=int(payload["activityGoalsHit"]["basic"]["value"]), -1989 special_score=int(payload["activitySpecialScore"]["basic"]["value"]), -1990 kd_assists=int(payload["activityKillsDeathsAssists"]["basic"]["value"]), -1991 kd_ratio=float( -1992 payload["activityKillsDeathsAssists"]["basic"]["displayValue"] -1993 ), -1994 precision_kills=int(payload["activityPrecisionKills"]["basic"]["value"]), -1995 ) -1996 -1997 def deserialize_aggregated_activity( -1998 self, payload: typedefs.JSONObject -1999 ) -> activity.AggregatedActivity: -2000 return activity.AggregatedActivity( -2001 hash=int(payload["activityHash"]), -2002 values=self._deserialize_aggregated_activity_values(payload["values"]), -2003 ) -2004 -2005 def deserialize_aggregated_activities( -2006 self, payload: typedefs.JSONObject -2007 ) -> iterators.FlatIterator[activity.AggregatedActivity]: -2008 return iterators.FlatIterator( -2009 [ -2010 self.deserialize_aggregated_activity(activity) -2011 for activity in payload["activities"] -2012 ] -2013 ) -2014 -2015 def deserialize_linked_profiles( -2016 self, payload: typedefs.JSONObject -2017 ) -> profile.LinkedProfile: -2018 bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"]) -2019 error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] -2020 profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] -2021 -2022 if raw_profile := payload.get("profiles"): -2023 for pfile in raw_profile: -2024 profiles_vec.append(self.deserialize_destiny_membership(pfile)) -2025 -2026 if raw_profiles_with_errors := payload.get("profilesWithErrors"): -2027 for raw_error_pfile in raw_profiles_with_errors: -2028 if error_pfile := raw_error_pfile.get("infoCard"): -2029 error_profiles_vec.append( -2030 self.deserialize_destiny_membership(error_pfile) -2031 ) -2032 -2033 return profile.LinkedProfile( -2034 net=self._net, -2035 bungie=bungie_user, -2036 profiles=profiles_vec, -2037 profiles_with_errors=error_profiles_vec, -2038 ) -2039 -2040 def deserialize_clan_banners( -2041 self, payload: typedefs.JSONObject -2042 ) -> collections.Sequence[clans.ClanBanner]: -2043 banners_seq: typing.MutableSequence[clans.ClanBanner] = [] -2044 if banners := payload.get("clanBannerDecals"): -2045 for k, v in banners.items(): -2046 banner_obj = clans.ClanBanner( -2047 id=int(k), -2048 foreground=assets.Image(v["foregroundPath"]), -2049 background=assets.Image(v["backgroundPath"]), -2050 ) -2051 banners_seq.append(banner_obj) -2052 return banners_seq -2053 -2054 def deserialize_public_milestone_content( -2055 self, payload: typedefs.JSONObject -2056 ) -> milestones.MilestoneContent: -2057 items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None -2058 if raw_categories := payload.get("itemCategories"): -2059 for item in raw_categories: -2060 title = undefined.Undefined -2061 if raw_title := item.get("title"): -2062 if raw_title != typedefs.Unknown: -2063 title = raw_title -2064 if raw_hashes := item.get("itemHashes"): -2065 hashes: collections.Sequence[int] = raw_hashes +1988 precision_kills=int(payload["activityPrecisionKills"]["basic"]["value"]), +1989 ) +1990 +1991 def deserialize_aggregated_activity( +1992 self, payload: typedefs.JSONObject +1993 ) -> activity.AggregatedActivity: +1994 return activity.AggregatedActivity( +1995 hash=int(payload["activityHash"]), +1996 values=self._deserialize_aggregated_activity_values(payload["values"]), +1997 ) +1998 +1999 def deserialize_aggregated_activities( +2000 self, payload: typedefs.JSONObject +2001 ) -> iterators.Iterator[activity.AggregatedActivity]: +2002 return iterators.Iterator( +2003 [ +2004 self.deserialize_aggregated_activity(activity) +2005 for activity in payload["activities"] +2006 ] +2007 ) +2008 +2009 def deserialize_linked_profiles( +2010 self, payload: typedefs.JSONObject +2011 ) -> profile.LinkedProfile: +2012 bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"]) +2013 error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] +2014 profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] +2015 +2016 if raw_profile := payload.get("profiles"): +2017 for pfile in raw_profile: +2018 profiles_vec.append(self.deserialize_destiny_membership(pfile)) +2019 +2020 if raw_profiles_with_errors := payload.get("profilesWithErrors"): +2021 for raw_error_pfile in raw_profiles_with_errors: +2022 if error_pfile := raw_error_pfile.get("infoCard"): +2023 error_profiles_vec.append( +2024 self.deserialize_destiny_membership(error_pfile) +2025 ) +2026 +2027 return profile.LinkedProfile( +2028 net=self._net, +2029 bungie=bungie_user, +2030 profiles=profiles_vec, +2031 profiles_with_errors=error_profiles_vec, +2032 ) +2033 +2034 def deserialize_clan_banners( +2035 self, payload: typedefs.JSONObject +2036 ) -> collections.Sequence[clans.ClanBanner]: +2037 banners_seq: typing.MutableSequence[clans.ClanBanner] = [] +2038 if banners := payload.get("clanBannerDecals"): +2039 for k, v in banners.items(): +2040 banner_obj = clans.ClanBanner( +2041 id=int(k), +2042 foreground=assets.Image(v["foregroundPath"]), +2043 background=assets.Image(v["backgroundPath"]), +2044 ) +2045 banners_seq.append(banner_obj) +2046 return banners_seq +2047 +2048 def deserialize_public_milestone_content( +2049 self, payload: typedefs.JSONObject +2050 ) -> milestones.MilestoneContent: +2051 items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None +2052 if raw_categories := payload.get("itemCategories"): +2053 for item in raw_categories: +2054 title = undefined.Undefined +2055 if raw_title := item.get("title"): +2056 if raw_title != typedefs.Unknown: +2057 title = raw_title +2058 if raw_hashes := item.get("itemHashes"): +2059 hashes: collections.Sequence[int] = raw_hashes +2060 +2061 items_categoris = milestones.MilestoneItems(title=title, hashes=hashes) +2062 +2063 about = undefined.Undefined +2064 if (raw_about := payload["about"]) != typedefs.Unknown: +2065 about = raw_about 2066 -2067 items_categoris = milestones.MilestoneItems(title=title, hashes=hashes) -2068 -2069 about = undefined.Undefined -2070 if (raw_about := payload["about"]) != typedefs.Unknown: -2071 about = raw_about -2072 -2073 status = undefined.Undefined -2074 if (raw_status := payload["status"]) != typedefs.Unknown: -2075 status = raw_status -2076 -2077 tips: typing.MutableSequence[undefined.UndefinedOr[str]] = [] -2078 if raw_tips := payload.get("tips"): -2079 for raw_tip in raw_tips: -2080 if raw_tip == typedefs.Unknown: -2081 raw_tip = undefined.Undefined -2082 tips.append(raw_tip) -2083 -2084 return milestones.MilestoneContent( -2085 about=about, status=status, tips=tips, items=items_categoris -2086 ) -2087 -2088 def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend: -2089 name = undefined.Undefined -2090 if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown: -2091 name = raw_name -2092 -2093 bungie_user: typedefs.NoneOr[user.BungieUser] = None -2094 -2095 if raw_bungie_user := payload.get("bungieNetUser"): -2096 bungie_user = self.deserialize_bungie_user(raw_bungie_user) -2097 -2098 return friends.Friend( -2099 net=self._net, -2100 id=int(payload["lastSeenAsMembershipId"]), -2101 name=name, -2102 code=payload.get("bungieGlobalDisplayNameCode"), -2103 relationship=enums.Relationship(payload["relationship"]), -2104 user=bungie_user, -2105 online_status=enums.Presence(payload["onlineStatus"]), -2106 online_title=payload["onlineTitle"], -2107 type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]), -2108 ) -2109 -2110 def deserialize_friends( -2111 self, payload: typedefs.JSONObject -2112 ) -> collections.Sequence[friends.Friend]: -2113 mut_seq: typing.MutableSequence[friends.Friend] = [] -2114 if raw_friends := payload.get("friends"): -2115 for friend in raw_friends: -2116 mut_seq.append(self.deserialize_friend(friend)) -2117 return mut_seq +2067 status = undefined.Undefined +2068 if (raw_status := payload["status"]) != typedefs.Unknown: +2069 status = raw_status +2070 +2071 tips: typing.MutableSequence[undefined.UndefinedOr[str]] = [] +2072 if raw_tips := payload.get("tips"): +2073 for raw_tip in raw_tips: +2074 if raw_tip == typedefs.Unknown: +2075 raw_tip = undefined.Undefined +2076 tips.append(raw_tip) +2077 +2078 return milestones.MilestoneContent( +2079 about=about, status=status, tips=tips, items=items_categoris +2080 ) +2081 +2082 def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend: +2083 name = undefined.Undefined +2084 if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown: +2085 name = raw_name +2086 +2087 bungie_user: typedefs.NoneOr[user.BungieUser] = None +2088 +2089 if raw_bungie_user := payload.get("bungieNetUser"): +2090 bungie_user = self.deserialize_bungie_user(raw_bungie_user) +2091 +2092 return friends.Friend( +2093 net=self._net, +2094 id=int(payload["lastSeenAsMembershipId"]), +2095 name=name, +2096 code=payload.get("bungieGlobalDisplayNameCode"), +2097 relationship=enums.Relationship(payload["relationship"]), +2098 user=bungie_user, +2099 online_status=enums.Presence(payload["onlineStatus"]), +2100 online_title=payload["onlineTitle"], +2101 type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]), +2102 ) +2103 +2104 def deserialize_friends( +2105 self, payload: typedefs.JSONObject +2106 ) -> collections.Sequence[friends.Friend]: +2107 mut_seq: typing.MutableSequence[friends.Friend] = [] +2108 if raw_friends := payload.get("friends"): +2109 for friend in raw_friends: +2110 mut_seq.append(self.deserialize_friend(friend)) +2111 return mut_seq +2112 +2113 def deserialize_friend_requests( +2114 self, payload: typedefs.JSONObject +2115 ) -> friends.FriendRequestView: +2116 incoming: typing.MutableSequence[friends.Friend] = [] +2117 outgoing: typing.MutableSequence[friends.Friend] = [] 2118 -2119 def deserialize_friend_requests( -2120 self, payload: typedefs.JSONObject -2121 ) -> friends.FriendRequestView: -2122 incoming: typing.MutableSequence[friends.Friend] = [] -2123 outgoing: typing.MutableSequence[friends.Friend] = [] -2124 -2125 if raw_incoming_requests := payload.get("incomingRequests"): -2126 for incoming_request in raw_incoming_requests: -2127 incoming.append(self.deserialize_friend(incoming_request)) +2119 if raw_incoming_requests := payload.get("incomingRequests"): +2120 for incoming_request in raw_incoming_requests: +2121 incoming.append(self.deserialize_friend(incoming_request)) +2122 +2123 if raw_outgoing_requests := payload.get("outgoingRequests"): +2124 for outgoing_request in raw_outgoing_requests: +2125 outgoing.append(self.deserialize_friend(outgoing_request)) +2126 +2127 return friends.FriendRequestView(incoming=incoming, outgoing=outgoing) 2128 -2129 if raw_outgoing_requests := payload.get("outgoingRequests"): -2130 for outgoing_request in raw_outgoing_requests: -2131 outgoing.append(self.deserialize_friend(outgoing_request)) -2132 -2133 return friends.FriendRequestView(incoming=incoming, outgoing=outgoing) -2134 -2135 def _set_fireteam_fields( -2136 self, payload: typedefs.JSONObject, total_results: typing.Optional[int] = None -2137 ) -> fireteams.Fireteam: -2138 activity_type = fireteams.FireteamActivity(payload["activityType"]) -2139 return fireteams.Fireteam( -2140 id=int(payload["fireteamId"]), -2141 group_id=int(payload["groupId"]), -2142 platform=fireteams.FireteamPlatform(payload["platform"]), -2143 is_immediate=payload["isImmediate"], -2144 activity_type=activity_type, -2145 owner_id=int(payload["ownerMembershipId"]), -2146 player_slot_count=payload["playerSlotCount"], -2147 available_player_slots=payload["availablePlayerSlotCount"], -2148 available_alternate_slots=payload["availableAlternateSlotCount"], -2149 title=payload["title"], -2150 date_created=time.clean_date(payload["dateCreated"]), -2151 is_public=payload["isPublic"], -2152 locale=fireteams.FireteamLanguage(payload["locale"]), -2153 is_valid=payload["isValid"], -2154 last_modified=time.clean_date(payload["datePlayerModified"]), -2155 total_results=total_results or 0, -2156 ) -2157 -2158 def deserialize_fireteams( -2159 self, payload: typedefs.JSONObject -2160 ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]: -2161 fireteams_: typing.MutableSequence[fireteams.Fireteam] = [] -2162 -2163 result: list[typedefs.JSONObject] -2164 if not (result := payload["results"]): -2165 return None -2166 for elem in result: -2167 fireteams_.append( -2168 self._set_fireteam_fields( -2169 elem, total_results=int(payload["totalResults"]) -2170 ) -2171 ) -2172 return fireteams_ -2173 -2174 def deserialize_fireteam_destiny_users( -2175 self, payload: typedefs.JSONObject -2176 ) -> fireteams.FireteamUser: -2177 destiny_obj = self.deserialize_destiny_membership(payload) -2178 # We could helpers.just return a DestinyMembership object but this is -2179 # missing the fireteam display name and id fields. -2180 return fireteams.FireteamUser( -2181 net=self._net, -2182 id=destiny_obj.id, -2183 code=destiny_obj.code, -2184 icon=destiny_obj.icon, -2185 types=destiny_obj.types, -2186 type=destiny_obj.type, -2187 is_public=destiny_obj.is_public, -2188 crossave_override=destiny_obj.crossave_override, -2189 name=destiny_obj.name, -2190 last_seen_name=destiny_obj.last_seen_name, -2191 fireteam_display_name=payload["FireteamDisplayName"], -2192 fireteam_membership_id=enums.MembershipType( -2193 payload["FireteamMembershipType"] -2194 ), -2195 ) -2196 -2197 def deserialize_fireteam_members( -2198 self, payload: typedefs.JSONObject, *, alternatives: bool = False -2199 ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]: -2200 members_: list[fireteams.FireteamMember] = [] -2201 if members := payload.get("Members" if not alternatives else "Alternates"): -2202 for member in members: -2203 bungie_fields = self.deserialize_partial_bungie_user(member) -2204 members_fields = fireteams.FireteamMember( -2205 destiny_user=self.deserialize_fireteam_destiny_users(member), -2206 has_microphone=member["hasMicrophone"], -2207 character_id=int(member["characterId"]), -2208 date_joined=time.clean_date(member["dateJoined"]), -2209 last_platform_invite_date=time.clean_date( -2210 member["lastPlatformInviteAttemptDate"] -2211 ), -2212 last_platform_invite_result=int( -2213 member["lastPlatformInviteAttemptResult"] -2214 ), -2215 net=self._net, -2216 name=bungie_fields.name, -2217 id=bungie_fields.id, -2218 icon=bungie_fields.icon, -2219 is_public=bungie_fields.is_public, -2220 crossave_override=bungie_fields.crossave_override, -2221 types=bungie_fields.types, -2222 type=bungie_fields.type, -2223 ) -2224 members_.append(members_fields) -2225 else: -2226 return None -2227 return members_ -2228 -2229 def deserialize_available_fireteams( -2230 self, -2231 data: typedefs.JSONObject, -2232 *, -2233 no_results: bool = False, -2234 ) -> typing.Union[ -2235 fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam] -2236 ]: -2237 fireteams_: list[fireteams.AvailableFireteam] = [] -2238 -2239 # This needs to be used outside the results -2240 # JSON key. -2241 if no_results is True: -2242 payload = data -2243 -2244 if result := payload.get("results"): -2245 -2246 for fireteam in result: -2247 found_fireteams = self._set_fireteam_fields(fireteam["Summary"]) -2248 fireteams_fields = fireteams.AvailableFireteam( -2249 id=found_fireteams.id, -2250 group_id=found_fireteams.group_id, -2251 platform=found_fireteams.platform, -2252 activity_type=found_fireteams.activity_type, -2253 is_immediate=found_fireteams.is_immediate, -2254 is_public=found_fireteams.is_public, -2255 is_valid=found_fireteams.is_valid, -2256 owner_id=found_fireteams.owner_id, -2257 player_slot_count=found_fireteams.player_slot_count, -2258 available_player_slots=found_fireteams.available_player_slots, -2259 available_alternate_slots=found_fireteams.available_alternate_slots, -2260 title=found_fireteams.title, -2261 date_created=found_fireteams.date_created, -2262 locale=found_fireteams.locale, -2263 last_modified=found_fireteams.last_modified, -2264 total_results=found_fireteams.total_results, -2265 members=self.deserialize_fireteam_members(payload), -2266 alternatives=self.deserialize_fireteam_members( -2267 payload, alternatives=True -2268 ), -2269 ) -2270 fireteams_.append(fireteams_fields) -2271 if no_results: -2272 return fireteams_fields -2273 return fireteams_ -2274 -2275 def deserialize_fireteam_party( -2276 self, payload: typedefs.JSONObject -2277 ) -> fireteams.FireteamParty: -2278 last_destination_hash: typing.Optional[int] = None -2279 if raw_dest_hash := payload.get("lastOrbitedDestinationHash"): -2280 last_destination_hash = int(raw_dest_hash) -2281 -2282 return fireteams.FireteamParty( -2283 members=[ -2284 self._deserialize_fireteam_party_member(member) -2285 for member in payload["partyMembers"] -2286 ], -2287 activity=self._deserialize_fireteam_party_current_activity( -2288 payload["currentActivity"] -2289 ), -2290 settings=self._deserialize_fireteam_party_settings(payload["joinability"]), -2291 last_destination_hash=last_destination_hash, -2292 tracking=payload["tracking"], -2293 ) -2294 -2295 def _deserialize_fireteam_party_member( -2296 self, payload: typedefs.JSONObject -2297 ) -> fireteams.FireteamPartyMember: -2298 -2299 status = fireteams.FireteamPartyMemberState(payload["status"]) -2300 displayname: undefined.UndefinedOr[str] = undefined.Undefined -2301 if raw_name := payload.get("displayName"): -2302 displayname = raw_name -2303 -2304 return fireteams.FireteamPartyMember( -2305 membership_id=int(payload["membershipId"]), -2306 emblem_hash=int(payload["emblemHash"]), -2307 status=status, -2308 display_name=displayname, -2309 ) -2310 -2311 def _deserialize_fireteam_party_current_activity( -2312 self, payload: typedefs.JSONObject -2313 ) -> fireteams.FireteamPartyCurrentActivity: -2314 start_date: typing.Optional[datetime.datetime] = None -2315 if raw_start_date := payload.get("startTime"): -2316 start_date = time.clean_date(raw_start_date) -2317 -2318 end_date: typing.Optional[datetime.datetime] = None -2319 if raw_end_date := payload.get("endTime"): -2320 end_date = time.clean_date(raw_end_date) -2321 return fireteams.FireteamPartyCurrentActivity( -2322 start_time=start_date, -2323 end_time=end_date, -2324 score=float(payload["score"]), -2325 highest_opposing_score=float(payload["highestOpposingFactionScore"]), -2326 opponenst_count=int(payload["numberOfOpponents"]), -2327 player_count=int(payload["numberOfPlayers"]), -2328 ) -2329 -2330 def _deserialize_fireteam_party_settings( -2331 self, payload: typedefs.JSONObject -2332 ) -> fireteams.FireteamPartySettings: -2333 closed_reasons = enums.ClosedReasons(payload["closedReasons"]) -2334 return fireteams.FireteamPartySettings( -2335 open_slots=int(payload["openSlots"]), -2336 privacy_setting=enums.PrivacySetting(int(payload["privacySetting"])), -2337 closed_reasons=closed_reasons, -2338 ) -2339 -2340 def deserialize_seasonal_artifact( -2341 self, payload: typedefs.JSONObject -2342 ) -> season.Artifact: -2343 if raw_artifact := payload.get("seasonalArtifact"): -2344 if points := raw_artifact.get("pointProgression"): -2345 points_prog = progressions.Progression( -2346 hash=points["progressionHash"], -2347 level=points["level"], -2348 cap=points["levelCap"], -2349 daily_limit=points["dailyLimit"], -2350 weekly_limit=points["weeklyLimit"], -2351 current_progress=points["currentProgress"], -2352 daily_progress=points["dailyProgress"], -2353 needed=points["progressToNextLevel"], -2354 next_level=points["nextLevelAt"], -2355 ) -2356 -2357 if bonus := raw_artifact.get("powerBonusProgression"): -2358 power_bonus_prog = progressions.Progression( -2359 hash=bonus["progressionHash"], -2360 level=bonus["level"], -2361 cap=bonus["levelCap"], -2362 daily_limit=bonus["dailyLimit"], -2363 weekly_limit=bonus["weeklyLimit"], -2364 current_progress=bonus["currentProgress"], -2365 daily_progress=bonus["dailyProgress"], -2366 needed=bonus["progressToNextLevel"], -2367 next_level=bonus["nextLevelAt"], -2368 ) -2369 artifact = season.Artifact( -2370 net=self._net, -2371 hash=raw_artifact["artifactHash"], -2372 power_bonus=raw_artifact["powerBonus"], -2373 acquired_points=raw_artifact["pointsAcquired"], -2374 bonus=power_bonus_prog, -2375 points=points_prog, -2376 ) -2377 return artifact -2378 -2379 def deserialize_profile_progression( -2380 self, payload: typedefs.JSONObject -2381 ) -> profile.ProfileProgression: -2382 return profile.ProfileProgression( -2383 artifact=self.deserialize_seasonal_artifact(payload["data"]), -2384 checklist={ -2385 int(check_id): checklists -2386 for check_id, checklists in payload["data"]["checklists"].items() -2387 }, -2388 ) -2389 -2390 def deserialize_instanced_item( -2391 self, payload: typedefs.JSONObject -2392 ) -> items.ItemInstance: -2393 damage_type_hash: typing.Optional[int] = None -2394 if raw_damagetype_hash := payload.get("damageTypeHash"): -2395 damage_type_hash = int(raw_damagetype_hash) -2396 -2397 required_hashes: typing.Optional[collections.Collection[int]] = None -2398 if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"): -2399 required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes] -2400 -2401 breaker_type: typing.Optional[items.ItemBreakerType] = None -2402 if raw_break_type := payload.get("breakerType"): -2403 breaker_type = items.ItemBreakerType(int(raw_break_type)) -2404 -2405 breaker_type_hash: typing.Optional[int] = None -2406 if raw_break_type_hash := payload.get("breakerTypeHash"): -2407 breaker_type_hash = int(raw_break_type_hash) -2408 -2409 energy: typing.Optional[items.ItemEnergy] = None -2410 if raw_energy := payload.get("energy"): -2411 energy = self.deserialize_item_energy(raw_energy) -2412 -2413 primary_stats = None -2414 if raw_primary_stats := payload.get("primaryStat"): -2415 primary_stats = self.deserialize_item_stats_view(raw_primary_stats) -2416 -2417 return items.ItemInstance( -2418 damage_type=enums.DamageType(int(payload["damageType"])), -2419 damage_type_hash=damage_type_hash, -2420 primary_stat=primary_stats, -2421 item_level=int(payload["itemLevel"]), -2422 quality=int(payload["quality"]), -2423 is_equipped=payload["isEquipped"], -2424 can_equip=payload["canEquip"], -2425 equip_required_level=int(payload["equipRequiredLevel"]), -2426 required_equip_unlock_hashes=required_hashes, -2427 cant_equip_reason=int(payload["cannotEquipReason"]), -2428 breaker_type=breaker_type, -2429 breaker_type_hash=breaker_type_hash, -2430 energy=energy, -2431 ) -2432 -2433 def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy: -2434 energy_hash: typing.Optional[int] = None -2435 if raw_energy_hash := payload.get("energyTypeHash"): -2436 energy_hash = int(raw_energy_hash) -2437 -2438 return items.ItemEnergy( -2439 hash=energy_hash, -2440 type=items.ItemEnergyType(int(payload["energyType"])), -2441 capacity=int(payload["energyCapacity"]), -2442 used_energy=int(payload["energyUsed"]), -2443 unused_energy=int(payload["energyUnused"]), -2444 ) -2445 -2446 def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk: -2447 perk_hash: typing.Optional[int] = None -2448 if raw_perk_hash := payload.get("perkHash"): -2449 perk_hash = int(raw_perk_hash) -2450 -2451 return items.ItemPerk( -2452 hash=perk_hash, -2453 icon=assets.Image(payload["iconPath"]), -2454 is_active=payload["isActive"], -2455 is_visible=payload["visible"], -2456 ) -2457 -2458 def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket: -2459 plug_hash: typing.Optional[int] = None -2460 if raw_plug_hash := payload.get("plugHash"): -2461 plug_hash = int(raw_plug_hash) -2462 -2463 enable_fail_indexes: typing.Optional[list[int]] = None -2464 if raw_indexes := payload.get("enableFailIndexes"): -2465 enable_fail_indexes = [int(index) for index in raw_indexes] -2466 -2467 return items.ItemSocket( -2468 plug_hash=plug_hash, -2469 is_enabled=payload["isEnabled"], -2470 enable_fail_indexes=enable_fail_indexes, -2471 is_visible=payload.get("visible"), -2472 ) -2473 -2474 def deserialize_item_stats_view( -2475 self, payload: typedefs.JSONObject -2476 ) -> items.ItemStatsView: -2477 return items.ItemStatsView( -2478 stat_hash=payload.get("statHash"), value=payload.get("value") -2479 ) -2480 -2481 def deserialize_plug_item_state( -2482 self, payload: typedefs.JSONObject -2483 ) -> items.PlugItemState: -2484 item_hash: typing.Optional[int] = None -2485 if raw_item_hash := payload.get("plugItemHash"): -2486 item_hash = int(raw_item_hash) -2487 -2488 insert_fail_indexes: typedefs.NoneOr[list[int]] = None -2489 if raw_fail_indexes := payload.get("insertFailIndexes"): -2490 insert_fail_indexes = [int(k) for k in raw_fail_indexes] -2491 -2492 enable_fail_indexes: typedefs.NoneOr[list[int]] = None -2493 if raw_enabled_indexes := payload.get("enableFailIndexes"): -2494 enable_fail_indexes = [int(k) for k in raw_enabled_indexes] -2495 -2496 return items.PlugItemState( -2497 item_hash=item_hash, -2498 insert_fail_indexes=insert_fail_indexes, -2499 enable_fail_indexes=enable_fail_indexes, -2500 is_enabled=payload["enabled"], -2501 can_insert=payload["canInsert"], -2502 ) +2129 def _set_fireteam_fields( +2130 self, payload: typedefs.JSONObject, total_results: typing.Optional[int] = None +2131 ) -> fireteams.Fireteam: +2132 activity_type = fireteams.FireteamActivity(payload["activityType"]) +2133 return fireteams.Fireteam( +2134 id=int(payload["fireteamId"]), +2135 group_id=int(payload["groupId"]), +2136 platform=fireteams.FireteamPlatform(payload["platform"]), +2137 is_immediate=payload["isImmediate"], +2138 activity_type=activity_type, +2139 owner_id=int(payload["ownerMembershipId"]), +2140 player_slot_count=payload["playerSlotCount"], +2141 available_player_slots=payload["availablePlayerSlotCount"], +2142 available_alternate_slots=payload["availableAlternateSlotCount"], +2143 title=payload["title"], +2144 date_created=time.clean_date(payload["dateCreated"]), +2145 is_public=payload["isPublic"], +2146 locale=fireteams.FireteamLanguage(payload["locale"]), +2147 is_valid=payload["isValid"], +2148 last_modified=time.clean_date(payload["datePlayerModified"]), +2149 total_results=total_results or 0, +2150 ) +2151 +2152 def deserialize_fireteams( +2153 self, payload: typedefs.JSONObject +2154 ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]: +2155 fireteams_: typing.MutableSequence[fireteams.Fireteam] = [] +2156 +2157 result: list[typedefs.JSONObject] +2158 if not (result := payload["results"]): +2159 return None +2160 for elem in result: +2161 fireteams_.append( +2162 self._set_fireteam_fields( +2163 elem, total_results=int(payload["totalResults"]) +2164 ) +2165 ) +2166 return fireteams_ +2167 +2168 def deserialize_fireteam_destiny_users( +2169 self, payload: typedefs.JSONObject +2170 ) -> fireteams.FireteamUser: +2171 destiny_obj = self.deserialize_destiny_membership(payload) +2172 # We could helpers.just return a DestinyMembership object but this is +2173 # missing the fireteam display name and id fields. +2174 return fireteams.FireteamUser( +2175 net=self._net, +2176 id=destiny_obj.id, +2177 code=destiny_obj.code, +2178 icon=destiny_obj.icon, +2179 types=destiny_obj.types, +2180 type=destiny_obj.type, +2181 is_public=destiny_obj.is_public, +2182 crossave_override=destiny_obj.crossave_override, +2183 name=destiny_obj.name, +2184 last_seen_name=destiny_obj.last_seen_name, +2185 fireteam_display_name=payload["FireteamDisplayName"], +2186 fireteam_membership_id=enums.MembershipType( +2187 payload["FireteamMembershipType"] +2188 ), +2189 ) +2190 +2191 def deserialize_fireteam_members( +2192 self, payload: typedefs.JSONObject, *, alternatives: bool = False +2193 ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]: +2194 members_: list[fireteams.FireteamMember] = [] +2195 if members := payload.get("Members" if not alternatives else "Alternates"): +2196 for member in members: +2197 bungie_fields = self.deserialize_partial_bungie_user(member) +2198 members_fields = fireteams.FireteamMember( +2199 destiny_user=self.deserialize_fireteam_destiny_users(member), +2200 has_microphone=member["hasMicrophone"], +2201 character_id=int(member["characterId"]), +2202 date_joined=time.clean_date(member["dateJoined"]), +2203 last_platform_invite_date=time.clean_date( +2204 member["lastPlatformInviteAttemptDate"] +2205 ), +2206 last_platform_invite_result=int( +2207 member["lastPlatformInviteAttemptResult"] +2208 ), +2209 net=self._net, +2210 name=bungie_fields.name, +2211 id=bungie_fields.id, +2212 icon=bungie_fields.icon, +2213 is_public=bungie_fields.is_public, +2214 crossave_override=bungie_fields.crossave_override, +2215 types=bungie_fields.types, +2216 type=bungie_fields.type, +2217 ) +2218 members_.append(members_fields) +2219 else: +2220 return None +2221 return members_ +2222 +2223 def deserialize_available_fireteams( +2224 self, +2225 data: typedefs.JSONObject, +2226 *, +2227 no_results: bool = False, +2228 ) -> typing.Union[ +2229 fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam] +2230 ]: +2231 fireteams_: list[fireteams.AvailableFireteam] = [] +2232 +2233 # This needs to be used outside the results +2234 # JSON key. +2235 if no_results is True: +2236 payload = data +2237 +2238 if result := payload.get("results"): +2239 +2240 for fireteam in result: +2241 found_fireteams = self._set_fireteam_fields(fireteam["Summary"]) +2242 fireteams_fields = fireteams.AvailableFireteam( +2243 id=found_fireteams.id, +2244 group_id=found_fireteams.group_id, +2245 platform=found_fireteams.platform, +2246 activity_type=found_fireteams.activity_type, +2247 is_immediate=found_fireteams.is_immediate, +2248 is_public=found_fireteams.is_public, +2249 is_valid=found_fireteams.is_valid, +2250 owner_id=found_fireteams.owner_id, +2251 player_slot_count=found_fireteams.player_slot_count, +2252 available_player_slots=found_fireteams.available_player_slots, +2253 available_alternate_slots=found_fireteams.available_alternate_slots, +2254 title=found_fireteams.title, +2255 date_created=found_fireteams.date_created, +2256 locale=found_fireteams.locale, +2257 last_modified=found_fireteams.last_modified, +2258 total_results=found_fireteams.total_results, +2259 members=self.deserialize_fireteam_members(payload), +2260 alternatives=self.deserialize_fireteam_members( +2261 payload, alternatives=True +2262 ), +2263 ) +2264 fireteams_.append(fireteams_fields) +2265 if no_results: +2266 return fireteams_fields +2267 return fireteams_ +2268 +2269 def deserialize_fireteam_party( +2270 self, payload: typedefs.JSONObject +2271 ) -> fireteams.FireteamParty: +2272 last_destination_hash: typing.Optional[int] = None +2273 if raw_dest_hash := payload.get("lastOrbitedDestinationHash"): +2274 last_destination_hash = int(raw_dest_hash) +2275 +2276 return fireteams.FireteamParty( +2277 members=[ +2278 self._deserialize_fireteam_party_member(member) +2279 for member in payload["partyMembers"] +2280 ], +2281 activity=self._deserialize_fireteam_party_current_activity( +2282 payload["currentActivity"] +2283 ), +2284 settings=self._deserialize_fireteam_party_settings(payload["joinability"]), +2285 last_destination_hash=last_destination_hash, +2286 tracking=payload["tracking"], +2287 ) +2288 +2289 def _deserialize_fireteam_party_member( +2290 self, payload: typedefs.JSONObject +2291 ) -> fireteams.FireteamPartyMember: +2292 +2293 status = fireteams.FireteamPartyMemberState(payload["status"]) +2294 displayname: undefined.UndefinedOr[str] = undefined.Undefined +2295 if raw_name := payload.get("displayName"): +2296 displayname = raw_name +2297 +2298 return fireteams.FireteamPartyMember( +2299 membership_id=int(payload["membershipId"]), +2300 emblem_hash=int(payload["emblemHash"]), +2301 status=status, +2302 display_name=displayname, +2303 ) +2304 +2305 def _deserialize_fireteam_party_current_activity( +2306 self, payload: typedefs.JSONObject +2307 ) -> fireteams.FireteamPartyCurrentActivity: +2308 start_date: typing.Optional[datetime.datetime] = None +2309 if raw_start_date := payload.get("startTime"): +2310 start_date = time.clean_date(raw_start_date) +2311 +2312 end_date: typing.Optional[datetime.datetime] = None +2313 if raw_end_date := payload.get("endTime"): +2314 end_date = time.clean_date(raw_end_date) +2315 return fireteams.FireteamPartyCurrentActivity( +2316 start_time=start_date, +2317 end_time=end_date, +2318 score=float(payload["score"]), +2319 highest_opposing_score=float(payload["highestOpposingFactionScore"]), +2320 opponenst_count=int(payload["numberOfOpponents"]), +2321 player_count=int(payload["numberOfPlayers"]), +2322 ) +2323 +2324 def _deserialize_fireteam_party_settings( +2325 self, payload: typedefs.JSONObject +2326 ) -> fireteams.FireteamPartySettings: +2327 closed_reasons = enums.ClosedReasons(payload["closedReasons"]) +2328 return fireteams.FireteamPartySettings( +2329 open_slots=int(payload["openSlots"]), +2330 privacy_setting=enums.PrivacySetting(int(payload["privacySetting"])), +2331 closed_reasons=closed_reasons, +2332 ) +2333 +2334 def deserialize_seasonal_artifact( +2335 self, payload: typedefs.JSONObject +2336 ) -> season.Artifact: +2337 if raw_artifact := payload.get("seasonalArtifact"): +2338 if points := raw_artifact.get("pointProgression"): +2339 points_prog = progressions.Progression( +2340 hash=points["progressionHash"], +2341 level=points["level"], +2342 cap=points["levelCap"], +2343 daily_limit=points["dailyLimit"], +2344 weekly_limit=points["weeklyLimit"], +2345 current_progress=points["currentProgress"], +2346 daily_progress=points["dailyProgress"], +2347 needed=points["progressToNextLevel"], +2348 next_level=points["nextLevelAt"], +2349 ) +2350 +2351 if bonus := raw_artifact.get("powerBonusProgression"): +2352 power_bonus_prog = progressions.Progression( +2353 hash=bonus["progressionHash"], +2354 level=bonus["level"], +2355 cap=bonus["levelCap"], +2356 daily_limit=bonus["dailyLimit"], +2357 weekly_limit=bonus["weeklyLimit"], +2358 current_progress=bonus["currentProgress"], +2359 daily_progress=bonus["dailyProgress"], +2360 needed=bonus["progressToNextLevel"], +2361 next_level=bonus["nextLevelAt"], +2362 ) +2363 artifact = season.Artifact( +2364 net=self._net, +2365 hash=raw_artifact["artifactHash"], +2366 power_bonus=raw_artifact["powerBonus"], +2367 acquired_points=raw_artifact["pointsAcquired"], +2368 bonus=power_bonus_prog, +2369 points=points_prog, +2370 ) +2371 return artifact +2372 +2373 def deserialize_profile_progression( +2374 self, payload: typedefs.JSONObject +2375 ) -> profile.ProfileProgression: +2376 return profile.ProfileProgression( +2377 artifact=self.deserialize_seasonal_artifact(payload["data"]), +2378 checklist={ +2379 int(check_id): checklists +2380 for check_id, checklists in payload["data"]["checklists"].items() +2381 }, +2382 ) +2383 +2384 def deserialize_instanced_item( +2385 self, payload: typedefs.JSONObject +2386 ) -> items.ItemInstance: +2387 damage_type_hash: typing.Optional[int] = None +2388 if raw_damagetype_hash := payload.get("damageTypeHash"): +2389 damage_type_hash = int(raw_damagetype_hash) +2390 +2391 required_hashes: typing.Optional[collections.Collection[int]] = None +2392 if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"): +2393 required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes] +2394 +2395 breaker_type: typing.Optional[items.ItemBreakerType] = None +2396 if raw_break_type := payload.get("breakerType"): +2397 breaker_type = items.ItemBreakerType(int(raw_break_type)) +2398 +2399 breaker_type_hash: typing.Optional[int] = None +2400 if raw_break_type_hash := payload.get("breakerTypeHash"): +2401 breaker_type_hash = int(raw_break_type_hash) +2402 +2403 energy: typing.Optional[items.ItemEnergy] = None +2404 if raw_energy := payload.get("energy"): +2405 energy = self.deserialize_item_energy(raw_energy) +2406 +2407 primary_stats = None +2408 if raw_primary_stats := payload.get("primaryStat"): +2409 primary_stats = self.deserialize_item_stats_view(raw_primary_stats) +2410 +2411 return items.ItemInstance( +2412 damage_type=enums.DamageType(int(payload["damageType"])), +2413 damage_type_hash=damage_type_hash, +2414 primary_stat=primary_stats, +2415 item_level=int(payload["itemLevel"]), +2416 quality=int(payload["quality"]), +2417 is_equipped=payload["isEquipped"], +2418 can_equip=payload["canEquip"], +2419 equip_required_level=int(payload["equipRequiredLevel"]), +2420 required_equip_unlock_hashes=required_hashes, +2421 cant_equip_reason=int(payload["cannotEquipReason"]), +2422 breaker_type=breaker_type, +2423 breaker_type_hash=breaker_type_hash, +2424 energy=energy, +2425 ) +2426 +2427 def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy: +2428 energy_hash: typing.Optional[int] = None +2429 if raw_energy_hash := payload.get("energyTypeHash"): +2430 energy_hash = int(raw_energy_hash) +2431 +2432 return items.ItemEnergy( +2433 hash=energy_hash, +2434 type=items.ItemEnergyType(int(payload["energyType"])), +2435 capacity=int(payload["energyCapacity"]), +2436 used_energy=int(payload["energyUsed"]), +2437 unused_energy=int(payload["energyUnused"]), +2438 ) +2439 +2440 def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk: +2441 perk_hash: typing.Optional[int] = None +2442 if raw_perk_hash := payload.get("perkHash"): +2443 perk_hash = int(raw_perk_hash) +2444 +2445 return items.ItemPerk( +2446 hash=perk_hash, +2447 icon=assets.Image(payload["iconPath"]), +2448 is_active=payload["isActive"], +2449 is_visible=payload["visible"], +2450 ) +2451 +2452 def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket: +2453 plug_hash: typing.Optional[int] = None +2454 if raw_plug_hash := payload.get("plugHash"): +2455 plug_hash = int(raw_plug_hash) +2456 +2457 enable_fail_indexes: typing.Optional[list[int]] = None +2458 if raw_indexes := payload.get("enableFailIndexes"): +2459 enable_fail_indexes = [int(index) for index in raw_indexes] +2460 +2461 return items.ItemSocket( +2462 plug_hash=plug_hash, +2463 is_enabled=payload["isEnabled"], +2464 enable_fail_indexes=enable_fail_indexes, +2465 is_visible=payload.get("visible"), +2466 ) +2467 +2468 def deserialize_item_stats_view( +2469 self, payload: typedefs.JSONObject +2470 ) -> items.ItemStatsView: +2471 return items.ItemStatsView( +2472 stat_hash=payload.get("statHash"), value=payload.get("value") +2473 ) +2474 +2475 def deserialize_plug_item_state( +2476 self, payload: typedefs.JSONObject +2477 ) -> items.PlugItemState: +2478 item_hash: typing.Optional[int] = None +2479 if raw_item_hash := payload.get("plugItemHash"): +2480 item_hash = int(raw_item_hash) +2481 +2482 insert_fail_indexes: typedefs.NoneOr[list[int]] = None +2483 if raw_fail_indexes := payload.get("insertFailIndexes"): +2484 insert_fail_indexes = [int(k) for k in raw_fail_indexes] +2485 +2486 enable_fail_indexes: typedefs.NoneOr[list[int]] = None +2487 if raw_enabled_indexes := payload.get("enableFailIndexes"): +2488 enable_fail_indexes = [int(k) for k in raw_enabled_indexes] +2489 +2490 return items.PlugItemState( +2491 item_hash=item_hash, +2492 insert_fail_indexes=insert_fail_indexes, +2493 enable_fail_indexes=enable_fail_indexes, +2494 is_enabled=payload["enabled"], +2495 can_insert=payload["canInsert"], +2496 )

          @@ -5613,40 +5598,6 @@
          Returns
          -
          -
          - -
          -
          @staticmethod
          - - def - set_themese_attrs( payload: list[typing.Any], /) -> Collection[aiobungie.crates.user.UserThemes]: - - - -
          - -
          197    @staticmethod
          -198    def set_themese_attrs(
          -199        payload: typedefs.JSONArray, /
          -200    ) -> typing.Collection[user.UserThemes]:
          -201        return [
          -202            user.UserThemes(
          -203                id=int(entry["userThemeId"]),
          -204                name=entry["userThemeName"]
          -205                if "userThemeName" in entry
          -206                else undefined.Undefined,
          -207                description=entry["userThemeDescription"]
          -208                if "userThemeDescription" in entry
          -209                else undefined.Undefined,
          -210            )
          -211            for entry in payload
          -212        ]
          -
          - - - -
          @@ -5659,10 +5610,21 @@
          Returns
          -
          214    def deserialize_user_themes(
          -215        self, payload: typedefs.JSONArray
          -216    ) -> collections.Sequence[user.UserThemes]:
          -217        return list(self.set_themese_attrs(payload))
          +            
          197    def deserialize_user_themes(
          +198        self, payload: typedefs.JSONArray
          +199    ) -> collections.Sequence[user.UserThemes]:
          +200        return [
          +201            user.UserThemes(
          +202                id=int(entry["userThemeId"]),
          +203                name=entry["userThemeName"]
          +204                if "userThemeName" in entry
          +205                else undefined.Undefined,
          +206                description=entry["userThemeDescription"]
          +207                if "userThemeDescription" in entry
          +208                else undefined.Undefined,
          +209            )
          +210            for entry in payload
          +211        ]
           
          @@ -5695,84 +5657,84 @@
          Returns
          -
          219    def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan:
          -220
          -221        # This is kinda redundant
          -222        data = payload
          -223
          -224        # This is always outside the details.
          -225        current_user_map: typing.Optional[
          -226            collections.Mapping[str, clans.ClanMember]
          -227        ] = None
          -228        if raw_current_user_map := payload.get("currentUserMemberMap"):
          -229            current_user_map = {
          -230                membership_type: self.deserialize_clan_member(membership)
          -231                for membership_type, membership in raw_current_user_map.items()
          -232            }
          -233
          -234        try:
          -235            data = payload["detail"]
          -236        except KeyError:
          -237            pass
          -238
          -239        id = data["groupId"]
          -240        name = data["name"]
          -241        created_at = data["creationDate"]
          -242        member_count = data["memberCount"]
          -243        about = data["about"]
          -244        motto = data["motto"]
          -245        is_public = data["isPublic"]
          -246        banner = assets.Image(str(data["bannerPath"]))
          -247        avatar = assets.Image(str(data["avatarPath"]))
          -248        tags = data["tags"]
          -249        type = data["groupType"]
          -250
          -251        features = data["features"]
          -252        features_obj = clans.ClanFeatures(
          -253            max_members=features["maximumMembers"],
          -254            max_membership_types=features["maximumMembershipsOfGroupType"],
          -255            capabilities=features["capabilities"],
          -256            membership_types=features["membershipTypes"],
          -257            invite_permissions=features["invitePermissionOverride"],
          -258            update_banner_permissions=features["updateBannerPermissionOverride"],
          -259            update_culture_permissions=features["updateCulturePermissionOverride"],
          -260            join_level=features["joinLevel"],
          -261        )
          +            
          213    def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan:
          +214
          +215        # This is kinda redundant
          +216        data = payload
          +217
          +218        # This is always outside the details.
          +219        current_user_map: typing.Optional[
          +220            collections.Mapping[str, clans.ClanMember]
          +221        ] = None
          +222        if raw_current_user_map := payload.get("currentUserMemberMap"):
          +223            current_user_map = {
          +224                membership_type: self.deserialize_clan_member(membership)
          +225                for membership_type, membership in raw_current_user_map.items()
          +226            }
          +227
          +228        try:
          +229            data = payload["detail"]
          +230        except KeyError:
          +231            pass
          +232
          +233        id = data["groupId"]
          +234        name = data["name"]
          +235        created_at = data["creationDate"]
          +236        member_count = data["memberCount"]
          +237        about = data["about"]
          +238        motto = data["motto"]
          +239        is_public = data["isPublic"]
          +240        banner = assets.Image(str(data["bannerPath"]))
          +241        avatar = assets.Image(str(data["avatarPath"]))
          +242        tags = data["tags"]
          +243        type = data["groupType"]
          +244
          +245        features = data["features"]
          +246        features_obj = clans.ClanFeatures(
          +247            max_members=features["maximumMembers"],
          +248            max_membership_types=features["maximumMembershipsOfGroupType"],
          +249            capabilities=features["capabilities"],
          +250            membership_types=features["membershipTypes"],
          +251            invite_permissions=features["invitePermissionOverride"],
          +252            update_banner_permissions=features["updateBannerPermissionOverride"],
          +253            update_culture_permissions=features["updateCulturePermissionOverride"],
          +254            join_level=features["joinLevel"],
          +255        )
          +256
          +257        information: typedefs.JSONObject = data["clanInfo"]
          +258        progression: collections.Mapping[int, progressions.Progression] = {
          +259            int(prog_hash): self.deserialize_progressions(prog)
          +260            for prog_hash, prog in information["d2ClanProgressions"].items()
          +261        }
           262
          -263        information: typedefs.JSONObject = data["clanInfo"]
          -264        progression: collections.Mapping[int, progressions.Progression] = {
          -265            int(prog_hash): self.deserialize_progressions(prog)
          -266            for prog_hash, prog in information["d2ClanProgressions"].items()
          -267        }
          -268
          -269        founder: typedefs.NoneOr[clans.ClanMember] = None
          -270        if raw_founder := payload.get("founder"):
          -271            founder = self.deserialize_clan_member(raw_founder)
          -272
          -273        return clans.Clan(
          -274            net=self._net,
          -275            id=int(id),
          -276            name=name,
          -277            type=enums.GroupType(type),
          -278            created_at=time.clean_date(created_at),
          -279            member_count=member_count,
          -280            motto=motto,
          -281            about=about,
          -282            is_public=is_public,
          -283            banner=banner,
          -284            avatar=avatar,
          -285            tags=tags,
          -286            features=features_obj,
          -287            owner=founder,
          -288            progressions=progression,
          -289            call_sign=information["clanCallsign"],
          -290            banner_data=information["clanBannerData"],
          -291            chat_security=data["chatSecurity"],
          -292            conversation_id=int(data["conversationId"]),
          -293            allow_chat=data["allowChat"],
          -294            theme=data["theme"],
          -295            current_user_membership=current_user_map,
          -296        )
          +263        founder: typedefs.NoneOr[clans.ClanMember] = None
          +264        if raw_founder := payload.get("founder"):
          +265            founder = self.deserialize_clan_member(raw_founder)
          +266
          +267        return clans.Clan(
          +268            net=self._net,
          +269            id=int(id),
          +270            name=name,
          +271            type=enums.GroupType(type),
          +272            created_at=time.clean_date(created_at),
          +273            member_count=member_count,
          +274            motto=motto,
          +275            about=about,
          +276            is_public=is_public,
          +277            banner=banner,
          +278            avatar=avatar,
          +279            tags=tags,
          +280            features=features_obj,
          +281            owner=founder,
          +282            progressions=progression,
          +283            call_sign=information["clanCallsign"],
          +284            banner_data=information["clanBannerData"],
          +285            chat_security=data["chatSecurity"],
          +286            conversation_id=int(data["conversationId"]),
          +287            allow_chat=data["allowChat"],
          +288            theme=data["theme"],
          +289            current_user_membership=current_user_map,
          +290        )
           
          @@ -5805,28 +5767,28 @@
          Returns
          -
          298    def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember:
          -299        destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"])
          -300        return clans.ClanMember(
          -301            net=self._net,
          -302            last_seen_name=destiny_user.last_seen_name,
          -303            id=destiny_user.id,
          -304            name=destiny_user.name,
          -305            icon=destiny_user.icon,
          -306            last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])),
          -307            group_id=int(data["groupId"]),
          -308            joined_at=time.clean_date(data["joinDate"]),
          -309            types=destiny_user.types,
          -310            is_public=destiny_user.is_public,
          -311            type=destiny_user.type,
          -312            code=destiny_user.code,
          -313            is_online=data["isOnline"],
          -314            crossave_override=destiny_user.crossave_override,
          -315            bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"])
          -316            if "bungieNetUserInfo" in data
          -317            else None,
          -318            member_type=enums.ClanMemberType(int(data["memberType"])),
          -319        )
          +            
          292    def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember:
          +293        destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"])
          +294        return clans.ClanMember(
          +295            net=self._net,
          +296            last_seen_name=destiny_user.last_seen_name,
          +297            id=destiny_user.id,
          +298            name=destiny_user.name,
          +299            icon=destiny_user.icon,
          +300            last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])),
          +301            group_id=int(data["groupId"]),
          +302            joined_at=time.clean_date(data["joinDate"]),
          +303            types=destiny_user.types,
          +304            is_public=destiny_user.is_public,
          +305            type=destiny_user.type,
          +306            code=destiny_user.code,
          +307            is_online=data["isOnline"],
          +308            crossave_override=destiny_user.crossave_override,
          +309            bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"])
          +310            if "bungieNetUserInfo" in data
          +311            else None,
          +312            member_type=enums.ClanMemberType(int(data["memberType"])),
          +313        )
           
          @@ -5853,18 +5815,18 @@
          Returns
          def - deserialize_clan_members( self, data: dict[str, typing.Any], /) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.clans.ClanMember]: + deserialize_clan_members( self, data: dict[str, typing.Any], /) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.clans.ClanMember]:
          -
          321    def deserialize_clan_members(
          -322        self, data: typedefs.JSONObject, /
          -323    ) -> iterators.FlatIterator[clans.ClanMember]:
          -324        return iterators.FlatIterator(
          -325            [self.deserialize_clan_member(member) for member in data["results"]]
          -326        )
          +            
          315    def deserialize_clan_members(
          +316        self, data: typedefs.JSONObject, /
          +317    ) -> iterators.Iterator[clans.ClanMember]:
          +318        return iterators.Iterator(
          +319            [self.deserialize_clan_member(member) for member in data["results"]]
          +320        )
           
          @@ -5880,7 +5842,7 @@
          Parameters
          Returns
          @@ -5897,21 +5859,21 @@
          Returns
          -
          328    def deserialize_group_member(
          -329        self, payload: typedefs.JSONObject
          -330    ) -> clans.GroupMember:
          -331        member = payload["member"]
          -332        return clans.GroupMember(
          -333            net=self._net,
          -334            join_date=time.clean_date(member["joinDate"]),
          -335            group_id=int(member["groupId"]),
          -336            member_type=enums.ClanMemberType(member["memberType"]),
          -337            is_online=member["isOnline"],
          -338            last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])),
          -339            inactive_memberships=payload.get("areAllMembershipsInactive", None),
          -340            member=self.deserialize_destiny_membership(member["destinyUserInfo"]),
          -341            group=self.deserialize_clan(payload["group"]),
          -342        )
          +            
          322    def deserialize_group_member(
          +323        self, payload: typedefs.JSONObject
          +324    ) -> clans.GroupMember:
          +325        member = payload["member"]
          +326        return clans.GroupMember(
          +327            net=self._net,
          +328            join_date=time.clean_date(member["joinDate"]),
          +329            group_id=int(member["groupId"]),
          +330            member_type=enums.ClanMemberType(member["memberType"]),
          +331            is_online=member["isOnline"],
          +332            last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])),
          +333            inactive_memberships=payload.get("areAllMembershipsInactive", None),
          +334            member=self.deserialize_destiny_membership(member["destinyUserInfo"]),
          +335            group=self.deserialize_clan(payload["group"]),
          +336        )
           
          @@ -5944,10 +5906,10 @@
          Returns
          -
          360    def deserialize_clan_conversations(
          -361        self, payload: typedefs.JSONArray
          -362    ) -> collections.Sequence[clans.ClanConversation]:
          -363        return [self._deserialize_clan_conversation(conv) for conv in payload]
          +            
          354    def deserialize_clan_conversations(
          +355        self, payload: typedefs.JSONArray
          +356    ) -> collections.Sequence[clans.ClanConversation]:
          +357        return [self._deserialize_clan_conversation(conv) for conv in payload]
           
          @@ -5980,18 +5942,18 @@
          Returns
          -
          365    def deserialize_app_owner(
          -366        self, payload: typedefs.JSONObject
          -367    ) -> application.ApplicationOwner:
          -368        return application.ApplicationOwner(
          -369            net=self._net,
          -370            name=payload.get("bungieGlobalDisplayName", undefined.Undefined),
          -371            id=int(payload["membershipId"]),
          -372            type=enums.MembershipType(payload["membershipType"]),
          -373            icon=assets.Image(str(payload["iconPath"])),
          -374            is_public=payload["isPublic"],
          -375            code=payload.get("bungieGlobalDisplayNameCode", None),
          -376        )
          +            
          359    def deserialize_app_owner(
          +360        self, payload: typedefs.JSONObject
          +361    ) -> application.ApplicationOwner:
          +362        return application.ApplicationOwner(
          +363            net=self._net,
          +364            name=payload.get("bungieGlobalDisplayName", undefined.Undefined),
          +365            id=int(payload["membershipId"]),
          +366            type=enums.MembershipType(payload["membershipType"]),
          +367            icon=assets.Image(str(payload["iconPath"])),
          +368            is_public=payload["isPublic"],
          +369            code=payload.get("bungieGlobalDisplayNameCode", None),
          +370        )
           
          @@ -6024,18 +5986,18 @@
          Returns
          -
          378    def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application:
          -379        return application.Application(
          -380            id=int(payload["applicationId"]),
          -381            name=payload["name"],
          -382            link=payload["link"],
          -383            status=payload["status"],
          -384            redirect_url=payload.get("redirectUrl", None),
          -385            created_at=time.clean_date(str(payload["creationDate"])),
          -386            published_at=time.clean_date(str(payload["firstPublished"])),
          -387            owner=self.deserialize_app_owner(payload["team"][0]["user"]),  # type: ignore
          -388            scope=payload.get("scope", undefined.Undefined),
          -389        )
          +            
          372    def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application:
          +373        return application.Application(
          +374            id=int(payload["applicationId"]),
          +375            name=payload["name"],
          +376            link=payload["link"],
          +377            status=payload["status"],
          +378            redirect_url=payload.get("redirectUrl", None),
          +379            created_at=time.clean_date(str(payload["creationDate"])),
          +380            published_at=time.clean_date(str(payload["firstPublished"])),
          +381            owner=self.deserialize_app_owner(payload["team"][0]["user"]),  # type: ignore
          +382            scope=payload.get("scope", undefined.Undefined),
          +383        )
           
          @@ -6068,31 +6030,31 @@
          Returns
          -
          412    def deserialize_profile(
          -413        self, payload: typedefs.JSONObject, /
          -414    ) -> typing.Optional[profile.Profile]:
          -415        if (raw_profile := payload.get("data")) is None:
          -416            return None
          -417
          -418        payload = raw_profile
          -419        id = int(payload["userInfo"]["membershipId"])
          -420        name = payload["userInfo"]["displayName"]
          -421        is_public = payload["userInfo"]["isPublic"]
          -422        type = enums.MembershipType(payload["userInfo"]["membershipType"])
          -423        last_played = time.clean_date(str(payload["dateLastPlayed"]))
          -424        character_ids = [int(cid) for cid in payload["characterIds"]]
          -425        power_cap = payload["currentSeasonRewardPowerCap"]
          -426
          -427        return profile.Profile(
          -428            id=int(id),
          -429            name=name,
          -430            is_public=is_public,
          -431            type=type,
          -432            last_played=last_played,
          -433            character_ids=character_ids,
          -434            power_cap=power_cap,
          -435            net=self._net,
          -436        )
          +            
          406    def deserialize_profile(
          +407        self, payload: typedefs.JSONObject, /
          +408    ) -> typing.Optional[profile.Profile]:
          +409        if (raw_profile := payload.get("data")) is None:
          +410            return None
          +411
          +412        payload = raw_profile
          +413        id = int(payload["userInfo"]["membershipId"])
          +414        name = payload["userInfo"]["displayName"]
          +415        is_public = payload["userInfo"]["isPublic"]
          +416        type = enums.MembershipType(payload["userInfo"]["membershipType"])
          +417        last_played = time.clean_date(str(payload["dateLastPlayed"]))
          +418        character_ids = [int(cid) for cid in payload["characterIds"]]
          +419        power_cap = payload["currentSeasonRewardPowerCap"]
          +420
          +421        return profile.Profile(
          +422            id=int(id),
          +423            name=name,
          +424            is_public=is_public,
          +425            type=type,
          +426            last_played=last_played,
          +427            character_ids=character_ids,
          +428            power_cap=power_cap,
          +429            net=self._net,
          +430        )
           
          @@ -6125,36 +6087,36 @@
          Returns
          -
          438    def deserialize_profile_item(
          -439        self, payload: typedefs.JSONObject
          -440    ) -> profile.ProfileItemImpl:
          -441
          -442        instance_id: typing.Optional[int] = None
          -443        if raw_instance_id := payload.get("itemInstanceId"):
          -444            instance_id = int(raw_instance_id)
          +            
          432    def deserialize_profile_item(
          +433        self, payload: typedefs.JSONObject
          +434    ) -> profile.ProfileItemImpl:
          +435
          +436        instance_id: typing.Optional[int] = None
          +437        if raw_instance_id := payload.get("itemInstanceId"):
          +438            instance_id = int(raw_instance_id)
          +439
          +440        version_number: typing.Optional[int] = None
          +441        if raw_version := payload.get("versionNumber"):
          +442            version_number = int(raw_version)
          +443
          +444        transfer_status = enums.TransferStatus(payload["transferStatus"])
           445
          -446        version_number: typing.Optional[int] = None
          -447        if raw_version := payload.get("versionNumber"):
          -448            version_number = int(raw_version)
          -449
          -450        transfer_status = enums.TransferStatus(payload["transferStatus"])
          -451
          -452        return profile.ProfileItemImpl(
          -453            net=self._net,
          -454            hash=payload["itemHash"],
          -455            quantity=payload["quantity"],
          -456            bind_status=enums.ItemBindStatus(payload["bindStatus"]),
          -457            location=enums.ItemLocation(payload["location"]),
          -458            bucket=payload["bucketHash"],
          -459            transfer_status=transfer_status,
          -460            lockable=payload["lockable"],
          -461            state=enums.ItemState(payload["state"]),
          -462            dismantel_permissions=payload["dismantlePermission"],
          -463            is_wrapper=payload["isWrapper"],
          -464            instance_id=instance_id,
          -465            version_number=version_number,
          -466            ornament_id=payload.get("overrideStyleItemHash"),
          -467        )
          +446        return profile.ProfileItemImpl(
          +447            net=self._net,
          +448            hash=payload["itemHash"],
          +449            quantity=payload["quantity"],
          +450            bind_status=enums.ItemBindStatus(payload["bindStatus"]),
          +451            location=enums.ItemLocation(payload["location"]),
          +452            bucket=payload["bucketHash"],
          +453            transfer_status=transfer_status,
          +454            lockable=payload["lockable"],
          +455            state=enums.ItemState(payload["state"]),
          +456            dismantel_permissions=payload["dismantlePermission"],
          +457            is_wrapper=payload["isWrapper"],
          +458            instance_id=instance_id,
          +459            version_number=version_number,
          +460            ornament_id=payload.get("overrideStyleItemHash"),
          +461        )
           
          @@ -6187,17 +6149,17 @@
          Returns
          -
          469    def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective:
          -470        return records.Objective(
          -471            net=self._net,
          -472            hash=payload["objectiveHash"],
          -473            visible=payload["visible"],
          -474            complete=payload["complete"],
          -475            completion_value=payload["completionValue"],
          -476            progress=payload.get("progress"),
          -477            destination_hash=payload.get("destinationHash"),
          -478            activity_hash=payload.get("activityHash"),
          -479        )
          +            
          463    def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective:
          +464        return records.Objective(
          +465            net=self._net,
          +466            hash=payload["objectiveHash"],
          +467            visible=payload["visible"],
          +468            complete=payload["complete"],
          +469            completion_value=payload["completionValue"],
          +470            progress=payload.get("progress"),
          +471            destination_hash=payload.get("destinationHash"),
          +472            activity_hash=payload.get("activityHash"),
          +473        )
           
          @@ -6230,37 +6192,37 @@
          Returns
          -
          481    def deserialize_records(
          -482        self,
          -483        payload: typedefs.JSONObject,
          -484        scores: typing.Optional[records.RecordScores] = None,
          -485        **nodes: int,
          -486    ) -> records.Record:
          -487        objectives: typing.Optional[list[records.Objective]] = None
          -488        interval_objectives: typing.Optional[list[records.Objective]] = None
          -489        record_state: typedefs.IntAnd[records.RecordState]
          -490
          -491        record_state = records.RecordState(payload["state"])
          -492
          -493        if raw_objs := payload.get("objectives"):
          -494            objectives = [self.deserialize_objectives(obj) for obj in raw_objs]
          -495
          -496        if raw_interval_objs := payload.get("intervalObjectives"):
          -497            interval_objectives = [
          -498                self.deserialize_objectives(obj) for obj in raw_interval_objs
          -499            ]
          -500
          -501        return records.Record(
          -502            scores=scores,
          -503            categories_node_hash=nodes.get("categories_hash", undefined.Undefined),
          -504            seals_node_hash=nodes.get("seals_hash", undefined.Undefined),
          -505            state=record_state,
          -506            objectives=objectives,
          -507            interval_objectives=interval_objectives,
          -508            redeemed_count=payload.get("intervalsRedeemedCount", 0),
          -509            completion_times=payload.get("completedCount", None),
          -510            reward_visibility=payload.get("rewardVisibilty", None),
          -511        )
          +            
          475    def deserialize_records(
          +476        self,
          +477        payload: typedefs.JSONObject,
          +478        scores: typing.Optional[records.RecordScores] = None,
          +479        **nodes: int,
          +480    ) -> records.Record:
          +481        objectives: typing.Optional[list[records.Objective]] = None
          +482        interval_objectives: typing.Optional[list[records.Objective]] = None
          +483        record_state: typedefs.IntAnd[records.RecordState]
          +484
          +485        record_state = records.RecordState(payload["state"])
          +486
          +487        if raw_objs := payload.get("objectives"):
          +488            objectives = [self.deserialize_objectives(obj) for obj in raw_objs]
          +489
          +490        if raw_interval_objs := payload.get("intervalObjectives"):
          +491            interval_objectives = [
          +492                self.deserialize_objectives(obj) for obj in raw_interval_objs
          +493            ]
          +494
          +495        return records.Record(
          +496            scores=scores,
          +497            categories_node_hash=nodes.get("categories_hash", undefined.Undefined),
          +498            seals_node_hash=nodes.get("seals_hash", undefined.Undefined),
          +499            state=record_state,
          +500            objectives=objectives,
          +501            interval_objectives=interval_objectives,
          +502            redeemed_count=payload.get("intervalsRedeemedCount", 0),
          +503            completion_times=payload.get("completedCount", None),
          +504            reward_visibility=payload.get("rewardVisibilty", None),
          +505        )
           
          @@ -6299,26 +6261,26 @@
          Returns
          -
          513    def deserialize_character_records(
          -514        self,
          -515        payload: typedefs.JSONObject,
          -516        scores: typing.Optional[records.RecordScores] = None,
          -517        record_hashes: typing.Optional[list[int]] = None,
          -518    ) -> records.CharacterRecord:
          -519
          -520        record = self.deserialize_records(payload, scores)
          -521        return records.CharacterRecord(
          -522            scores=scores,
          -523            categories_node_hash=record.categories_node_hash,
          -524            seals_node_hash=record.seals_node_hash,
          -525            state=record.state,
          -526            objectives=record.objectives,
          -527            interval_objectives=record.interval_objectives,
          -528            redeemed_count=payload.get("intervalsRedeemedCount", 0),
          -529            completion_times=payload.get("completedCount"),
          -530            reward_visibility=payload.get("rewardVisibilty"),
          -531            record_hashes=record_hashes or [],
          -532        )
          +            
          507    def deserialize_character_records(
          +508        self,
          +509        payload: typedefs.JSONObject,
          +510        scores: typing.Optional[records.RecordScores] = None,
          +511        record_hashes: typing.Optional[list[int]] = None,
          +512    ) -> records.CharacterRecord:
          +513
          +514        record = self.deserialize_records(payload, scores)
          +515        return records.CharacterRecord(
          +516            scores=scores,
          +517            categories_node_hash=record.categories_node_hash,
          +518            seals_node_hash=record.seals_node_hash,
          +519            state=record.state,
          +520            objectives=record.objectives,
          +521            interval_objectives=record.interval_objectives,
          +522            redeemed_count=payload.get("intervalsRedeemedCount", 0),
          +523            completion_times=payload.get("completedCount"),
          +524            reward_visibility=payload.get("rewardVisibilty"),
          +525            record_hashes=record_hashes or [],
          +526        )
           
          @@ -6354,10 +6316,10 @@
          Returns
          -
          534    def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye:
          -535        return character.Dye(
          -536            channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"]
          -537        )
          +            
          528    def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye:
          +529        return character.Dye(
          +530            channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"]
          +531        )
           
          @@ -6390,23 +6352,23 @@
          Returns
          -
          539    def deserialize_character_customization(
          -540        self, payload: typedefs.JSONObject
          -541    ) -> character.CustomizationOptions:
          -542        return character.CustomizationOptions(
          -543            personality=payload["personality"],
          -544            face=payload["face"],
          -545            skin_color=payload["skinColor"],
          -546            lip_color=payload["lipColor"],
          -547            eye_color=payload["eyeColor"],
          -548            hair_colors=payload.get("hairColors", []),
          -549            feature_colors=payload.get("featureColors", []),
          -550            decal_color=payload["decalColor"],
          -551            wear_helmet=payload["wearHelmet"],
          -552            hair_index=payload["hairIndex"],
          -553            feature_index=payload["featureIndex"],
          -554            decal_index=payload["decalIndex"],
          -555        )
          +            
          533    def deserialize_character_customization(
          +534        self, payload: typedefs.JSONObject
          +535    ) -> character.CustomizationOptions:
          +536        return character.CustomizationOptions(
          +537            personality=payload["personality"],
          +538            face=payload["face"],
          +539            skin_color=payload["skinColor"],
          +540            lip_color=payload["lipColor"],
          +541            eye_color=payload["eyeColor"],
          +542            hair_colors=payload.get("hairColors", []),
          +543            feature_colors=payload.get("featureColors", []),
          +544            decal_color=payload["decalColor"],
          +545            wear_helmet=payload["wearHelmet"],
          +546            hair_index=payload["hairIndex"],
          +547            feature_index=payload["featureIndex"],
          +548            decal_index=payload["decalIndex"],
          +549        )
           
          @@ -6440,16 +6402,16 @@
          Returns
          -
          557    def deserialize_character_minimal_equipments(
          -558        self, payload: typedefs.JSONObject
          -559    ) -> character.MinimalEquipments:
          -560        dyes = None
          -561        if raw_dyes := payload.get("dyes"):
          -562            if raw_dyes:
          -563                dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes]
          -564        return character.MinimalEquipments(
          -565            net=self._net, item_hash=payload["itemHash"], dyes=dyes
          -566        )
          +            
          551    def deserialize_character_minimal_equipments(
          +552        self, payload: typedefs.JSONObject
          +553    ) -> character.MinimalEquipments:
          +554        dyes = None
          +555        if raw_dyes := payload.get("dyes"):
          +556            if raw_dyes:
          +557                dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes]
          +558        return character.MinimalEquipments(
          +559            net=self._net, item_hash=payload["itemHash"], dyes=dyes
          +560        )
           
          @@ -6482,24 +6444,24 @@
          Returns
          -
          568    def deserialize_character_render_data(
          -569        self, payload: typedefs.JSONObject, /
          -570    ) -> character.RenderedData:
          -571        return character.RenderedData(
          -572            net=self._net,
          -573            customization=self.deserialize_character_customization(
          -574                payload["customization"]
          -575            ),
          -576            custom_dyes=[
          -577                self.deserialize_character_dye(dye)
          -578                for dye in payload["customDyes"]
          -579                if dye
          -580            ],
          -581            equipment=[
          -582                self.deserialize_character_minimal_equipments(equipment)
          -583                for equipment in payload["peerView"]["equipment"]
          -584            ],
          -585        )
          +            
          562    def deserialize_character_render_data(
          +563        self, payload: typedefs.JSONObject, /
          +564    ) -> character.RenderedData:
          +565        return character.RenderedData(
          +566            net=self._net,
          +567            customization=self.deserialize_character_customization(
          +568                payload["customization"]
          +569            ),
          +570            custom_dyes=[
          +571                self.deserialize_character_dye(dye)
          +572                for dye in payload["customDyes"]
          +573                if dye
          +574            ],
          +575            equipment=[
          +576                self.deserialize_character_minimal_equipments(equipment)
          +577                for equipment in payload["peerView"]["equipment"]
          +578            ],
          +579        )
           
          @@ -6532,20 +6494,20 @@
          Returns
          -
          587    def deserialize_available_activity(
          -588        self, payload: typedefs.JSONObject
          -589    ) -> activity.AvailableActivity:
          -590        return activity.AvailableActivity(
          -591            hash=payload["activityHash"],
          -592            is_new=payload["isNew"],
          -593            is_completed=payload["isCompleted"],
          -594            is_visible=payload["isVisible"],
          -595            display_level=payload.get("displayLevel"),
          -596            recommended_light=payload.get("recommendedLight"),
          -597            difficulty=activity.Difficulty(payload["difficultyTier"]),
          -598            can_join=payload["canJoin"],
          -599            can_lead=payload["canLead"],
          -600        )
          +            
          581    def deserialize_available_activity(
          +582        self, payload: typedefs.JSONObject
          +583    ) -> activity.AvailableActivity:
          +584        return activity.AvailableActivity(
          +585            hash=payload["activityHash"],
          +586            is_new=payload["isNew"],
          +587            is_completed=payload["isCompleted"],
          +588            is_visible=payload["isVisible"],
          +589            display_level=payload.get("displayLevel"),
          +590            recommended_light=payload.get("recommendedLight"),
          +591            difficulty=activity.Difficulty(payload["difficultyTier"]),
          +592            can_join=payload["canJoin"],
          +593            can_lead=payload["canLead"],
          +594        )
           
          @@ -6580,31 +6542,31 @@
          Returns
          -
          602    def deserialize_character_activity(
          -603        self, payload: typedefs.JSONObject
          -604    ) -> activity.CharacterActivity:
          -605        current_mode: typing.Optional[enums.GameMode] = None
          -606        if raw_current_mode := payload.get("currentActivityModeType"):
          -607            current_mode = enums.GameMode(raw_current_mode)
          -608
          -609        current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None
          -610        if raw_current_modes := payload.get("currentActivityModeTypes"):
          -611            current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes]
          -612
          -613        return activity.CharacterActivity(
          -614            date_started=time.clean_date(payload["dateActivityStarted"]),
          -615            current_hash=payload["currentActivityHash"],
          -616            current_mode_hash=payload["currentActivityModeHash"],
          -617            current_mode=current_mode,
          -618            current_mode_hashes=payload.get("currentActivityModeHashes"),
          -619            current_mode_types=current_mode_types,
          -620            current_playlist_hash=payload.get("currentPlaylistActivityHash"),
          -621            last_story_hash=payload["lastCompletedStoryHash"],
          -622            available_activities=[
          -623                self.deserialize_available_activity(activity_)
          -624                for activity_ in payload["availableActivities"]
          -625            ],
          -626        )
          +            
          596    def deserialize_character_activity(
          +597        self, payload: typedefs.JSONObject
          +598    ) -> activity.CharacterActivity:
          +599        current_mode: typing.Optional[enums.GameMode] = None
          +600        if raw_current_mode := payload.get("currentActivityModeType"):
          +601            current_mode = enums.GameMode(raw_current_mode)
          +602
          +603        current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None
          +604        if raw_current_modes := payload.get("currentActivityModeTypes"):
          +605            current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes]
          +606
          +607        return activity.CharacterActivity(
          +608            date_started=time.clean_date(payload["dateActivityStarted"]),
          +609            current_hash=payload["currentActivityHash"],
          +610            current_mode_hash=payload["currentActivityModeHash"],
          +611            current_mode=current_mode,
          +612            current_mode_hashes=payload.get("currentActivityModeHashes"),
          +613            current_mode_types=current_mode_types,
          +614            current_playlist_hash=payload.get("currentPlaylistActivityHash"),
          +615            last_story_hash=payload["lastCompletedStoryHash"],
          +616            available_activities=[
          +617                self.deserialize_available_activity(activity_)
          +618                for activity_ in payload["availableActivities"]
          +619            ],
          +620        )
           
          @@ -6637,10 +6599,10 @@
          Returns
          -
          628    def deserialize_profile_items(
          -629        self, payload: typedefs.JSONObject, /
          -630    ) -> list[profile.ProfileItemImpl]:
          -631        return [self.deserialize_profile_item(item) for item in payload["items"]]
          +            
          622    def deserialize_profile_items(
          +623        self, payload: typedefs.JSONObject, /
          +624    ) -> list[profile.ProfileItemImpl]:
          +625        return [self.deserialize_profile_item(item) for item in payload["items"]]
           
          @@ -6676,20 +6638,20 @@
          Returns
          -
          674    def deserialize_progressions(
          -675        self, payload: typedefs.JSONObject
          -676    ) -> progressions.Progression:
          -677        return progressions.Progression(
          -678            hash=int(payload["progressionHash"]),
          -679            level=int(payload["level"]),
          -680            cap=int(payload["levelCap"]),
          -681            daily_limit=int(payload["dailyLimit"]),
          -682            weekly_limit=int(payload["weeklyLimit"]),
          -683            current_progress=int(payload["currentProgress"]),
          -684            daily_progress=int(payload["dailyProgress"]),
          -685            needed=int(payload["progressToNextLevel"]),
          -686            next_level=int(payload["nextLevelAt"]),
          -687        )
          +            
          668    def deserialize_progressions(
          +669        self, payload: typedefs.JSONObject
          +670    ) -> progressions.Progression:
          +671        return progressions.Progression(
          +672            hash=int(payload["progressionHash"]),
          +673            level=int(payload["level"]),
          +674            cap=int(payload["levelCap"]),
          +675            daily_limit=int(payload["dailyLimit"]),
          +676            weekly_limit=int(payload["weeklyLimit"]),
          +677            current_progress=int(payload["currentProgress"]),
          +678            daily_progress=int(payload["dailyProgress"]),
          +679            needed=int(payload["progressToNextLevel"]),
          +680            next_level=int(payload["nextLevelAt"]),
          +681        )
           
          @@ -6707,63 +6669,63 @@
          Returns
          -
          775    def deserialize_milestone(
          -776        self, payload: typedefs.JSONObject
          -777    ) -> milestones.Milestone:
          -778        start_date: typing.Optional[datetime.datetime] = None
          -779        if raw_start_date := payload.get("startDate"):
          -780            start_date = time.clean_date(raw_start_date)
          -781
          -782        end_date: typing.Optional[datetime.datetime] = None
          -783        if raw_end_date := payload.get("endDate"):
          -784            end_date = time.clean_date(raw_end_date)
          -785
          -786        rewards: typing.Optional[
          -787            collections.Collection[milestones.MilestoneReward]
          -788        ] = None
          -789        if raw_rewards := payload.get("rewards"):
          -790            rewards = [
          -791                self._deserialize_milestone_rewards(reward) for reward in raw_rewards
          -792            ]
          -793
          -794        activities: typing.Optional[
          -795            collections.Sequence[milestones.MilestoneActivity]
          -796        ] = None
          -797        if raw_activities := payload.get("activities"):
          -798            activities = [
          -799                self._deserialize_milestone_activity(active)
          -800                for active in raw_activities
          -801            ]
          -802
          -803        quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None
          -804        if raw_quests := payload.get("availableQuests"):
          -805            quests = [
          -806                self._deserialize_milestone_available_quest(quest)
          -807                for quest in raw_quests
          -808            ]
          -809
          -810        vendors: typing.Optional[
          -811            collections.Sequence[milestones.MilestoneVendor]
          -812        ] = None
          -813        if raw_vendors := payload.get("vendors"):
          -814            vendors = [
          -815                milestones.MilestoneVendor(
          -816                    vendor_hash=vendor["vendorHash"],
          -817                    preview_itemhash=vendor.get("previewItemHash"),
          -818                )
          -819                for vendor in raw_vendors
          -820            ]
          -821
          -822        return milestones.Milestone(
          -823            hash=payload["milestoneHash"],
          -824            start_date=start_date,
          -825            end_date=end_date,
          -826            order=payload["order"],
          -827            rewards=rewards,
          -828            available_quests=quests,
          -829            activities=activities,
          -830            vendors=vendors,
          -831        )
          +            
          769    def deserialize_milestone(
          +770        self, payload: typedefs.JSONObject
          +771    ) -> milestones.Milestone:
          +772        start_date: typing.Optional[datetime.datetime] = None
          +773        if raw_start_date := payload.get("startDate"):
          +774            start_date = time.clean_date(raw_start_date)
          +775
          +776        end_date: typing.Optional[datetime.datetime] = None
          +777        if raw_end_date := payload.get("endDate"):
          +778            end_date = time.clean_date(raw_end_date)
          +779
          +780        rewards: typing.Optional[
          +781            collections.Collection[milestones.MilestoneReward]
          +782        ] = None
          +783        if raw_rewards := payload.get("rewards"):
          +784            rewards = [
          +785                self._deserialize_milestone_rewards(reward) for reward in raw_rewards
          +786            ]
          +787
          +788        activities: typing.Optional[
          +789            collections.Sequence[milestones.MilestoneActivity]
          +790        ] = None
          +791        if raw_activities := payload.get("activities"):
          +792            activities = [
          +793                self._deserialize_milestone_activity(active)
          +794                for active in raw_activities
          +795            ]
          +796
          +797        quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None
          +798        if raw_quests := payload.get("availableQuests"):
          +799            quests = [
          +800                self._deserialize_milestone_available_quest(quest)
          +801                for quest in raw_quests
          +802            ]
          +803
          +804        vendors: typing.Optional[
          +805            collections.Sequence[milestones.MilestoneVendor]
          +806        ] = None
          +807        if raw_vendors := payload.get("vendors"):
          +808            vendors = [
          +809                milestones.MilestoneVendor(
          +810                    vendor_hash=vendor["vendorHash"],
          +811                    preview_itemhash=vendor.get("previewItemHash"),
          +812                )
          +813                for vendor in raw_vendors
          +814            ]
          +815
          +816        return milestones.Milestone(
          +817            hash=payload["milestoneHash"],
          +818            start_date=start_date,
          +819            end_date=end_date,
          +820            order=payload["order"],
          +821            rewards=rewards,
          +822            available_quests=quests,
          +823            activities=activities,
          +824            vendors=vendors,
          +825        )
           
          @@ -6781,13 +6743,13 @@
          Returns
          -
          848    def deserialize_characters(
          -849        self, payload: typedefs.JSONObject
          -850    ) -> collections.Mapping[int, character.Character]:
          -851        return {
          -852            int(char_id): self._set_character_attrs(char)
          -853            for char_id, char in payload["data"].items()
          -854        }
          +            
          842    def deserialize_characters(
          +843        self, payload: typedefs.JSONObject
          +844    ) -> collections.Mapping[int, character.Character]:
          +845        return {
          +846            int(char_id): self._set_character_attrs(char)
          +847            for char_id, char in payload["data"].items()
          +848        }
           
          @@ -6805,10 +6767,10 @@
          Returns
          -
          856    def deserialize_character(
          -857        self, payload: typedefs.JSONObject
          -858    ) -> character.Character:
          -859        return self._set_character_attrs(payload)
          +            
          850    def deserialize_character(
          +851        self, payload: typedefs.JSONObject
          +852    ) -> character.Character:
          +853        return self._set_character_attrs(payload)
           
          @@ -6826,13 +6788,13 @@
          Returns
          -
          861    def deserialize_character_equipments(
          -862        self, payload: typedefs.JSONObject
          -863    ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]:
          -864        return {
          -865            int(char_id): self.deserialize_profile_items(item)
          -866            for char_id, item in payload["data"].items()
          -867        }
          +            
          855    def deserialize_character_equipments(
          +856        self, payload: typedefs.JSONObject
          +857    ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]:
          +858        return {
          +859            int(char_id): self.deserialize_profile_items(item)
          +860            for char_id, item in payload["data"].items()
          +861        }
           
          @@ -6850,13 +6812,13 @@
          Returns
          -
          869    def deserialize_character_activities(
          -870        self, payload: typedefs.JSONObject
          -871    ) -> collections.Mapping[int, activity.CharacterActivity]:
          -872        return {
          -873            int(char_id): self.deserialize_character_activity(data)
          -874            for char_id, data in payload["data"].items()
          -875        }
          +            
          863    def deserialize_character_activities(
          +864        self, payload: typedefs.JSONObject
          +865    ) -> collections.Mapping[int, activity.CharacterActivity]:
          +866        return {
          +867            int(char_id): self.deserialize_character_activity(data)
          +868            for char_id, data in payload["data"].items()
          +869        }
           
          @@ -6874,13 +6836,13 @@
          Returns
          -
          877    def deserialize_characters_render_data(
          -878        self, payload: typedefs.JSONObject
          -879    ) -> collections.Mapping[int, character.RenderedData]:
          -880        return {
          -881            int(char_id): self.deserialize_character_render_data(data)
          -882            for char_id, data in payload["data"].items()
          -883        }
          +            
          871    def deserialize_characters_render_data(
          +872        self, payload: typedefs.JSONObject
          +873    ) -> collections.Mapping[int, character.RenderedData]:
          +874        return {
          +875            int(char_id): self.deserialize_character_render_data(data)
          +876            for char_id, data in payload["data"].items()
          +877        }
           
          @@ -6898,48 +6860,48 @@
          Returns
          -
          885    def deserialize_character_progressions(
          -886        self, payload: typedefs.JSONObject
          -887    ) -> character.CharacterProgression:
          -888        progressions_ = {
          -889            int(prog_id): self.deserialize_progressions(prog)
          -890            for prog_id, prog in payload["progressions"].items()
          -891        }
          -892
          -893        factions = {
          -894            int(faction_id): self._deserialize_factions(faction)
          -895            for faction_id, faction in payload["factions"].items()
          -896        }
          -897
          -898        milestones_ = {
          -899            int(milestone_hash): self.deserialize_milestone(milestone)
          -900            for milestone_hash, milestone in payload["milestones"].items()
          -901        }
          -902
          -903        uninstanced_item_objectives = {
          -904            int(item_hash): [self.deserialize_objectives(ins) for ins in obj]
          -905            for item_hash, obj in payload["uninstancedItemObjectives"].items()
          -906        }
          -907
          -908        artifact = payload["seasonalArtifact"]
          -909        seasonal_artifact = season.CharacterScopedArtifact(
          -910            hash=artifact["artifactHash"],
          -911            points_used=artifact["pointsUsed"],
          -912            reset_count=artifact["resetCount"],
          -913            tiers=[
          -914                self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"]
          -915            ],
          -916        )
          -917        checklists = payload["checklists"]
          -918
          -919        return character.CharacterProgression(
          -920            progressions=progressions_,
          -921            factions=factions,
          -922            checklists=checklists,
          -923            milestones=milestones_,
          -924            seasonal_artifact=seasonal_artifact,
          -925            uninstanced_item_objectives=uninstanced_item_objectives,
          -926        )
          +            
          879    def deserialize_character_progressions(
          +880        self, payload: typedefs.JSONObject
          +881    ) -> character.CharacterProgression:
          +882        progressions_ = {
          +883            int(prog_id): self.deserialize_progressions(prog)
          +884            for prog_id, prog in payload["progressions"].items()
          +885        }
          +886
          +887        factions = {
          +888            int(faction_id): self._deserialize_factions(faction)
          +889            for faction_id, faction in payload["factions"].items()
          +890        }
          +891
          +892        milestones_ = {
          +893            int(milestone_hash): self.deserialize_milestone(milestone)
          +894            for milestone_hash, milestone in payload["milestones"].items()
          +895        }
          +896
          +897        uninstanced_item_objectives = {
          +898            int(item_hash): [self.deserialize_objectives(ins) for ins in obj]
          +899            for item_hash, obj in payload["uninstancedItemObjectives"].items()
          +900        }
          +901
          +902        artifact = payload["seasonalArtifact"]
          +903        seasonal_artifact = season.CharacterScopedArtifact(
          +904            hash=artifact["artifactHash"],
          +905            points_used=artifact["pointsUsed"],
          +906            reset_count=artifact["resetCount"],
          +907            tiers=[
          +908                self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"]
          +909            ],
          +910        )
          +911        checklists = payload["checklists"]
          +912
          +913        return character.CharacterProgression(
          +914            progressions=progressions_,
          +915            factions=factions,
          +916            checklists=checklists,
          +917            milestones=milestones_,
          +918            seasonal_artifact=seasonal_artifact,
          +919            uninstanced_item_objectives=uninstanced_item_objectives,
          +920        )
           
          @@ -6957,16 +6919,16 @@
          Returns
          -
          928    def deserialize_character_progressions_mapping(
          -929        self, payload: typedefs.JSONObject
          -930    ) -> collections.Mapping[int, character.CharacterProgression]:
          -931        character_progressions: collections.Mapping[
          -932            int, character.CharacterProgression
          -933        ] = {}
          -934        for char_id, data in payload["data"].items():
          -935            # A little hack to stop mypy complaining about Mapping <-> dict
          -936            character_progressions[int(char_id)] = self.deserialize_character_progressions(data)  # type: ignore[index]
          -937        return character_progressions
          +            
          922    def deserialize_character_progressions_mapping(
          +923        self, payload: typedefs.JSONObject
          +924    ) -> collections.Mapping[int, character.CharacterProgression]:
          +925        character_progressions: collections.Mapping[
          +926            int, character.CharacterProgression
          +927        ] = {}
          +928        for char_id, data in payload["data"].items():
          +929            # A little hack to stop mypy complaining about Mapping <-> dict
          +930            character_progressions[int(char_id)] = self.deserialize_character_progressions(data)  # type: ignore[index]
          +931        return character_progressions
           
          @@ -6984,17 +6946,17 @@
          Returns
          -
          939    def deserialize_characters_records(
          -940        self,
          -941        payload: typedefs.JSONObject,
          -942    ) -> collections.Mapping[int, records.CharacterRecord]:
          -943
          -944        return {
          -945            int(rec_id): self.deserialize_character_records(
          -946                rec, record_hashes=payload.get("featuredRecordHashes")
          -947            )
          -948            for rec_id, rec in payload["records"].items()
          -949        }
          +            
          933    def deserialize_characters_records(
          +934        self,
          +935        payload: typedefs.JSONObject,
          +936    ) -> collections.Mapping[int, records.CharacterRecord]:
          +937
          +938        return {
          +939            int(rec_id): self.deserialize_character_records(
          +940                rec, record_hashes=payload.get("featuredRecordHashes")
          +941            )
          +942            for rec_id, rec in payload["records"].items()
          +943        }
           
          @@ -7012,24 +6974,24 @@
          Returns
          -
          951    def deserialize_profile_records(
          -952        self, payload: typedefs.JSONObject
          -953    ) -> collections.Mapping[int, records.Record]:
          -954        raw_profile_records = payload["data"]
          -955        scores = records.RecordScores(
          -956            current_score=raw_profile_records["score"],
          -957            legacy_score=raw_profile_records["legacyScore"],
          -958            lifetime_score=raw_profile_records["lifetimeScore"],
          -959        )
          -960        return {
          -961            int(record_id): self.deserialize_records(
          -962                record,
          -963                scores,
          -964                categories_hash=raw_profile_records["recordCategoriesRootNodeHash"],
          -965                seals_hash=raw_profile_records["recordSealsRootNodeHash"],
          -966            )
          -967            for record_id, record in raw_profile_records["records"].items()
          -968        }
          +            
          945    def deserialize_profile_records(
          +946        self, payload: typedefs.JSONObject
          +947    ) -> collections.Mapping[int, records.Record]:
          +948        raw_profile_records = payload["data"]
          +949        scores = records.RecordScores(
          +950            current_score=raw_profile_records["score"],
          +951            legacy_score=raw_profile_records["legacyScore"],
          +952            lifetime_score=raw_profile_records["lifetimeScore"],
          +953        )
          +954        return {
          +955            int(record_id): self.deserialize_records(
          +956                record,
          +957                scores,
          +958                categories_hash=raw_profile_records["recordCategoriesRootNodeHash"],
          +959                seals_hash=raw_profile_records["recordSealsRootNodeHash"],
          +960            )
          +961            for record_id, record in raw_profile_records["records"].items()
          +962        }
           
          @@ -7047,18 +7009,18 @@
          Returns
          -
          1005    def deserialize_craftables_component(
          -1006        self, payload: typedefs.JSONObject
          -1007    ) -> components.CraftablesComponent:
          -1008        return components.CraftablesComponent(
          -1009            net=self._net,
          -1010            craftables={
          -1011                int(item_id): self._deserialize_craftable_item(item)
          -1012                for item_id, item in payload["craftables"].items()
          -1013                if item is not None
          -1014            },
          -1015            crafting_root_node_hash=payload["craftingRootNodeHash"],
          -1016        )
          +            
           999    def deserialize_craftables_component(
          +1000        self, payload: typedefs.JSONObject
          +1001    ) -> components.CraftablesComponent:
          +1002        return components.CraftablesComponent(
          +1003            net=self._net,
          +1004            craftables={
          +1005                int(item_id): self._deserialize_craftable_item(item)
          +1006                for item_id, item in payload["craftables"].items()
          +1007                if item is not None
          +1008            },
          +1009            crafting_root_node_hash=payload["craftingRootNodeHash"],
          +1010        )
           
          @@ -7076,273 +7038,273 @@
          Returns
          -
          1018    def deserialize_components(  # noqa: C901 Too complex.
          -1019        self, payload: typedefs.JSONObject
          -1020    ) -> components.Component:
          -1021
          -1022        profile_: typing.Optional[profile.Profile] = None
          -1023        if raw_profile := payload.get("profile"):
          -1024            profile_ = self.deserialize_profile(raw_profile)
          +            
          1012    def deserialize_components(  # noqa: C901 Too complex.
          +1013        self, payload: typedefs.JSONObject
          +1014    ) -> components.Component:
          +1015
          +1016        profile_: typing.Optional[profile.Profile] = None
          +1017        if raw_profile := payload.get("profile"):
          +1018            profile_ = self.deserialize_profile(raw_profile)
          +1019
          +1020        profile_progression: typing.Optional[profile.ProfileProgression] = None
          +1021        if raw_profile_progression := payload.get("profileProgression"):
          +1022            profile_progression = self.deserialize_profile_progression(
          +1023                raw_profile_progression
          +1024            )
           1025
          -1026        profile_progression: typing.Optional[profile.ProfileProgression] = None
          -1027        if raw_profile_progression := payload.get("profileProgression"):
          -1028            profile_progression = self.deserialize_profile_progression(
          -1029                raw_profile_progression
          -1030            )
          -1031
          -1032        profile_currencies: typing.Optional[
          -1033            collections.Sequence[profile.ProfileItemImpl]
          -1034        ] = None
          -1035        if raw_profile_currencies := payload.get("profileCurrencies"):
          -1036            if "data" in raw_profile_currencies:
          -1037                profile_currencies = self.deserialize_profile_items(
          -1038                    raw_profile_currencies["data"]
          -1039                )
          -1040
          -1041        profile_inventories: typing.Optional[
          -1042            collections.Sequence[profile.ProfileItemImpl]
          -1043        ] = None
          -1044        if raw_profile_inventories := payload.get("profileInventory"):
          -1045            if "data" in raw_profile_inventories:
          -1046                profile_inventories = self.deserialize_profile_items(
          -1047                    raw_profile_inventories["data"]
          -1048                )
          -1049
          -1050        profile_records: typing.Optional[
          -1051            collections.Mapping[int, records.Record]
          -1052        ] = None
          -1053
          -1054        if raw_profile_records_ := payload.get("profileRecords"):
          -1055            profile_records = self.deserialize_profile_records(raw_profile_records_)
          -1056
          -1057        characters: typing.Optional[typing.Mapping[int, character.Character]] = None
          -1058        if raw_characters := payload.get("characters"):
          -1059            characters = self.deserialize_characters(raw_characters)
          -1060
          -1061        character_records: typing.Optional[
          -1062            collections.Mapping[int, records.CharacterRecord]
          -1063        ] = None
          -1064
          -1065        if raw_character_records := payload.get("characterRecords"):
          -1066            # Had to do it in two steps..
          -1067            to_update: typedefs.JSONObject = {}
          -1068            for _, data in raw_character_records["data"].items():
          -1069                for record_id, record in data.items():
          -1070                    to_update[record_id] = record
          -1071
          -1072            character_records = {
          -1073                int(rec_id): self.deserialize_character_records(
          -1074                    rec, record_hashes=to_update.get("featuredRecordHashes")
          -1075                )
          -1076                for rec_id, rec in to_update["records"].items()
          -1077            }
          -1078
          -1079        character_equipments: typing.Optional[
          -1080            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
          -1081        ] = None
          -1082        if raw_character_equips := payload.get("characterEquipment"):
          -1083            character_equipments = self.deserialize_character_equipments(
          -1084                raw_character_equips
          -1085            )
          -1086
          -1087        character_inventories: typing.Optional[
          -1088            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
          -1089        ] = None
          -1090        if raw_character_inventories := payload.get("characterInventories"):
          -1091            if "data" in raw_character_inventories:
          -1092                character_inventories = self.deserialize_character_equipments(
          -1093                    raw_character_inventories
          -1094                )
          +1026        profile_currencies: typing.Optional[
          +1027            collections.Sequence[profile.ProfileItemImpl]
          +1028        ] = None
          +1029        if raw_profile_currencies := payload.get("profileCurrencies"):
          +1030            if "data" in raw_profile_currencies:
          +1031                profile_currencies = self.deserialize_profile_items(
          +1032                    raw_profile_currencies["data"]
          +1033                )
          +1034
          +1035        profile_inventories: typing.Optional[
          +1036            collections.Sequence[profile.ProfileItemImpl]
          +1037        ] = None
          +1038        if raw_profile_inventories := payload.get("profileInventory"):
          +1039            if "data" in raw_profile_inventories:
          +1040                profile_inventories = self.deserialize_profile_items(
          +1041                    raw_profile_inventories["data"]
          +1042                )
          +1043
          +1044        profile_records: typing.Optional[
          +1045            collections.Mapping[int, records.Record]
          +1046        ] = None
          +1047
          +1048        if raw_profile_records_ := payload.get("profileRecords"):
          +1049            profile_records = self.deserialize_profile_records(raw_profile_records_)
          +1050
          +1051        characters: typing.Optional[typing.Mapping[int, character.Character]] = None
          +1052        if raw_characters := payload.get("characters"):
          +1053            characters = self.deserialize_characters(raw_characters)
          +1054
          +1055        character_records: typing.Optional[
          +1056            collections.Mapping[int, records.CharacterRecord]
          +1057        ] = None
          +1058
          +1059        if raw_character_records := payload.get("characterRecords"):
          +1060            # Had to do it in two steps..
          +1061            to_update: typedefs.JSONObject = {}
          +1062            for _, data in raw_character_records["data"].items():
          +1063                for record_id, record in data.items():
          +1064                    to_update[record_id] = record
          +1065
          +1066            character_records = {
          +1067                int(rec_id): self.deserialize_character_records(
          +1068                    rec, record_hashes=to_update.get("featuredRecordHashes")
          +1069                )
          +1070                for rec_id, rec in to_update["records"].items()
          +1071            }
          +1072
          +1073        character_equipments: typing.Optional[
          +1074            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
          +1075        ] = None
          +1076        if raw_character_equips := payload.get("characterEquipment"):
          +1077            character_equipments = self.deserialize_character_equipments(
          +1078                raw_character_equips
          +1079            )
          +1080
          +1081        character_inventories: typing.Optional[
          +1082            collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]
          +1083        ] = None
          +1084        if raw_character_inventories := payload.get("characterInventories"):
          +1085            if "data" in raw_character_inventories:
          +1086                character_inventories = self.deserialize_character_equipments(
          +1087                    raw_character_inventories
          +1088                )
          +1089
          +1090        character_activities: typing.Optional[
          +1091            collections.Mapping[int, activity.CharacterActivity]
          +1092        ] = None
          +1093        if raw_char_acts := payload.get("characterActivities"):
          +1094            character_activities = self.deserialize_character_activities(raw_char_acts)
           1095
          -1096        character_activities: typing.Optional[
          -1097            collections.Mapping[int, activity.CharacterActivity]
          +1096        character_render_data: typing.Optional[
          +1097            collections.Mapping[int, character.RenderedData]
           1098        ] = None
          -1099        if raw_char_acts := payload.get("characterActivities"):
          -1100            character_activities = self.deserialize_character_activities(raw_char_acts)
          -1101
          -1102        character_render_data: typing.Optional[
          -1103            collections.Mapping[int, character.RenderedData]
          -1104        ] = None
          -1105        if raw_character_render_data := payload.get("characterRenderData"):
          -1106            character_render_data = self.deserialize_characters_render_data(
          -1107                raw_character_render_data
          -1108            )
          -1109
          -1110        character_progressions: typing.Optional[
          -1111            collections.Mapping[int, character.CharacterProgression]
          -1112        ] = None
          -1113
          -1114        if raw_character_progressions := payload.get("characterProgressions"):
          -1115            character_progressions = self.deserialize_character_progressions_mapping(
          -1116                raw_character_progressions
          -1117            )
          -1118
          -1119        profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None
          -1120        if raw_profile_string_vars := payload.get("profileStringVariables"):
          -1121            profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"]
          -1122
          -1123        character_string_vars: typing.Optional[
          -1124            collections.Mapping[int, collections.Mapping[int, int]]
          -1125        ] = None
          -1126        if raw_character_string_vars := payload.get("characterStringVariables"):
          -1127            character_string_vars = {
          -1128                int(char_id): data["integerValuesByHash"]
          -1129                for char_id, data in raw_character_string_vars["data"].items()
          -1130            }
          -1131
          -1132        metrics: typing.Optional[
          -1133            collections.Sequence[
          -1134                collections.Mapping[
          -1135                    int, tuple[bool, typing.Optional[records.Objective]]
          -1136                ]
          -1137            ]
          -1138        ] = None
          -1139        root_node_hash: typing.Optional[int] = None
          -1140
          -1141        if raw_metrics := payload.get("metrics"):
          -1142            root_node_hash = raw_metrics["data"]["metricsRootNodeHash"]
          -1143            metrics = [
          -1144                {
          -1145                    int(metrics_hash): (
          -1146                        data["invisible"],
          -1147                        self.deserialize_objectives(data["objectiveProgress"])
          -1148                        if "objectiveProgress" in data
          -1149                        else None,
          -1150                    )
          -1151                    for metrics_hash, data in raw_metrics["data"]["metrics"].items()
          -1152                }
          -1153            ]
          -1154        transitory: typing.Optional[fireteams.FireteamParty] = None
          -1155        if raw_transitory := payload.get("profileTransitoryData"):
          -1156            if "data" in raw_transitory:
          -1157                transitory = self.deserialize_fireteam_party(raw_transitory["data"])
          -1158
          -1159        item_components: typing.Optional[components.ItemsComponent] = None
          -1160        if raw_item_components := payload.get("itemComponents"):
          -1161            item_components = self.deserialize_items_component(raw_item_components)
          -1162
          -1163        profile_plugsets: typing.Optional[
          -1164            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
          -1165        ] = None
          +1099        if raw_character_render_data := payload.get("characterRenderData"):
          +1100            character_render_data = self.deserialize_characters_render_data(
          +1101                raw_character_render_data
          +1102            )
          +1103
          +1104        character_progressions: typing.Optional[
          +1105            collections.Mapping[int, character.CharacterProgression]
          +1106        ] = None
          +1107
          +1108        if raw_character_progressions := payload.get("characterProgressions"):
          +1109            character_progressions = self.deserialize_character_progressions_mapping(
          +1110                raw_character_progressions
          +1111            )
          +1112
          +1113        profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None
          +1114        if raw_profile_string_vars := payload.get("profileStringVariables"):
          +1115            profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"]
          +1116
          +1117        character_string_vars: typing.Optional[
          +1118            collections.Mapping[int, collections.Mapping[int, int]]
          +1119        ] = None
          +1120        if raw_character_string_vars := payload.get("characterStringVariables"):
          +1121            character_string_vars = {
          +1122                int(char_id): data["integerValuesByHash"]
          +1123                for char_id, data in raw_character_string_vars["data"].items()
          +1124            }
          +1125
          +1126        metrics: typing.Optional[
          +1127            collections.Sequence[
          +1128                collections.Mapping[
          +1129                    int, tuple[bool, typing.Optional[records.Objective]]
          +1130                ]
          +1131            ]
          +1132        ] = None
          +1133        root_node_hash: typing.Optional[int] = None
          +1134
          +1135        if raw_metrics := payload.get("metrics"):
          +1136            root_node_hash = raw_metrics["data"]["metricsRootNodeHash"]
          +1137            metrics = [
          +1138                {
          +1139                    int(metrics_hash): (
          +1140                        data["invisible"],
          +1141                        self.deserialize_objectives(data["objectiveProgress"])
          +1142                        if "objectiveProgress" in data
          +1143                        else None,
          +1144                    )
          +1145                    for metrics_hash, data in raw_metrics["data"]["metrics"].items()
          +1146                }
          +1147            ]
          +1148        transitory: typing.Optional[fireteams.FireteamParty] = None
          +1149        if raw_transitory := payload.get("profileTransitoryData"):
          +1150            if "data" in raw_transitory:
          +1151                transitory = self.deserialize_fireteam_party(raw_transitory["data"])
          +1152
          +1153        item_components: typing.Optional[components.ItemsComponent] = None
          +1154        if raw_item_components := payload.get("itemComponents"):
          +1155            item_components = self.deserialize_items_component(raw_item_components)
          +1156
          +1157        profile_plugsets: typing.Optional[
          +1158            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
          +1159        ] = None
          +1160
          +1161        if raw_profile_plugs := payload.get("profilePlugSets"):
          +1162            profile_plugsets = {
          +1163                int(index): [self.deserialize_plug_item_state(state) for state in data]
          +1164                for index, data in raw_profile_plugs["data"]["plugs"].items()
          +1165            }
           1166
          -1167        if raw_profile_plugs := payload.get("profilePlugSets"):
          -1168            profile_plugsets = {
          -1169                int(index): [self.deserialize_plug_item_state(state) for state in data]
          -1170                for index, data in raw_profile_plugs["data"]["plugs"].items()
          -1171            }
          -1172
          -1173        character_plugsets: typing.Optional[
          -1174            collections.Mapping[
          -1175                int, collections.Mapping[int, collections.Sequence[items.PlugItemState]]
          -1176            ]
          -1177        ] = None
          -1178        if raw_char_plugsets := payload.get("characterPlugSets"):
          -1179            character_plugsets = {
          -1180                int(char_id): {
          -1181                    int(index): [
          -1182                        self.deserialize_plug_item_state(state) for state in data
          -1183                    ]
          -1184                    for index, data in inner["plugs"].items()
          -1185                }
          -1186                for char_id, inner in raw_char_plugsets["data"].items()
          -1187            }
          -1188
          -1189        character_collectibles: typing.Optional[
          -1190            collections.Mapping[int, items.Collectible]
          -1191        ] = None
          -1192        if raw_character_collectibles := payload.get("characterCollectibles"):
          -1193            character_collectibles = {
          -1194                int(char_id): self._deserialize_collectible(data)
          -1195                for char_id, data in raw_character_collectibles["data"].items()
          -1196            }
          +1167        character_plugsets: typing.Optional[
          +1168            collections.Mapping[
          +1169                int, collections.Mapping[int, collections.Sequence[items.PlugItemState]]
          +1170            ]
          +1171        ] = None
          +1172        if raw_char_plugsets := payload.get("characterPlugSets"):
          +1173            character_plugsets = {
          +1174                int(char_id): {
          +1175                    int(index): [
          +1176                        self.deserialize_plug_item_state(state) for state in data
          +1177                    ]
          +1178                    for index, data in inner["plugs"].items()
          +1179                }
          +1180                for char_id, inner in raw_char_plugsets["data"].items()
          +1181            }
          +1182
          +1183        character_collectibles: typing.Optional[
          +1184            collections.Mapping[int, items.Collectible]
          +1185        ] = None
          +1186        if raw_character_collectibles := payload.get("characterCollectibles"):
          +1187            character_collectibles = {
          +1188                int(char_id): self._deserialize_collectible(data)
          +1189                for char_id, data in raw_character_collectibles["data"].items()
          +1190            }
          +1191
          +1192        profile_collectibles: typing.Optional[items.Collectible] = None
          +1193        if raw_profile_collectibles := payload.get("profileCollectibles"):
          +1194            profile_collectibles = self._deserialize_collectible(
          +1195                raw_profile_collectibles["data"]
          +1196            )
           1197
          -1198        profile_collectibles: typing.Optional[items.Collectible] = None
          -1199        if raw_profile_collectibles := payload.get("profileCollectibles"):
          -1200            profile_collectibles = self._deserialize_collectible(
          -1201                raw_profile_collectibles["data"]
          -1202            )
          -1203
          -1204        profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
          -1205        if raw_profile_nodes := payload.get("profilePresentationNodes"):
          -1206            profile_nodes = {
          -1207                int(node_hash): self._deserialize_node(node)
          -1208                for node_hash, node in raw_profile_nodes["data"]["nodes"].items()
          -1209            }
          -1210
          -1211        character_nodes: typing.Optional[
          -1212            collections.Mapping[int, collections.Mapping[int, records.Node]]
          -1213        ] = None
          -1214        if raw_character_nodes := payload.get("characterPresentationNodes"):
          -1215            character_nodes = {
          -1216                int(char_id): {
          -1217                    int(node_hash): self._deserialize_node(node)
          -1218                    for node_hash, node in each_character["nodes"].items()
          -1219                }
          -1220                for char_id, each_character in raw_character_nodes["data"].items()
          -1221            }
          -1222
          -1223        platform_silver: typing.Optional[
          -1224            collections.Mapping[str, profile.ProfileItemImpl]
          -1225        ] = None
          -1226        if raw_platform_silver := payload.get("platformSilver"):
          -1227            if "data" in raw_platform_silver:
          -1228                platform_silver = {
          -1229                    platform_name: self.deserialize_profile_item(item)
          -1230                    for platform_name, item in raw_platform_silver["data"][
          -1231                        "platformSilver"
          -1232                    ].items()
          -1233                }
          -1234
          -1235        character_currency_lookups: typing.Optional[
          -1236            collections.Mapping[int, collections.Sequence[items.Currency]]
          -1237        ] = None
          -1238        if raw_char_lookups := payload.get("characterCurrencyLookups"):
          -1239            if "data" in raw_char_lookups:
          -1240                character_currency_lookups = {
          -1241                    int(char_id): self._deserialize_currencies(currencie)
          -1242                    for char_id, currencie in raw_char_lookups["data"].items()
          -1243                }
          -1244
          -1245        character_craftables: typing.Optional[
          -1246            collections.Mapping[int, components.CraftablesComponent]
          -1247        ] = None
          -1248        if raw_character_craftables := payload.get("characterCraftables"):
          +1198        profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
          +1199        if raw_profile_nodes := payload.get("profilePresentationNodes"):
          +1200            profile_nodes = {
          +1201                int(node_hash): self._deserialize_node(node)
          +1202                for node_hash, node in raw_profile_nodes["data"]["nodes"].items()
          +1203            }
          +1204
          +1205        character_nodes: typing.Optional[
          +1206            collections.Mapping[int, collections.Mapping[int, records.Node]]
          +1207        ] = None
          +1208        if raw_character_nodes := payload.get("characterPresentationNodes"):
          +1209            character_nodes = {
          +1210                int(char_id): {
          +1211                    int(node_hash): self._deserialize_node(node)
          +1212                    for node_hash, node in each_character["nodes"].items()
          +1213                }
          +1214                for char_id, each_character in raw_character_nodes["data"].items()
          +1215            }
          +1216
          +1217        platform_silver: typing.Optional[
          +1218            collections.Mapping[str, profile.ProfileItemImpl]
          +1219        ] = None
          +1220        if raw_platform_silver := payload.get("platformSilver"):
          +1221            if "data" in raw_platform_silver:
          +1222                platform_silver = {
          +1223                    platform_name: self.deserialize_profile_item(item)
          +1224                    for platform_name, item in raw_platform_silver["data"][
          +1225                        "platformSilver"
          +1226                    ].items()
          +1227                }
          +1228
          +1229        character_currency_lookups: typing.Optional[
          +1230            collections.Mapping[int, collections.Sequence[items.Currency]]
          +1231        ] = None
          +1232        if raw_char_lookups := payload.get("characterCurrencyLookups"):
          +1233            if "data" in raw_char_lookups:
          +1234                character_currency_lookups = {
          +1235                    int(char_id): self._deserialize_currencies(currencie)
          +1236                    for char_id, currencie in raw_char_lookups["data"].items()
          +1237                }
          +1238
          +1239        character_craftables: typing.Optional[
          +1240            collections.Mapping[int, components.CraftablesComponent]
          +1241        ] = None
          +1242        if raw_character_craftables := payload.get("characterCraftables"):
          +1243
          +1244            if "data" in raw_character_craftables:
          +1245                character_craftables = {
          +1246                    int(char_id): self.deserialize_craftables_component(craftable)
          +1247                    for char_id, craftable in raw_character_craftables["data"].items()
          +1248                }
           1249
          -1250            if "data" in raw_character_craftables:
          -1251                character_craftables = {
          -1252                    int(char_id): self.deserialize_craftables_component(craftable)
          -1253                    for char_id, craftable in raw_character_craftables["data"].items()
          -1254                }
          -1255
          -1256        return components.Component(
          -1257            profiles=profile_,
          -1258            profile_progression=profile_progression,
          -1259            profile_currencies=profile_currencies,
          -1260            profile_inventories=profile_inventories,
          -1261            profile_records=profile_records,
          -1262            characters=characters,
          -1263            character_records=character_records,
          -1264            character_equipments=character_equipments,
          -1265            character_inventories=character_inventories,
          -1266            character_activities=character_activities,
          -1267            character_render_data=character_render_data,
          -1268            character_progressions=character_progressions,
          -1269            profile_string_variables=profile_string_vars,
          -1270            character_string_variables=character_string_vars,
          -1271            metrics=metrics,
          -1272            root_node_hash=root_node_hash,
          -1273            transitory=transitory,
          -1274            item_components=item_components,
          -1275            profile_plugsets=profile_plugsets,
          -1276            character_plugsets=character_plugsets,
          -1277            character_collectibles=character_collectibles,
          -1278            profile_collectibles=profile_collectibles,
          -1279            profile_nodes=profile_nodes,
          -1280            character_nodes=character_nodes,
          -1281            platform_silver=platform_silver,
          -1282            character_currency_lookups=character_currency_lookups,
          -1283            character_craftables=character_craftables,
          -1284        )
          +1250        return components.Component(
          +1251            profiles=profile_,
          +1252            profile_progression=profile_progression,
          +1253            profile_currencies=profile_currencies,
          +1254            profile_inventories=profile_inventories,
          +1255            profile_records=profile_records,
          +1256            characters=characters,
          +1257            character_records=character_records,
          +1258            character_equipments=character_equipments,
          +1259            character_inventories=character_inventories,
          +1260            character_activities=character_activities,
          +1261            character_render_data=character_render_data,
          +1262            character_progressions=character_progressions,
          +1263            profile_string_variables=profile_string_vars,
          +1264            character_string_variables=character_string_vars,
          +1265            metrics=metrics,
          +1266            root_node_hash=root_node_hash,
          +1267            transitory=transitory,
          +1268            item_components=item_components,
          +1269            profile_plugsets=profile_plugsets,
          +1270            character_plugsets=character_plugsets,
          +1271            character_collectibles=character_collectibles,
          +1272            profile_collectibles=profile_collectibles,
          +1273            profile_nodes=profile_nodes,
          +1274            character_nodes=character_nodes,
          +1275            platform_silver=platform_silver,
          +1276            character_currency_lookups=character_currency_lookups,
          +1277            character_craftables=character_craftables,
          +1278        )
           
          @@ -7376,113 +7338,113 @@
          Returns
          -
          1286    def deserialize_items_component(
          -1287        self, payload: typedefs.JSONObject
          -1288    ) -> components.ItemsComponent:
          -1289        instances: typing.Optional[
          -1290            collections.Sequence[collections.Mapping[int, items.ItemInstance]]
          -1291        ] = None
          -1292        if raw_instances := payload.get("instances"):
          -1293            instances = [
          -1294                {
          -1295                    int(ins_id): self.deserialize_instanced_item(item)
          -1296                    for ins_id, item in raw_instances["data"].items()
          -1297                }
          -1298            ]
          -1299
          -1300        render_data: typing.Optional[
          -1301            collections.Mapping[int, tuple[bool, dict[int, int]]]
          -1302        ] = None
          -1303        if raw_render_data := payload.get("renderData"):
          -1304            render_data = {
          -1305                int(ins_id): (data["useCustomDyes"], data["artRegions"])
          -1306                for ins_id, data in raw_render_data["data"].items()
          -1307            }
          -1308
          -1309        stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None
          -1310        if raw_stats := payload.get("stats"):
          -1311            builder: collections.Mapping[int, items.ItemStatsView] = {}
          -1312            for ins_id, stat in raw_stats["data"].items():
          -1313                for _, items_ in stat.items():
          -1314                    builder[int(ins_id)] = self.deserialize_item_stats_view(items_)  # type: ignore[index]
          -1315            stats = builder
          -1316
          -1317        sockets: typing.Optional[
          -1318            collections.Mapping[int, collections.Sequence[items.ItemSocket]]
          -1319        ] = None
          -1320        if raw_sockets := payload.get("sockets"):
          -1321            sockets = {
          -1322                int(ins_id): [
          -1323                    self.deserialize_item_socket(socket) for socket in item["sockets"]
          -1324                ]
          -1325                for ins_id, item in raw_sockets["data"].items()
          -1326            }
          -1327
          -1328        objeectives: typing.Optional[
          -1329            collections.Mapping[int, collections.Sequence[records.Objective]]
          -1330        ] = None
          -1331        if raw_objectives := payload.get("objectives"):
          -1332            objeectives = {
          -1333                int(ins_id): [self.deserialize_objectives(objective)]
          -1334                for ins_id, data in raw_objectives["data"].items()
          -1335                for objective in data["objectives"]
          -1336            }
          -1337
          -1338        perks: typing.Optional[
          -1339            collections.Mapping[int, collections.Collection[items.ItemPerk]]
          -1340        ] = None
          -1341        if raw_perks := payload.get("perks"):
          -1342            perks = {
          -1343                int(ins_id): [
          -1344                    self.deserialize_item_perk(perk) for perk in item["perks"]
          -1345                ]
          -1346                for ins_id, item in raw_perks["data"].items()
          -1347            }
          -1348
          -1349        plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None
          -1350        if raw_plug_states := payload.get("plugStates"):
          -1351            pending_states: list[items.PlugItemState] = []
          -1352            for _, plug in raw_plug_states["data"].items():
          -1353                pending_states.append(self.deserialize_plug_item_state(plug))
          -1354            plug_states = pending_states
          -1355
          -1356        reusable_plugs: typing.Optional[
          -1357            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
          -1358        ] = None
          -1359        if raw_re_plugs := payload.get("reusablePlugs"):
          -1360            reusable_plugs = {
          -1361                int(ins_id): [
          -1362                    self.deserialize_plug_item_state(state) for state in inner
          -1363                ]
          -1364                for ins_id, plug in raw_re_plugs["data"].items()
          -1365                for inner in list(plug["plugs"].values())
          -1366            }
          -1367
          -1368        plug_objectives: typing.Optional[
          -1369            collections.Mapping[
          -1370                int, collections.Mapping[int, collections.Collection[records.Objective]]
          -1371            ]
          -1372        ] = None
          -1373        if raw_plug_objectives := payload.get("plugObjectives"):
          -1374            plug_objectives = {
          -1375                int(ins_id): {
          -1376                    int(obj_hash): [self.deserialize_objectives(obj) for obj in objs]
          -1377                    for obj_hash, objs in inner["objectivesPerPlug"].items()
          -1378                }
          -1379                for ins_id, inner in raw_plug_objectives["data"].items()
          -1380            }
          -1381
          -1382        return components.ItemsComponent(
          -1383            sockets=sockets,
          -1384            stats=stats,
          -1385            render_data=render_data,
          -1386            instances=instances,
          -1387            objectives=objeectives,
          -1388            perks=perks,
          -1389            plug_states=plug_states,
          -1390            reusable_plugs=reusable_plugs,
          -1391            plug_objectives=plug_objectives,
          -1392        )
          +            
          1280    def deserialize_items_component(
          +1281        self, payload: typedefs.JSONObject
          +1282    ) -> components.ItemsComponent:
          +1283        instances: typing.Optional[
          +1284            collections.Sequence[collections.Mapping[int, items.ItemInstance]]
          +1285        ] = None
          +1286        if raw_instances := payload.get("instances"):
          +1287            instances = [
          +1288                {
          +1289                    int(ins_id): self.deserialize_instanced_item(item)
          +1290                    for ins_id, item in raw_instances["data"].items()
          +1291                }
          +1292            ]
          +1293
          +1294        render_data: typing.Optional[
          +1295            collections.Mapping[int, tuple[bool, dict[int, int]]]
          +1296        ] = None
          +1297        if raw_render_data := payload.get("renderData"):
          +1298            render_data = {
          +1299                int(ins_id): (data["useCustomDyes"], data["artRegions"])
          +1300                for ins_id, data in raw_render_data["data"].items()
          +1301            }
          +1302
          +1303        stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None
          +1304        if raw_stats := payload.get("stats"):
          +1305            builder: collections.Mapping[int, items.ItemStatsView] = {}
          +1306            for ins_id, stat in raw_stats["data"].items():
          +1307                for _, items_ in stat.items():
          +1308                    builder[int(ins_id)] = self.deserialize_item_stats_view(items_)  # type: ignore[index]
          +1309            stats = builder
          +1310
          +1311        sockets: typing.Optional[
          +1312            collections.Mapping[int, collections.Sequence[items.ItemSocket]]
          +1313        ] = None
          +1314        if raw_sockets := payload.get("sockets"):
          +1315            sockets = {
          +1316                int(ins_id): [
          +1317                    self.deserialize_item_socket(socket) for socket in item["sockets"]
          +1318                ]
          +1319                for ins_id, item in raw_sockets["data"].items()
          +1320            }
          +1321
          +1322        objeectives: typing.Optional[
          +1323            collections.Mapping[int, collections.Sequence[records.Objective]]
          +1324        ] = None
          +1325        if raw_objectives := payload.get("objectives"):
          +1326            objeectives = {
          +1327                int(ins_id): [self.deserialize_objectives(objective)]
          +1328                for ins_id, data in raw_objectives["data"].items()
          +1329                for objective in data["objectives"]
          +1330            }
          +1331
          +1332        perks: typing.Optional[
          +1333            collections.Mapping[int, collections.Collection[items.ItemPerk]]
          +1334        ] = None
          +1335        if raw_perks := payload.get("perks"):
          +1336            perks = {
          +1337                int(ins_id): [
          +1338                    self.deserialize_item_perk(perk) for perk in item["perks"]
          +1339                ]
          +1340                for ins_id, item in raw_perks["data"].items()
          +1341            }
          +1342
          +1343        plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None
          +1344        if raw_plug_states := payload.get("plugStates"):
          +1345            pending_states: list[items.PlugItemState] = []
          +1346            for _, plug in raw_plug_states["data"].items():
          +1347                pending_states.append(self.deserialize_plug_item_state(plug))
          +1348            plug_states = pending_states
          +1349
          +1350        reusable_plugs: typing.Optional[
          +1351            collections.Mapping[int, collections.Sequence[items.PlugItemState]]
          +1352        ] = None
          +1353        if raw_re_plugs := payload.get("reusablePlugs"):
          +1354            reusable_plugs = {
          +1355                int(ins_id): [
          +1356                    self.deserialize_plug_item_state(state) for state in inner
          +1357                ]
          +1358                for ins_id, plug in raw_re_plugs["data"].items()
          +1359                for inner in list(plug["plugs"].values())
          +1360            }
          +1361
          +1362        plug_objectives: typing.Optional[
          +1363            collections.Mapping[
          +1364                int, collections.Mapping[int, collections.Collection[records.Objective]]
          +1365            ]
          +1366        ] = None
          +1367        if raw_plug_objectives := payload.get("plugObjectives"):
          +1368            plug_objectives = {
          +1369                int(ins_id): {
          +1370                    int(obj_hash): [self.deserialize_objectives(obj) for obj in objs]
          +1371                    for obj_hash, objs in inner["objectivesPerPlug"].items()
          +1372                }
          +1373                for ins_id, inner in raw_plug_objectives["data"].items()
          +1374            }
          +1375
          +1376        return components.ItemsComponent(
          +1377            sockets=sockets,
          +1378            stats=stats,
          +1379            render_data=render_data,
          +1380            instances=instances,
          +1381            objectives=objeectives,
          +1382            perks=perks,
          +1383            plug_states=plug_states,
          +1384            reusable_plugs=reusable_plugs,
          +1385            plug_objectives=plug_objectives,
          +1386        )
           
          @@ -7502,81 +7464,81 @@
          Returns
          -
          1394    def deserialize_character_component(  # type: ignore[call-arg]
          -1395        self, payload: typedefs.JSONObject
          -1396    ) -> components.CharacterComponent:
          -1397
          -1398        character_: typing.Optional[character.Character] = None
          -1399        if raw_singuler_character := payload.get("character"):
          -1400            character_ = self.deserialize_character(raw_singuler_character["data"])
          -1401
          -1402        inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
          -1403        if raw_inventory := payload.get("inventory"):
          -1404            if "data" in raw_inventory:
          -1405                inventory = self.deserialize_profile_items(raw_inventory["data"])
          -1406
          -1407        activities: typing.Optional[activity.CharacterActivity] = None
          -1408        if raw_activities := payload.get("activities"):
          -1409            activities = self.deserialize_character_activity(raw_activities["data"])
          -1410
          -1411        equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
          -1412        if raw_equipments := payload.get("equipment"):
          -1413            equipment = self.deserialize_profile_items(raw_equipments["data"])
          +            
          1388    def deserialize_character_component(  # type: ignore[call-arg]
          +1389        self, payload: typedefs.JSONObject
          +1390    ) -> components.CharacterComponent:
          +1391
          +1392        character_: typing.Optional[character.Character] = None
          +1393        if raw_singuler_character := payload.get("character"):
          +1394            character_ = self.deserialize_character(raw_singuler_character["data"])
          +1395
          +1396        inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
          +1397        if raw_inventory := payload.get("inventory"):
          +1398            if "data" in raw_inventory:
          +1399                inventory = self.deserialize_profile_items(raw_inventory["data"])
          +1400
          +1401        activities: typing.Optional[activity.CharacterActivity] = None
          +1402        if raw_activities := payload.get("activities"):
          +1403            activities = self.deserialize_character_activity(raw_activities["data"])
          +1404
          +1405        equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None
          +1406        if raw_equipments := payload.get("equipment"):
          +1407            equipment = self.deserialize_profile_items(raw_equipments["data"])
          +1408
          +1409        progressions_: typing.Optional[character.CharacterProgression] = None
          +1410        if raw_progressions := payload.get("progressions"):
          +1411            progressions_ = self.deserialize_character_progressions(
          +1412                raw_progressions["data"]
          +1413            )
           1414
          -1415        progressions_: typing.Optional[character.CharacterProgression] = None
          -1416        if raw_progressions := payload.get("progressions"):
          -1417            progressions_ = self.deserialize_character_progressions(
          -1418                raw_progressions["data"]
          +1415        render_data: typing.Optional[character.RenderedData] = None
          +1416        if raw_render_data := payload.get("renderData"):
          +1417            render_data = self.deserialize_character_render_data(
          +1418                raw_render_data["data"]
           1419            )
           1420
          -1421        render_data: typing.Optional[character.RenderedData] = None
          -1422        if raw_render_data := payload.get("renderData"):
          -1423            render_data = self.deserialize_character_render_data(
          -1424                raw_render_data["data"]
          -1425            )
          -1426
          -1427        character_records: typing.Optional[
          -1428            collections.Mapping[int, records.CharacterRecord]
          -1429        ] = None
          -1430        if raw_char_records := payload.get("records"):
          -1431            character_records = self.deserialize_characters_records(
          -1432                raw_char_records["data"]
          -1433            )
          -1434
          -1435        item_components: typing.Optional[components.ItemsComponent] = None
          -1436        if raw_item_components := payload.get("itemComponents"):
          -1437            item_components = self.deserialize_items_component(raw_item_components)
          -1438
          -1439        nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
          -1440        if raw_nodes := payload.get("presentationNodes"):
          -1441            nodes = {
          -1442                int(node_hash): self._deserialize_node(node)
          -1443                for node_hash, node in raw_nodes["data"]["nodes"].items()
          -1444            }
          -1445
          -1446        collectibles: typing.Optional[items.Collectible] = None
          -1447        if raw_collectibles := payload.get("collectibles"):
          -1448            collectibles = self._deserialize_collectible(raw_collectibles["data"])
          -1449
          -1450        currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None
          -1451        if raw_currencies := payload.get("currencyLookups"):
          -1452            if "data" in raw_currencies:
          -1453                currency_lookups = self._deserialize_currencies(raw_currencies)
          -1454
          -1455        return components.CharacterComponent(
          -1456            activities=activities,
          -1457            equipment=equipment,
          -1458            inventory=inventory,
          -1459            progressions=progressions_,
          -1460            render_data=render_data,
          -1461            character=character_,
          -1462            character_records=character_records,
          -1463            profile_records=None,
          -1464            item_components=item_components,
          -1465            currency_lookups=currency_lookups,
          -1466            collectibles=collectibles,
          -1467            nodes=nodes,
          -1468        )
          +1421        character_records: typing.Optional[
          +1422            collections.Mapping[int, records.CharacterRecord]
          +1423        ] = None
          +1424        if raw_char_records := payload.get("records"):
          +1425            character_records = self.deserialize_characters_records(
          +1426                raw_char_records["data"]
          +1427            )
          +1428
          +1429        item_components: typing.Optional[components.ItemsComponent] = None
          +1430        if raw_item_components := payload.get("itemComponents"):
          +1431            item_components = self.deserialize_items_component(raw_item_components)
          +1432
          +1433        nodes: typing.Optional[collections.Mapping[int, records.Node]] = None
          +1434        if raw_nodes := payload.get("presentationNodes"):
          +1435            nodes = {
          +1436                int(node_hash): self._deserialize_node(node)
          +1437                for node_hash, node in raw_nodes["data"]["nodes"].items()
          +1438            }
          +1439
          +1440        collectibles: typing.Optional[items.Collectible] = None
          +1441        if raw_collectibles := payload.get("collectibles"):
          +1442            collectibles = self._deserialize_collectible(raw_collectibles["data"])
          +1443
          +1444        currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None
          +1445        if raw_currencies := payload.get("currencyLookups"):
          +1446            if "data" in raw_currencies:
          +1447                currency_lookups = self._deserialize_currencies(raw_currencies)
          +1448
          +1449        return components.CharacterComponent(
          +1450            activities=activities,
          +1451            equipment=equipment,
          +1452            inventory=inventory,
          +1453            progressions=progressions_,
          +1454            render_data=render_data,
          +1455            character=character_,
          +1456            character_records=character_records,
          +1457            profile_records=None,
          +1458            item_components=item_components,
          +1459            currency_lookups=currency_lookups,
          +1460            collectibles=collectibles,
          +1461            nodes=nodes,
          +1462        )
           
          @@ -7603,38 +7565,38 @@
          Returns
          def - deserialize_inventory_results( self, payload: dict[str, typing.Any]) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.entity.SearchableEntity]: + deserialize_inventory_results( self, payload: dict[str, typing.Any]) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.entity.SearchableEntity]:
          -
          1496    def deserialize_inventory_results(
          -1497        self, payload: typedefs.JSONObject
          -1498    ) -> iterators.FlatIterator[entity.SearchableEntity]:
          -1499        suggested_words: list[str] = payload["suggestedWords"]
          -1500
          -1501        def _check_unknown(s: str) -> undefined.UndefinedOr[str]:
          -1502            return s if not typedefs.is_unknown(s) else undefined.Undefined
          -1503
          -1504        return iterators.FlatIterator(
          -1505            [
          -1506                entity.SearchableEntity(
          -1507                    net=self._net,
          -1508                    hash=data["hash"],
          -1509                    entity_type=data["entityType"],
          -1510                    weight=data["weight"],
          -1511                    suggested_words=suggested_words,
          -1512                    name=data["displayProperties"]["name"],
          -1513                    has_icon=data["displayProperties"]["hasIcon"],
          -1514                    description=_check_unknown(
          -1515                        data["displayProperties"]["description"]
          -1516                    ),
          -1517                    icon=assets.Image(data["displayProperties"]["icon"]),
          -1518                )
          -1519                for data in payload["results"]["results"]
          -1520            ]
          -1521        )
          +            
          1490    def deserialize_inventory_results(
          +1491        self, payload: typedefs.JSONObject
          +1492    ) -> iterators.Iterator[entity.SearchableEntity]:
          +1493        suggested_words: list[str] = payload["suggestedWords"]
          +1494
          +1495        def _check_unknown(s: str) -> undefined.UndefinedOr[str]:
          +1496            return s if not typedefs.is_unknown(s) else undefined.Undefined
          +1497
          +1498        return iterators.Iterator(
          +1499            [
          +1500                entity.SearchableEntity(
          +1501                    net=self._net,
          +1502                    hash=data["hash"],
          +1503                    entity_type=data["entityType"],
          +1504                    weight=data["weight"],
          +1505                    suggested_words=suggested_words,
          +1506                    name=data["displayProperties"]["name"],
          +1507                    has_icon=data["displayProperties"]["hasIcon"],
          +1508                    description=_check_unknown(
          +1509                        data["displayProperties"]["description"]
          +1510                    ),
          +1511                    icon=assets.Image(data["displayProperties"]["icon"]),
          +1512                )
          +1513                for data in payload["results"]["results"]
          +1514            ]
          +1515        )
           
          @@ -7650,7 +7612,7 @@
          Parameters
          Returns
          @@ -7667,181 +7629,181 @@
          Returns
          -
          1550    def deserialize_inventory_entity(  # noqa: C901 Too complex.
          -1551        self, payload: typedefs.JSONObject, /
          -1552    ) -> entity.InventoryEntity:
          -1553
          -1554        props = self._set_entity_attrs(payload)
          -1555        objects = self._deserialize_inventory_item_objects(payload)
          -1556
          -1557        collectible_hash: typing.Optional[int] = None
          -1558        if raw_collectible_hash := payload.get("collectibleHash"):
          -1559            collectible_hash = int(raw_collectible_hash)
          -1560
          -1561        secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.Undefined
          -1562        if raw_second_icon := payload.get("secondaryIcon"):
          -1563            secondary_icon = assets.Image(raw_second_icon)
          -1564
          -1565        secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.Undefined
          -1566        if raw_second_overlay := payload.get("secondaryOverlay"):
          -1567            secondary_overlay = assets.Image(raw_second_overlay)
          -1568
          -1569        secondary_special: undefined.UndefinedOr[assets.Image] = undefined.Undefined
          -1570        if raw_second_special := payload.get("secondarySpecial"):
          -1571            secondary_special = assets.Image(raw_second_special)
          -1572
          -1573        screenshot: undefined.UndefinedOr[assets.Image] = undefined.Undefined
          -1574        if raw_screenshot := payload.get("screenshot"):
          -1575            screenshot = assets.Image(raw_screenshot)
          -1576
          -1577        watermark_icon: typing.Optional[assets.Image] = None
          -1578        if raw_watermark_icon := payload.get("iconWatermark"):
          -1579            watermark_icon = assets.Image(raw_watermark_icon)
          -1580
          -1581        watermark_shelved: typing.Optional[assets.Image] = None
          -1582        if raw_watermark_shelved := payload.get("iconWatermarkShelved"):
          -1583            watermark_shelved = assets.Image(raw_watermark_shelved)
          +            
          1544    def deserialize_inventory_entity(  # noqa: C901 Too complex.
          +1545        self, payload: typedefs.JSONObject, /
          +1546    ) -> entity.InventoryEntity:
          +1547
          +1548        props = self._set_entity_attrs(payload)
          +1549        objects = self._deserialize_inventory_item_objects(payload)
          +1550
          +1551        collectible_hash: typing.Optional[int] = None
          +1552        if raw_collectible_hash := payload.get("collectibleHash"):
          +1553            collectible_hash = int(raw_collectible_hash)
          +1554
          +1555        secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.Undefined
          +1556        if raw_second_icon := payload.get("secondaryIcon"):
          +1557            secondary_icon = assets.Image(raw_second_icon)
          +1558
          +1559        secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.Undefined
          +1560        if raw_second_overlay := payload.get("secondaryOverlay"):
          +1561            secondary_overlay = assets.Image(raw_second_overlay)
          +1562
          +1563        secondary_special: undefined.UndefinedOr[assets.Image] = undefined.Undefined
          +1564        if raw_second_special := payload.get("secondarySpecial"):
          +1565            secondary_special = assets.Image(raw_second_special)
          +1566
          +1567        screenshot: undefined.UndefinedOr[assets.Image] = undefined.Undefined
          +1568        if raw_screenshot := payload.get("screenshot"):
          +1569            screenshot = assets.Image(raw_screenshot)
          +1570
          +1571        watermark_icon: typing.Optional[assets.Image] = None
          +1572        if raw_watermark_icon := payload.get("iconWatermark"):
          +1573            watermark_icon = assets.Image(raw_watermark_icon)
          +1574
          +1575        watermark_shelved: typing.Optional[assets.Image] = None
          +1576        if raw_watermark_shelved := payload.get("iconWatermarkShelved"):
          +1577            watermark_shelved = assets.Image(raw_watermark_shelved)
          +1578
          +1579        about: undefined.UndefinedOr[str] = undefined.Undefined
          +1580        if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown(
          +1581            raw_about
          +1582        ):
          +1583            about = raw_about
           1584
          -1585        about: undefined.UndefinedOr[str] = undefined.Undefined
          -1586        if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown(
          -1587            raw_about
          -1588        ):
          -1589            about = raw_about
          +1585        ui_item_style: undefined.UndefinedOr[str] = undefined.Undefined
          +1586        if (
          +1587            raw_ui_style := payload.get("uiItemDisplayStyle")
          +1588        ) and not typedefs.is_unknown(raw_ui_style):
          +1589            ui_item_style = raw_ui_style
           1590
          -1591        ui_item_style: undefined.UndefinedOr[str] = undefined.Undefined
          +1591        tier_and_name: undefined.UndefinedOr[str] = undefined.Undefined
           1592        if (
          -1593            raw_ui_style := payload.get("uiItemDisplayStyle")
          -1594        ) and not typedefs.is_unknown(raw_ui_style):
          -1595            ui_item_style = raw_ui_style
          +1593            raw_tier_and_name := payload.get("itemTypeAndTierDisplayName")
          +1594        ) and not typedefs.is_unknown(raw_tier_and_name):
          +1595            tier_and_name = raw_tier_and_name
           1596
          -1597        tier_and_name: undefined.UndefinedOr[str] = undefined.Undefined
          +1597        type_name: undefined.UndefinedOr[str] = undefined.Undefined
           1598        if (
          -1599            raw_tier_and_name := payload.get("itemTypeAndTierDisplayName")
          -1600        ) and not typedefs.is_unknown(raw_tier_and_name):
          -1601            tier_and_name = raw_tier_and_name
          +1599            raw_type_name := payload.get("itemTypeDisplayName")
          +1600        ) and not typedefs.is_unknown(raw_type_name):
          +1601            type_name = raw_type_name
           1602
          -1603        type_name: undefined.UndefinedOr[str] = undefined.Undefined
          +1603        display_source: undefined.UndefinedOr[str] = undefined.Undefined
           1604        if (
          -1605            raw_type_name := payload.get("itemTypeDisplayName")
          -1606        ) and not typedefs.is_unknown(raw_type_name):
          -1607            type_name = raw_type_name
          +1605            raw_display_source := payload.get("displaySource")
          +1606        ) and not typedefs.is_unknown(raw_display_source):
          +1607            display_source = raw_display_source
           1608
          -1609        display_source: undefined.UndefinedOr[str] = undefined.Undefined
          -1610        if (
          -1611            raw_display_source := payload.get("displaySource")
          -1612        ) and not typedefs.is_unknown(raw_display_source):
          -1613            display_source = raw_display_source
          -1614
          -1615        lorehash: typing.Optional[int] = None
          -1616        if raw_lore_hash := payload.get("loreHash"):
          -1617            lorehash = int(raw_lore_hash)
          -1618
          -1619        summary_hash: typing.Optional[int] = None
          -1620        if raw_summary_hash := payload.get("summaryItemHash"):
          -1621            summary_hash = raw_summary_hash
          -1622
          -1623        breaker_type_hash: typing.Optional[int] = None
          -1624        if raw_breaker_type_hash := payload.get("breakerTypeHash"):
          -1625            breaker_type_hash = int(raw_breaker_type_hash)
          -1626
          -1627        damage_types: typing.Optional[collections.Sequence[int]] = None
          -1628        if raw_damage_types := payload.get("damageTypes"):
          -1629            damage_types = [int(type_) for type_ in raw_damage_types]
          -1630
          -1631        damagetype_hashes: typing.Optional[collections.Sequence[int]] = None
          -1632        if raw_damagetype_hashes := payload.get("damageTypeHashes"):
          -1633            damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes]
          -1634
          -1635        default_damagetype_hash: typing.Optional[int] = None
          -1636        if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"):
          -1637            default_damagetype_hash = int(raw_defaultdmg_hash)
          -1638
          -1639        emblem_objective_hash: typing.Optional[int] = None
          -1640        if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"):
          -1641            emblem_objective_hash = int(raw_emblem_obj_hash)
          -1642
          -1643        tier_type: typing.Optional[enums.TierType] = None
          -1644        tier: typing.Optional[enums.ItemTier] = None
          -1645        bucket_hash: typing.Optional[int] = None
          -1646        recovery_hash: typing.Optional[int] = None
          -1647        tier_name: undefined.UndefinedOr[str] = undefined.Undefined
          -1648        isinstance_item: bool = False
          -1649        expire_tool_tip: undefined.UndefinedOr[str] = undefined.Undefined
          -1650        expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.Undefined
          -1651        suppress_expiration: bool = False
          -1652        max_stack_size: typing.Optional[int] = None
          -1653        stack_label: undefined.UndefinedOr[str] = undefined.Undefined
          -1654
          -1655        if inventory := payload.get("inventory"):
          -1656            tier_type = enums.TierType(int(inventory["tierType"]))
          -1657            tier = enums.ItemTier(int(inventory["tierTypeHash"]))
          -1658            bucket_hash = int(inventory["bucketTypeHash"])
          -1659            recovery_hash = int(inventory["recoveryBucketTypeHash"])
          -1660            tier_name = inventory["tierTypeName"]
          -1661            isinstance_item = inventory["isInstanceItem"]
          -1662            suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"]
          -1663            max_stack_size = int(inventory["maxStackSize"])
          -1664
          -1665            try:
          -1666                stack_label = inventory["stackUniqueLabel"]
          -1667            except KeyError:
          -1668                pass
          -1669
          -1670        return entity.InventoryEntity(
          -1671            net=self._net,
          -1672            collectible_hash=collectible_hash,
          -1673            name=props.name,
          -1674            about=about,
          -1675            emblem_objective_hash=emblem_objective_hash,
          -1676            suppress_expiration=suppress_expiration,
          -1677            max_stack_size=max_stack_size,
          -1678            stack_label=stack_label,
          -1679            tier=tier,
          -1680            tier_type=tier_type,
          -1681            tier_name=tier_name,
          -1682            bucket_hash=bucket_hash,
          -1683            recovery_bucket_hash=recovery_hash,
          -1684            isinstance_item=isinstance_item,
          -1685            expire_in_orbit_message=expire_in_orbit_message,
          -1686            expiration_tooltip=expire_tool_tip,
          -1687            lore_hash=lorehash,
          -1688            type_and_tier_name=tier_and_name,
          -1689            summary_hash=summary_hash,
          -1690            ui_display_style=ui_item_style,
          -1691            type_name=type_name,
          -1692            breaker_type_hash=breaker_type_hash,
          -1693            description=props.description,
          -1694            display_source=display_source,
          -1695            hash=props.hash,
          -1696            damage_types=damage_types,
          -1697            index=props.index,
          -1698            icon=props.icon,
          -1699            has_icon=props.has_icon,
          -1700            screenshot=screenshot,
          -1701            watermark_icon=watermark_icon,
          -1702            watermark_shelved=watermark_shelved,
          -1703            secondary_icon=secondary_icon,
          -1704            secondary_overlay=secondary_overlay,
          -1705            secondary_special=secondary_special,
          -1706            type=enums.ItemType(int(payload["itemType"])),
          -1707            trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])],
          -1708            trait_ids=[trait for trait in payload.get("traitIds", [])],
          -1709            category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]],
          -1710            item_class=enums.Class(int(payload["classType"])),
          -1711            sub_type=enums.ItemSubType(int(payload["itemSubType"])),
          -1712            breaker_type=int(payload["breakerType"]),
          -1713            default_damagetype=int(payload["defaultDamageType"]),
          -1714            default_damagetype_hash=default_damagetype_hash,
          -1715            damagetype_hashes=damagetype_hashes,
          -1716            tooltip_notifications=payload["tooltipNotifications"],
          -1717            not_transferable=payload["nonTransferrable"],
          -1718            allow_actions=payload["allowActions"],
          -1719            is_equippable=payload["equippable"],
          -1720            objects=objects,
          -1721            background_colors=payload.get("backgroundColor", {}),
          -1722            season_hash=payload.get("seasonHash"),
          -1723            has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"],
          -1724        )
          +1609        lorehash: typing.Optional[int] = None
          +1610        if raw_lore_hash := payload.get("loreHash"):
          +1611            lorehash = int(raw_lore_hash)
          +1612
          +1613        summary_hash: typing.Optional[int] = None
          +1614        if raw_summary_hash := payload.get("summaryItemHash"):
          +1615            summary_hash = raw_summary_hash
          +1616
          +1617        breaker_type_hash: typing.Optional[int] = None
          +1618        if raw_breaker_type_hash := payload.get("breakerTypeHash"):
          +1619            breaker_type_hash = int(raw_breaker_type_hash)
          +1620
          +1621        damage_types: typing.Optional[collections.Sequence[int]] = None
          +1622        if raw_damage_types := payload.get("damageTypes"):
          +1623            damage_types = [int(type_) for type_ in raw_damage_types]
          +1624
          +1625        damagetype_hashes: typing.Optional[collections.Sequence[int]] = None
          +1626        if raw_damagetype_hashes := payload.get("damageTypeHashes"):
          +1627            damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes]
          +1628
          +1629        default_damagetype_hash: typing.Optional[int] = None
          +1630        if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"):
          +1631            default_damagetype_hash = int(raw_defaultdmg_hash)
          +1632
          +1633        emblem_objective_hash: typing.Optional[int] = None
          +1634        if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"):
          +1635            emblem_objective_hash = int(raw_emblem_obj_hash)
          +1636
          +1637        tier_type: typing.Optional[enums.TierType] = None
          +1638        tier: typing.Optional[enums.ItemTier] = None
          +1639        bucket_hash: typing.Optional[int] = None
          +1640        recovery_hash: typing.Optional[int] = None
          +1641        tier_name: undefined.UndefinedOr[str] = undefined.Undefined
          +1642        isinstance_item: bool = False
          +1643        expire_tool_tip: undefined.UndefinedOr[str] = undefined.Undefined
          +1644        expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.Undefined
          +1645        suppress_expiration: bool = False
          +1646        max_stack_size: typing.Optional[int] = None
          +1647        stack_label: undefined.UndefinedOr[str] = undefined.Undefined
          +1648
          +1649        if inventory := payload.get("inventory"):
          +1650            tier_type = enums.TierType(int(inventory["tierType"]))
          +1651            tier = enums.ItemTier(int(inventory["tierTypeHash"]))
          +1652            bucket_hash = int(inventory["bucketTypeHash"])
          +1653            recovery_hash = int(inventory["recoveryBucketTypeHash"])
          +1654            tier_name = inventory["tierTypeName"]
          +1655            isinstance_item = inventory["isInstanceItem"]
          +1656            suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"]
          +1657            max_stack_size = int(inventory["maxStackSize"])
          +1658
          +1659            try:
          +1660                stack_label = inventory["stackUniqueLabel"]
          +1661            except KeyError:
          +1662                pass
          +1663
          +1664        return entity.InventoryEntity(
          +1665            net=self._net,
          +1666            collectible_hash=collectible_hash,
          +1667            name=props.name,
          +1668            about=about,
          +1669            emblem_objective_hash=emblem_objective_hash,
          +1670            suppress_expiration=suppress_expiration,
          +1671            max_stack_size=max_stack_size,
          +1672            stack_label=stack_label,
          +1673            tier=tier,
          +1674            tier_type=tier_type,
          +1675            tier_name=tier_name,
          +1676            bucket_hash=bucket_hash,
          +1677            recovery_bucket_hash=recovery_hash,
          +1678            isinstance_item=isinstance_item,
          +1679            expire_in_orbit_message=expire_in_orbit_message,
          +1680            expiration_tooltip=expire_tool_tip,
          +1681            lore_hash=lorehash,
          +1682            type_and_tier_name=tier_and_name,
          +1683            summary_hash=summary_hash,
          +1684            ui_display_style=ui_item_style,
          +1685            type_name=type_name,
          +1686            breaker_type_hash=breaker_type_hash,
          +1687            description=props.description,
          +1688            display_source=display_source,
          +1689            hash=props.hash,
          +1690            damage_types=damage_types,
          +1691            index=props.index,
          +1692            icon=props.icon,
          +1693            has_icon=props.has_icon,
          +1694            screenshot=screenshot,
          +1695            watermark_icon=watermark_icon,
          +1696            watermark_shelved=watermark_shelved,
          +1697            secondary_icon=secondary_icon,
          +1698            secondary_overlay=secondary_overlay,
          +1699            secondary_special=secondary_special,
          +1700            type=enums.ItemType(int(payload["itemType"])),
          +1701            trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])],
          +1702            trait_ids=[trait for trait in payload.get("traitIds", [])],
          +1703            category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]],
          +1704            item_class=enums.Class(int(payload["classType"])),
          +1705            sub_type=enums.ItemSubType(int(payload["itemSubType"])),
          +1706            breaker_type=int(payload["breakerType"]),
          +1707            default_damagetype=int(payload["defaultDamageType"]),
          +1708            default_damagetype_hash=default_damagetype_hash,
          +1709            damagetype_hashes=damagetype_hashes,
          +1710            tooltip_notifications=payload["tooltipNotifications"],
          +1711            not_transferable=payload["nonTransferrable"],
          +1712            allow_actions=payload["allowActions"],
          +1713            is_equippable=payload["equippable"],
          +1714            objects=objects,
          +1715            background_colors=payload.get("backgroundColor", {}),
          +1716            season_hash=payload.get("seasonHash"),
          +1717            has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"],
          +1718        )
           
          @@ -7876,42 +7838,42 @@
          Returns
          -
          1726    def deserialize_objective_entity(
          -1727        self, payload: typedefs.JSONObject, /
          -1728    ) -> entity.ObjectiveEntity:
          -1729        props = self._set_entity_attrs(payload)
          -1730        return entity.ObjectiveEntity(
          -1731            net=self._net,
          -1732            hash=props.hash,
          -1733            index=props.index,
          -1734            description=props.description,
          -1735            name=props.name,
          -1736            has_icon=props.has_icon,
          -1737            icon=props.icon,
          -1738            unlock_value_hash=payload["unlockValueHash"],
          -1739            completion_value=payload["completionValue"],
          -1740            scope=entity.GatingScope(int(payload["scope"])),
          -1741            location_hash=payload["locationHash"],
          -1742            allowed_negative_value=payload["allowNegativeValue"],
          -1743            allowed_value_change=payload["allowValueChangeWhenCompleted"],
          -1744            counting_downward=payload["isCountingDownward"],
          -1745            value_style=entity.ValueUIStyle(int(payload["valueStyle"])),
          -1746            progress_description=payload["progressDescription"],
          -1747            perks=payload["perks"],
          -1748            stats=payload["stats"],
          -1749            minimum_visibility=payload["minimumVisibilityThreshold"],
          -1750            allow_over_completion=payload["allowOvercompletion"],
          -1751            show_value_style=payload["showValueOnComplete"],
          -1752            display_only_objective=payload["isDisplayOnlyObjective"],
          -1753            complete_value_style=entity.ValueUIStyle(
          -1754                int(payload["completedValueStyle"])
          -1755            ),
          -1756            progress_value_style=entity.ValueUIStyle(
          -1757                int(payload["inProgressValueStyle"])
          -1758            ),
          -1759            ui_label=payload["uiLabel"],
          -1760            ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])),
          -1761        )
          +            
          1720    def deserialize_objective_entity(
          +1721        self, payload: typedefs.JSONObject, /
          +1722    ) -> entity.ObjectiveEntity:
          +1723        props = self._set_entity_attrs(payload)
          +1724        return entity.ObjectiveEntity(
          +1725            net=self._net,
          +1726            hash=props.hash,
          +1727            index=props.index,
          +1728            description=props.description,
          +1729            name=props.name,
          +1730            has_icon=props.has_icon,
          +1731            icon=props.icon,
          +1732            unlock_value_hash=payload["unlockValueHash"],
          +1733            completion_value=payload["completionValue"],
          +1734            scope=entity.GatingScope(int(payload["scope"])),
          +1735            location_hash=payload["locationHash"],
          +1736            allowed_negative_value=payload["allowNegativeValue"],
          +1737            allowed_value_change=payload["allowValueChangeWhenCompleted"],
          +1738            counting_downward=payload["isCountingDownward"],
          +1739            value_style=entity.ValueUIStyle(int(payload["valueStyle"])),
          +1740            progress_description=payload["progressDescription"],
          +1741            perks=payload["perks"],
          +1742            stats=payload["stats"],
          +1743            minimum_visibility=payload["minimumVisibilityThreshold"],
          +1744            allow_over_completion=payload["allowOvercompletion"],
          +1745            show_value_style=payload["showValueOnComplete"],
          +1746            display_only_objective=payload["isDisplayOnlyObjective"],
          +1747            complete_value_style=entity.ValueUIStyle(
          +1748                int(payload["completedValueStyle"])
          +1749            ),
          +1750            progress_value_style=entity.ValueUIStyle(
          +1751                int(payload["inProgressValueStyle"])
          +1752            ),
          +1753            ui_label=payload["uiLabel"],
          +1754            ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])),
          +1755        )
           
          @@ -7944,35 +7906,35 @@
          Returns
          -
          1789    def deserialize_activity(
          -1790        self,
          -1791        payload: typedefs.JSONObject,
          -1792        /,
          -1793    ) -> activity.Activity:
          -1794        period = time.clean_date(payload["period"])
          -1795        details = payload["activityDetails"]
          -1796        ref_id = int(details["referenceId"])
          -1797        instance_id = int(details["instanceId"])
          -1798        mode = enums.GameMode(details["mode"])
          -1799        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
          -1800        is_private = details["isPrivate"]
          -1801        membership_type = enums.MembershipType(int(details["membershipType"]))
          -1802
          -1803        # Since we're using the same fields for post activity method
          -1804        # this check is required since post activity doesn't values values
          -1805        values = self._deserialize_activity_values(payload["values"])
          -1806
          -1807        return activity.Activity(
          -1808            net=self._net,
          -1809            hash=ref_id,
          -1810            instance_id=instance_id,
          -1811            mode=mode,
          -1812            modes=modes,
          -1813            is_private=is_private,
          -1814            membership_type=membership_type,
          -1815            occurred_at=period,
          -1816            values=values,
          -1817        )
          +            
          1783    def deserialize_activity(
          +1784        self,
          +1785        payload: typedefs.JSONObject,
          +1786        /,
          +1787    ) -> activity.Activity:
          +1788        period = time.clean_date(payload["period"])
          +1789        details = payload["activityDetails"]
          +1790        ref_id = int(details["referenceId"])
          +1791        instance_id = int(details["instanceId"])
          +1792        mode = enums.GameMode(details["mode"])
          +1793        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
          +1794        is_private = details["isPrivate"]
          +1795        membership_type = enums.MembershipType(int(details["membershipType"]))
          +1796
          +1797        # Since we're using the same fields for post activity method
          +1798        # this check is required since post activity doesn't values values
          +1799        values = self._deserialize_activity_values(payload["values"])
          +1800
          +1801        return activity.Activity(
          +1802            net=self._net,
          +1803            hash=ref_id,
          +1804            instance_id=instance_id,
          +1805            mode=mode,
          +1806            modes=modes,
          +1807            is_private=is_private,
          +1808            membership_type=membership_type,
          +1809            occurred_at=period,
          +1810            values=values,
          +1811        )
           
          @@ -7999,21 +7961,21 @@
          Returns
          def - deserialize_activities( self, payload: dict[str, typing.Any]) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.activity.Activity]: + deserialize_activities( self, payload: dict[str, typing.Any]) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.activity.Activity]:
          -
          1819    def deserialize_activities(
          -1820        self, payload: typedefs.JSONObject
          -1821    ) -> iterators.FlatIterator[activity.Activity]:
          -1822        return iterators.FlatIterator(
          -1823            [
          -1824                self.deserialize_activity(activity_)
          -1825                for activity_ in payload["activities"]
          -1826            ]
          -1827        )
          +            
          1813    def deserialize_activities(
          +1814        self, payload: typedefs.JSONObject
          +1815    ) -> iterators.Iterator[activity.Activity]:
          +1816        return iterators.Iterator(
          +1817            [
          +1818                self.deserialize_activity(activity_)
          +1819                for activity_ in payload["activities"]
          +1820            ]
          +1821        )
           
          @@ -8029,7 +7991,7 @@
          Parameters
          Returns
          @@ -8046,33 +8008,33 @@
          Returns
          -
          1829    def deserialize_extended_weapon_values(
          -1830        self, payload: typedefs.JSONObject
          -1831    ) -> activity.ExtendedWeaponValues:
          -1832
          -1833        assists: typing.Optional[int] = None
          -1834        if raw_assists := payload["values"].get("uniqueWeaponAssists"):
          -1835            assists = raw_assists["basic"]["value"]
          -1836        assists_damage: typing.Optional[int] = None
          -1837
          -1838        if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"):
          -1839            assists_damage = raw_assists_damage["basic"]["value"]
          -1840
          -1841        return activity.ExtendedWeaponValues(
          -1842            reference_id=int(payload["referenceId"]),
          -1843            kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"],
          -1844            precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][
          -1845                "value"
          -1846            ],
          -1847            assists=assists,
          -1848            assists_damage=assists_damage,
          -1849            precision_kills_percentage=(
          -1850                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"],
          -1851                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][
          -1852                    "displayValue"
          -1853                ],
          -1854            ),
          -1855        )
          +            
          1823    def deserialize_extended_weapon_values(
          +1824        self, payload: typedefs.JSONObject
          +1825    ) -> activity.ExtendedWeaponValues:
          +1826
          +1827        assists: typing.Optional[int] = None
          +1828        if raw_assists := payload["values"].get("uniqueWeaponAssists"):
          +1829            assists = raw_assists["basic"]["value"]
          +1830        assists_damage: typing.Optional[int] = None
          +1831
          +1832        if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"):
          +1833            assists_damage = raw_assists_damage["basic"]["value"]
          +1834
          +1835        return activity.ExtendedWeaponValues(
          +1836            reference_id=int(payload["referenceId"]),
          +1837            kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"],
          +1838            precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][
          +1839                "value"
          +1840            ],
          +1841            assists=assists,
          +1842            assists_damage=assists_damage,
          +1843            precision_kills_percentage=(
          +1844                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"],
          +1845                payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][
          +1846                    "displayValue"
          +1847                ],
          +1848            ),
          +1849        )
           
          @@ -8105,48 +8067,48 @@
          Returns
          -
          1878    def deserialize_post_activity_player(
          -1879        self, payload: typedefs.JSONObject, /
          -1880    ) -> activity.PostActivityPlayer:
          -1881        player = payload["player"]
          -1882
          -1883        class_hash: typedefs.NoneOr[int] = None
          -1884        if (class_hash := player.get("classHash")) is not None:
          -1885            class_hash = class_hash
          -1886
          -1887        race_hash: typedefs.NoneOr[int] = None
          -1888        if (race_hash := player.get("raceHash")) is not None:
          -1889            race_hash = race_hash
          -1890
          -1891        gender_hash: typedefs.NoneOr[int] = None
          -1892        if (gender_hash := player.get("genderHash")) is not None:
          -1893            gender_hash = gender_hash
          +            
          1872    def deserialize_post_activity_player(
          +1873        self, payload: typedefs.JSONObject, /
          +1874    ) -> activity.PostActivityPlayer:
          +1875        player = payload["player"]
          +1876
          +1877        class_hash: typedefs.NoneOr[int] = None
          +1878        if (class_hash := player.get("classHash")) is not None:
          +1879            class_hash = class_hash
          +1880
          +1881        race_hash: typedefs.NoneOr[int] = None
          +1882        if (race_hash := player.get("raceHash")) is not None:
          +1883            race_hash = race_hash
          +1884
          +1885        gender_hash: typedefs.NoneOr[int] = None
          +1886        if (gender_hash := player.get("genderHash")) is not None:
          +1887            gender_hash = gender_hash
          +1888
          +1889        character_class: undefined.UndefinedOr[str] = undefined.Undefined
          +1890        if (
          +1891            character_class := player.get("characterClass")
          +1892        ) and not typedefs.is_unknown(character_class):
          +1893            character_class = character_class
           1894
          -1895        character_class: undefined.UndefinedOr[str] = undefined.Undefined
          -1896        if (
          -1897            character_class := player.get("characterClass")
          -1898        ) and not typedefs.is_unknown(character_class):
          -1899            character_class = character_class
          -1900
          -1901        character_level: typedefs.NoneOr[int] = None
          -1902        if (character_level := player.get("characterLevel")) is not None:
          -1903            character_level = character_level
          -1904
          -1905        return activity.PostActivityPlayer(
          -1906            standing=int(payload["standing"]),
          -1907            score=int(payload["score"]["basic"]["value"]),
          -1908            character_id=payload["characterId"],
          -1909            destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]),
          -1910            character_class=character_class,
          -1911            character_level=character_level,
          -1912            race_hash=race_hash,
          -1913            gender_hash=gender_hash,
          -1914            class_hash=class_hash,
          -1915            light_level=int(player["lightLevel"]),
          -1916            emblem_hash=int(player["emblemHash"]),
          -1917            values=self._deserialize_activity_values(payload["values"]),
          -1918            extended_values=self._deserialize_extended_values(payload["extended"]),
          -1919        )
          +1895        character_level: typedefs.NoneOr[int] = None
          +1896        if (character_level := player.get("characterLevel")) is not None:
          +1897            character_level = character_level
          +1898
          +1899        return activity.PostActivityPlayer(
          +1900            standing=int(payload["standing"]),
          +1901            score=int(payload["score"]["basic"]["value"]),
          +1902            character_id=payload["characterId"],
          +1903            destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]),
          +1904            character_class=character_class,
          +1905            character_level=character_level,
          +1906            race_hash=race_hash,
          +1907            gender_hash=gender_hash,
          +1908            class_hash=class_hash,
          +1909            light_level=int(player["lightLevel"]),
          +1910            emblem_hash=int(player["emblemHash"]),
          +1911            values=self._deserialize_activity_values(payload["values"]),
          +1912            extended_values=self._deserialize_extended_values(payload["extended"]),
          +1913        )
           
          @@ -8179,35 +8141,35 @@
          Returns
          -
          1931    def deserialize_post_activity(
          -1932        self, payload: typedefs.JSONObject
          -1933    ) -> activity.PostActivity:
          -1934        period = time.clean_date(payload["period"])
          -1935        details = payload["activityDetails"]
          -1936        ref_id = int(details["referenceId"])
          -1937        instance_id = int(details["instanceId"])
          -1938        mode = enums.GameMode(details["mode"])
          -1939        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
          -1940        is_private = details["isPrivate"]
          -1941        membership_type = enums.MembershipType(int(details["membershipType"]))
          -1942        return activity.PostActivity(
          -1943            net=self._net,
          -1944            hash=ref_id,
          -1945            membership_type=membership_type,
          -1946            instance_id=instance_id,
          -1947            mode=mode,
          -1948            modes=modes,
          -1949            is_private=is_private,
          -1950            occurred_at=period,
          -1951            starting_phase=int(payload["startingPhaseIndex"]),
          -1952            players=[
          -1953                self.deserialize_post_activity_player(player)
          -1954                for player in payload["entries"]
          -1955            ],
          -1956            teams=[
          -1957                self._deserialize_post_activity_team(team) for team in payload["teams"]
          -1958            ],
          -1959        )
          +            
          1925    def deserialize_post_activity(
          +1926        self, payload: typedefs.JSONObject
          +1927    ) -> activity.PostActivity:
          +1928        period = time.clean_date(payload["period"])
          +1929        details = payload["activityDetails"]
          +1930        ref_id = int(details["referenceId"])
          +1931        instance_id = int(details["instanceId"])
          +1932        mode = enums.GameMode(details["mode"])
          +1933        modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]]
          +1934        is_private = details["isPrivate"]
          +1935        membership_type = enums.MembershipType(int(details["membershipType"]))
          +1936        return activity.PostActivity(
          +1937            net=self._net,
          +1938            hash=ref_id,
          +1939            membership_type=membership_type,
          +1940            instance_id=instance_id,
          +1941            mode=mode,
          +1942            modes=modes,
          +1943            is_private=is_private,
          +1944            occurred_at=period,
          +1945            starting_phase=int(payload["startingPhaseIndex"]),
          +1946            players=[
          +1947                self.deserialize_post_activity_player(player)
          +1948                for player in payload["entries"]
          +1949            ],
          +1950            teams=[
          +1951                self._deserialize_post_activity_team(team) for team in payload["teams"]
          +1952            ],
          +1953        )
           
          @@ -8240,13 +8202,13 @@
          Returns
          -
          1997    def deserialize_aggregated_activity(
          -1998        self, payload: typedefs.JSONObject
          -1999    ) -> activity.AggregatedActivity:
          -2000        return activity.AggregatedActivity(
          -2001            hash=int(payload["activityHash"]),
          -2002            values=self._deserialize_aggregated_activity_values(payload["values"]),
          -2003        )
          +            
          1991    def deserialize_aggregated_activity(
          +1992        self, payload: typedefs.JSONObject
          +1993    ) -> activity.AggregatedActivity:
          +1994        return activity.AggregatedActivity(
          +1995            hash=int(payload["activityHash"]),
          +1996            values=self._deserialize_aggregated_activity_values(payload["values"]),
          +1997        )
           
          @@ -8273,21 +8235,21 @@
          Returns
          def - deserialize_aggregated_activities( self, payload: dict[str, typing.Any]) -> aiobungie.internal.iterators.FlatIterator[aiobungie.crates.activity.AggregatedActivity]: + deserialize_aggregated_activities( self, payload: dict[str, typing.Any]) -> aiobungie.internal.iterators.Iterator[aiobungie.crates.activity.AggregatedActivity]:
          -
          2005    def deserialize_aggregated_activities(
          -2006        self, payload: typedefs.JSONObject
          -2007    ) -> iterators.FlatIterator[activity.AggregatedActivity]:
          -2008        return iterators.FlatIterator(
          -2009            [
          -2010                self.deserialize_aggregated_activity(activity)
          -2011                for activity in payload["activities"]
          -2012            ]
          -2013        )
          +            
          1999    def deserialize_aggregated_activities(
          +2000        self, payload: typedefs.JSONObject
          +2001    ) -> iterators.Iterator[activity.AggregatedActivity]:
          +2002        return iterators.Iterator(
          +2003            [
          +2004                self.deserialize_aggregated_activity(activity)
          +2005                for activity in payload["activities"]
          +2006            ]
          +2007        )
           
          @@ -8303,7 +8265,7 @@
          Parameters
          Returns
          @@ -8320,30 +8282,30 @@
          Returns
          -
          2015    def deserialize_linked_profiles(
          -2016        self, payload: typedefs.JSONObject
          -2017    ) -> profile.LinkedProfile:
          -2018        bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"])
          -2019        error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
          -2020        profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
          -2021
          -2022        if raw_profile := payload.get("profiles"):
          -2023            for pfile in raw_profile:
          -2024                profiles_vec.append(self.deserialize_destiny_membership(pfile))
          -2025
          -2026        if raw_profiles_with_errors := payload.get("profilesWithErrors"):
          -2027            for raw_error_pfile in raw_profiles_with_errors:
          -2028                if error_pfile := raw_error_pfile.get("infoCard"):
          -2029                    error_profiles_vec.append(
          -2030                        self.deserialize_destiny_membership(error_pfile)
          -2031                    )
          -2032
          -2033        return profile.LinkedProfile(
          -2034            net=self._net,
          -2035            bungie=bungie_user,
          -2036            profiles=profiles_vec,
          -2037            profiles_with_errors=error_profiles_vec,
          -2038        )
          +            
          2009    def deserialize_linked_profiles(
          +2010        self, payload: typedefs.JSONObject
          +2011    ) -> profile.LinkedProfile:
          +2012        bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"])
          +2013        error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
          +2014        profiles_vec: typing.MutableSequence[user.DestinyMembership] = []
          +2015
          +2016        if raw_profile := payload.get("profiles"):
          +2017            for pfile in raw_profile:
          +2018                profiles_vec.append(self.deserialize_destiny_membership(pfile))
          +2019
          +2020        if raw_profiles_with_errors := payload.get("profilesWithErrors"):
          +2021            for raw_error_pfile in raw_profiles_with_errors:
          +2022                if error_pfile := raw_error_pfile.get("infoCard"):
          +2023                    error_profiles_vec.append(
          +2024                        self.deserialize_destiny_membership(error_pfile)
          +2025                    )
          +2026
          +2027        return profile.LinkedProfile(
          +2028            net=self._net,
          +2029            bungie=bungie_user,
          +2030            profiles=profiles_vec,
          +2031            profiles_with_errors=error_profiles_vec,
          +2032        )
           
          @@ -8376,19 +8338,19 @@
          Returns
          -
          2040    def deserialize_clan_banners(
          -2041        self, payload: typedefs.JSONObject
          -2042    ) -> collections.Sequence[clans.ClanBanner]:
          -2043        banners_seq: typing.MutableSequence[clans.ClanBanner] = []
          -2044        if banners := payload.get("clanBannerDecals"):
          -2045            for k, v in banners.items():
          -2046                banner_obj = clans.ClanBanner(
          -2047                    id=int(k),
          -2048                    foreground=assets.Image(v["foregroundPath"]),
          -2049                    background=assets.Image(v["backgroundPath"]),
          -2050                )
          -2051                banners_seq.append(banner_obj)
          -2052        return banners_seq
          +            
          2034    def deserialize_clan_banners(
          +2035        self, payload: typedefs.JSONObject
          +2036    ) -> collections.Sequence[clans.ClanBanner]:
          +2037        banners_seq: typing.MutableSequence[clans.ClanBanner] = []
          +2038        if banners := payload.get("clanBannerDecals"):
          +2039            for k, v in banners.items():
          +2040                banner_obj = clans.ClanBanner(
          +2041                    id=int(k),
          +2042                    foreground=assets.Image(v["foregroundPath"]),
          +2043                    background=assets.Image(v["backgroundPath"]),
          +2044                )
          +2045                banners_seq.append(banner_obj)
          +2046        return banners_seq
           
          @@ -8421,39 +8383,39 @@
          Returns
          -
          2054    def deserialize_public_milestone_content(
          -2055        self, payload: typedefs.JSONObject
          -2056    ) -> milestones.MilestoneContent:
          -2057        items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None
          -2058        if raw_categories := payload.get("itemCategories"):
          -2059            for item in raw_categories:
          -2060                title = undefined.Undefined
          -2061                if raw_title := item.get("title"):
          -2062                    if raw_title != typedefs.Unknown:
          -2063                        title = raw_title
          -2064                if raw_hashes := item.get("itemHashes"):
          -2065                    hashes: collections.Sequence[int] = raw_hashes
          +            
          2048    def deserialize_public_milestone_content(
          +2049        self, payload: typedefs.JSONObject
          +2050    ) -> milestones.MilestoneContent:
          +2051        items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None
          +2052        if raw_categories := payload.get("itemCategories"):
          +2053            for item in raw_categories:
          +2054                title = undefined.Undefined
          +2055                if raw_title := item.get("title"):
          +2056                    if raw_title != typedefs.Unknown:
          +2057                        title = raw_title
          +2058                if raw_hashes := item.get("itemHashes"):
          +2059                    hashes: collections.Sequence[int] = raw_hashes
          +2060
          +2061                items_categoris = milestones.MilestoneItems(title=title, hashes=hashes)
          +2062
          +2063        about = undefined.Undefined
          +2064        if (raw_about := payload["about"]) != typedefs.Unknown:
          +2065            about = raw_about
           2066
          -2067                items_categoris = milestones.MilestoneItems(title=title, hashes=hashes)
          -2068
          -2069        about = undefined.Undefined
          -2070        if (raw_about := payload["about"]) != typedefs.Unknown:
          -2071            about = raw_about
          -2072
          -2073        status = undefined.Undefined
          -2074        if (raw_status := payload["status"]) != typedefs.Unknown:
          -2075            status = raw_status
          -2076
          -2077        tips: typing.MutableSequence[undefined.UndefinedOr[str]] = []
          -2078        if raw_tips := payload.get("tips"):
          -2079            for raw_tip in raw_tips:
          -2080                if raw_tip == typedefs.Unknown:
          -2081                    raw_tip = undefined.Undefined
          -2082                tips.append(raw_tip)
          -2083
          -2084        return milestones.MilestoneContent(
          -2085            about=about, status=status, tips=tips, items=items_categoris
          -2086        )
          +2067        status = undefined.Undefined
          +2068        if (raw_status := payload["status"]) != typedefs.Unknown:
          +2069            status = raw_status
          +2070
          +2071        tips: typing.MutableSequence[undefined.UndefinedOr[str]] = []
          +2072        if raw_tips := payload.get("tips"):
          +2073            for raw_tip in raw_tips:
          +2074                if raw_tip == typedefs.Unknown:
          +2075                    raw_tip = undefined.Undefined
          +2076                tips.append(raw_tip)
          +2077
          +2078        return milestones.MilestoneContent(
          +2079            about=about, status=status, tips=tips, items=items_categoris
          +2080        )
           
          @@ -8486,27 +8448,27 @@
          Returns
          -
          2088    def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend:
          -2089        name = undefined.Undefined
          -2090        if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown:
          -2091            name = raw_name
          -2092
          -2093        bungie_user: typedefs.NoneOr[user.BungieUser] = None
          -2094
          -2095        if raw_bungie_user := payload.get("bungieNetUser"):
          -2096            bungie_user = self.deserialize_bungie_user(raw_bungie_user)
          -2097
          -2098        return friends.Friend(
          -2099            net=self._net,
          -2100            id=int(payload["lastSeenAsMembershipId"]),
          -2101            name=name,
          -2102            code=payload.get("bungieGlobalDisplayNameCode"),
          -2103            relationship=enums.Relationship(payload["relationship"]),
          -2104            user=bungie_user,
          -2105            online_status=enums.Presence(payload["onlineStatus"]),
          -2106            online_title=payload["onlineTitle"],
          -2107            type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]),
          -2108        )
          +            
          2082    def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend:
          +2083        name = undefined.Undefined
          +2084        if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown:
          +2085            name = raw_name
          +2086
          +2087        bungie_user: typedefs.NoneOr[user.BungieUser] = None
          +2088
          +2089        if raw_bungie_user := payload.get("bungieNetUser"):
          +2090            bungie_user = self.deserialize_bungie_user(raw_bungie_user)
          +2091
          +2092        return friends.Friend(
          +2093            net=self._net,
          +2094            id=int(payload["lastSeenAsMembershipId"]),
          +2095            name=name,
          +2096            code=payload.get("bungieGlobalDisplayNameCode"),
          +2097            relationship=enums.Relationship(payload["relationship"]),
          +2098            user=bungie_user,
          +2099            online_status=enums.Presence(payload["onlineStatus"]),
          +2100            online_title=payload["onlineTitle"],
          +2101            type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]),
          +2102        )
           
          @@ -8539,14 +8501,14 @@
          Returns
          -
          2110    def deserialize_friends(
          -2111        self, payload: typedefs.JSONObject
          -2112    ) -> collections.Sequence[friends.Friend]:
          -2113        mut_seq: typing.MutableSequence[friends.Friend] = []
          -2114        if raw_friends := payload.get("friends"):
          -2115            for friend in raw_friends:
          -2116                mut_seq.append(self.deserialize_friend(friend))
          -2117        return mut_seq
          +            
          2104    def deserialize_friends(
          +2105        self, payload: typedefs.JSONObject
          +2106    ) -> collections.Sequence[friends.Friend]:
          +2107        mut_seq: typing.MutableSequence[friends.Friend] = []
          +2108        if raw_friends := payload.get("friends"):
          +2109            for friend in raw_friends:
          +2110                mut_seq.append(self.deserialize_friend(friend))
          +2111        return mut_seq
           
          @@ -8581,21 +8543,21 @@
          Returns
          -
          2119    def deserialize_friend_requests(
          -2120        self, payload: typedefs.JSONObject
          -2121    ) -> friends.FriendRequestView:
          -2122        incoming: typing.MutableSequence[friends.Friend] = []
          -2123        outgoing: typing.MutableSequence[friends.Friend] = []
          -2124
          -2125        if raw_incoming_requests := payload.get("incomingRequests"):
          -2126            for incoming_request in raw_incoming_requests:
          -2127                incoming.append(self.deserialize_friend(incoming_request))
          -2128
          -2129        if raw_outgoing_requests := payload.get("outgoingRequests"):
          -2130            for outgoing_request in raw_outgoing_requests:
          -2131                outgoing.append(self.deserialize_friend(outgoing_request))
          -2132
          -2133        return friends.FriendRequestView(incoming=incoming, outgoing=outgoing)
          +            
          2113    def deserialize_friend_requests(
          +2114        self, payload: typedefs.JSONObject
          +2115    ) -> friends.FriendRequestView:
          +2116        incoming: typing.MutableSequence[friends.Friend] = []
          +2117        outgoing: typing.MutableSequence[friends.Friend] = []
          +2118
          +2119        if raw_incoming_requests := payload.get("incomingRequests"):
          +2120            for incoming_request in raw_incoming_requests:
          +2121                incoming.append(self.deserialize_friend(incoming_request))
          +2122
          +2123        if raw_outgoing_requests := payload.get("outgoingRequests"):
          +2124            for outgoing_request in raw_outgoing_requests:
          +2125                outgoing.append(self.deserialize_friend(outgoing_request))
          +2126
          +2127        return friends.FriendRequestView(incoming=incoming, outgoing=outgoing)
           
          @@ -8630,21 +8592,21 @@
          Returns
          -
          2158    def deserialize_fireteams(
          -2159        self, payload: typedefs.JSONObject
          -2160    ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]:
          -2161        fireteams_: typing.MutableSequence[fireteams.Fireteam] = []
          -2162
          -2163        result: list[typedefs.JSONObject]
          -2164        if not (result := payload["results"]):
          -2165            return None
          -2166        for elem in result:
          -2167            fireteams_.append(
          -2168                self._set_fireteam_fields(
          -2169                    elem, total_results=int(payload["totalResults"])
          -2170                )
          -2171            )
          -2172        return fireteams_
          +            
          2152    def deserialize_fireteams(
          +2153        self, payload: typedefs.JSONObject
          +2154    ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]:
          +2155        fireteams_: typing.MutableSequence[fireteams.Fireteam] = []
          +2156
          +2157        result: list[typedefs.JSONObject]
          +2158        if not (result := payload["results"]):
          +2159            return None
          +2160        for elem in result:
          +2161            fireteams_.append(
          +2162                self._set_fireteam_fields(
          +2163                    elem, total_results=int(payload["totalResults"])
          +2164                )
          +2165            )
          +2166        return fireteams_
           
          @@ -8677,28 +8639,28 @@
          Returns
          -
          2174    def deserialize_fireteam_destiny_users(
          -2175        self, payload: typedefs.JSONObject
          -2176    ) -> fireteams.FireteamUser:
          -2177        destiny_obj = self.deserialize_destiny_membership(payload)
          -2178        # We could helpers.just return a DestinyMembership object but this is
          -2179        # missing the fireteam display name and id fields.
          -2180        return fireteams.FireteamUser(
          -2181            net=self._net,
          -2182            id=destiny_obj.id,
          -2183            code=destiny_obj.code,
          -2184            icon=destiny_obj.icon,
          -2185            types=destiny_obj.types,
          -2186            type=destiny_obj.type,
          -2187            is_public=destiny_obj.is_public,
          -2188            crossave_override=destiny_obj.crossave_override,
          -2189            name=destiny_obj.name,
          -2190            last_seen_name=destiny_obj.last_seen_name,
          -2191            fireteam_display_name=payload["FireteamDisplayName"],
          -2192            fireteam_membership_id=enums.MembershipType(
          -2193                payload["FireteamMembershipType"]
          -2194            ),
          -2195        )
          +            
          2168    def deserialize_fireteam_destiny_users(
          +2169        self, payload: typedefs.JSONObject
          +2170    ) -> fireteams.FireteamUser:
          +2171        destiny_obj = self.deserialize_destiny_membership(payload)
          +2172        # We could helpers.just return a DestinyMembership object but this is
          +2173        # missing the fireteam display name and id fields.
          +2174        return fireteams.FireteamUser(
          +2175            net=self._net,
          +2176            id=destiny_obj.id,
          +2177            code=destiny_obj.code,
          +2178            icon=destiny_obj.icon,
          +2179            types=destiny_obj.types,
          +2180            type=destiny_obj.type,
          +2181            is_public=destiny_obj.is_public,
          +2182            crossave_override=destiny_obj.crossave_override,
          +2183            name=destiny_obj.name,
          +2184            last_seen_name=destiny_obj.last_seen_name,
          +2185            fireteam_display_name=payload["FireteamDisplayName"],
          +2186            fireteam_membership_id=enums.MembershipType(
          +2187                payload["FireteamMembershipType"]
          +2188            ),
          +2189        )
           
          @@ -8731,37 +8693,37 @@
          Returns
          -
          2197    def deserialize_fireteam_members(
          -2198        self, payload: typedefs.JSONObject, *, alternatives: bool = False
          -2199    ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]:
          -2200        members_: list[fireteams.FireteamMember] = []
          -2201        if members := payload.get("Members" if not alternatives else "Alternates"):
          -2202            for member in members:
          -2203                bungie_fields = self.deserialize_partial_bungie_user(member)
          -2204                members_fields = fireteams.FireteamMember(
          -2205                    destiny_user=self.deserialize_fireteam_destiny_users(member),
          -2206                    has_microphone=member["hasMicrophone"],
          -2207                    character_id=int(member["characterId"]),
          -2208                    date_joined=time.clean_date(member["dateJoined"]),
          -2209                    last_platform_invite_date=time.clean_date(
          -2210                        member["lastPlatformInviteAttemptDate"]
          -2211                    ),
          -2212                    last_platform_invite_result=int(
          -2213                        member["lastPlatformInviteAttemptResult"]
          -2214                    ),
          -2215                    net=self._net,
          -2216                    name=bungie_fields.name,
          -2217                    id=bungie_fields.id,
          -2218                    icon=bungie_fields.icon,
          -2219                    is_public=bungie_fields.is_public,
          -2220                    crossave_override=bungie_fields.crossave_override,
          -2221                    types=bungie_fields.types,
          -2222                    type=bungie_fields.type,
          -2223                )
          -2224                members_.append(members_fields)
          -2225        else:
          -2226            return None
          -2227        return members_
          +            
          2191    def deserialize_fireteam_members(
          +2192        self, payload: typedefs.JSONObject, *, alternatives: bool = False
          +2193    ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]:
          +2194        members_: list[fireteams.FireteamMember] = []
          +2195        if members := payload.get("Members" if not alternatives else "Alternates"):
          +2196            for member in members:
          +2197                bungie_fields = self.deserialize_partial_bungie_user(member)
          +2198                members_fields = fireteams.FireteamMember(
          +2199                    destiny_user=self.deserialize_fireteam_destiny_users(member),
          +2200                    has_microphone=member["hasMicrophone"],
          +2201                    character_id=int(member["characterId"]),
          +2202                    date_joined=time.clean_date(member["dateJoined"]),
          +2203                    last_platform_invite_date=time.clean_date(
          +2204                        member["lastPlatformInviteAttemptDate"]
          +2205                    ),
          +2206                    last_platform_invite_result=int(
          +2207                        member["lastPlatformInviteAttemptResult"]
          +2208                    ),
          +2209                    net=self._net,
          +2210                    name=bungie_fields.name,
          +2211                    id=bungie_fields.id,
          +2212                    icon=bungie_fields.icon,
          +2213                    is_public=bungie_fields.is_public,
          +2214                    crossave_override=bungie_fields.crossave_override,
          +2215                    types=bungie_fields.types,
          +2216                    type=bungie_fields.type,
          +2217                )
          +2218                members_.append(members_fields)
          +2219        else:
          +2220            return None
          +2221        return members_
           
          @@ -8797,51 +8759,51 @@
          Returns
          -
          2229    def deserialize_available_fireteams(
          -2230        self,
          -2231        data: typedefs.JSONObject,
          -2232        *,
          -2233        no_results: bool = False,
          -2234    ) -> typing.Union[
          -2235        fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam]
          -2236    ]:
          -2237        fireteams_: list[fireteams.AvailableFireteam] = []
          -2238
          -2239        # This needs to be used outside the results
          -2240        # JSON key.
          -2241        if no_results is True:
          -2242            payload = data
          -2243
          -2244        if result := payload.get("results"):
          -2245
          -2246            for fireteam in result:
          -2247                found_fireteams = self._set_fireteam_fields(fireteam["Summary"])
          -2248                fireteams_fields = fireteams.AvailableFireteam(
          -2249                    id=found_fireteams.id,
          -2250                    group_id=found_fireteams.group_id,
          -2251                    platform=found_fireteams.platform,
          -2252                    activity_type=found_fireteams.activity_type,
          -2253                    is_immediate=found_fireteams.is_immediate,
          -2254                    is_public=found_fireteams.is_public,
          -2255                    is_valid=found_fireteams.is_valid,
          -2256                    owner_id=found_fireteams.owner_id,
          -2257                    player_slot_count=found_fireteams.player_slot_count,
          -2258                    available_player_slots=found_fireteams.available_player_slots,
          -2259                    available_alternate_slots=found_fireteams.available_alternate_slots,
          -2260                    title=found_fireteams.title,
          -2261                    date_created=found_fireteams.date_created,
          -2262                    locale=found_fireteams.locale,
          -2263                    last_modified=found_fireteams.last_modified,
          -2264                    total_results=found_fireteams.total_results,
          -2265                    members=self.deserialize_fireteam_members(payload),
          -2266                    alternatives=self.deserialize_fireteam_members(
          -2267                        payload, alternatives=True
          -2268                    ),
          -2269                )
          -2270            fireteams_.append(fireteams_fields)
          -2271            if no_results:
          -2272                return fireteams_fields
          -2273        return fireteams_
          +            
          2223    def deserialize_available_fireteams(
          +2224        self,
          +2225        data: typedefs.JSONObject,
          +2226        *,
          +2227        no_results: bool = False,
          +2228    ) -> typing.Union[
          +2229        fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam]
          +2230    ]:
          +2231        fireteams_: list[fireteams.AvailableFireteam] = []
          +2232
          +2233        # This needs to be used outside the results
          +2234        # JSON key.
          +2235        if no_results is True:
          +2236            payload = data
          +2237
          +2238        if result := payload.get("results"):
          +2239
          +2240            for fireteam in result:
          +2241                found_fireteams = self._set_fireteam_fields(fireteam["Summary"])
          +2242                fireteams_fields = fireteams.AvailableFireteam(
          +2243                    id=found_fireteams.id,
          +2244                    group_id=found_fireteams.group_id,
          +2245                    platform=found_fireteams.platform,
          +2246                    activity_type=found_fireteams.activity_type,
          +2247                    is_immediate=found_fireteams.is_immediate,
          +2248                    is_public=found_fireteams.is_public,
          +2249                    is_valid=found_fireteams.is_valid,
          +2250                    owner_id=found_fireteams.owner_id,
          +2251                    player_slot_count=found_fireteams.player_slot_count,
          +2252                    available_player_slots=found_fireteams.available_player_slots,
          +2253                    available_alternate_slots=found_fireteams.available_alternate_slots,
          +2254                    title=found_fireteams.title,
          +2255                    date_created=found_fireteams.date_created,
          +2256                    locale=found_fireteams.locale,
          +2257                    last_modified=found_fireteams.last_modified,
          +2258                    total_results=found_fireteams.total_results,
          +2259                    members=self.deserialize_fireteam_members(payload),
          +2260                    alternatives=self.deserialize_fireteam_members(
          +2261                        payload, alternatives=True
          +2262                    ),
          +2263                )
          +2264            fireteams_.append(fireteams_fields)
          +2265            if no_results:
          +2266                return fireteams_fields
          +2267        return fireteams_
           
          @@ -8877,25 +8839,25 @@
          Returns
          -
          2275    def deserialize_fireteam_party(
          -2276        self, payload: typedefs.JSONObject
          -2277    ) -> fireteams.FireteamParty:
          -2278        last_destination_hash: typing.Optional[int] = None
          -2279        if raw_dest_hash := payload.get("lastOrbitedDestinationHash"):
          -2280            last_destination_hash = int(raw_dest_hash)
          -2281
          -2282        return fireteams.FireteamParty(
          -2283            members=[
          -2284                self._deserialize_fireteam_party_member(member)
          -2285                for member in payload["partyMembers"]
          -2286            ],
          -2287            activity=self._deserialize_fireteam_party_current_activity(
          -2288                payload["currentActivity"]
          -2289            ),
          -2290            settings=self._deserialize_fireteam_party_settings(payload["joinability"]),
          -2291            last_destination_hash=last_destination_hash,
          -2292            tracking=payload["tracking"],
          -2293        )
          +            
          2269    def deserialize_fireteam_party(
          +2270        self, payload: typedefs.JSONObject
          +2271    ) -> fireteams.FireteamParty:
          +2272        last_destination_hash: typing.Optional[int] = None
          +2273        if raw_dest_hash := payload.get("lastOrbitedDestinationHash"):
          +2274            last_destination_hash = int(raw_dest_hash)
          +2275
          +2276        return fireteams.FireteamParty(
          +2277            members=[
          +2278                self._deserialize_fireteam_party_member(member)
          +2279                for member in payload["partyMembers"]
          +2280            ],
          +2281            activity=self._deserialize_fireteam_party_current_activity(
          +2282                payload["currentActivity"]
          +2283            ),
          +2284            settings=self._deserialize_fireteam_party_settings(payload["joinability"]),
          +2285            last_destination_hash=last_destination_hash,
          +2286            tracking=payload["tracking"],
          +2287        )
           
          @@ -8928,44 +8890,44 @@
          Returns
          -
          2340    def deserialize_seasonal_artifact(
          -2341        self, payload: typedefs.JSONObject
          -2342    ) -> season.Artifact:
          -2343        if raw_artifact := payload.get("seasonalArtifact"):
          -2344            if points := raw_artifact.get("pointProgression"):
          -2345                points_prog = progressions.Progression(
          -2346                    hash=points["progressionHash"],
          -2347                    level=points["level"],
          -2348                    cap=points["levelCap"],
          -2349                    daily_limit=points["dailyLimit"],
          -2350                    weekly_limit=points["weeklyLimit"],
          -2351                    current_progress=points["currentProgress"],
          -2352                    daily_progress=points["dailyProgress"],
          -2353                    needed=points["progressToNextLevel"],
          -2354                    next_level=points["nextLevelAt"],
          -2355                )
          -2356
          -2357            if bonus := raw_artifact.get("powerBonusProgression"):
          -2358                power_bonus_prog = progressions.Progression(
          -2359                    hash=bonus["progressionHash"],
          -2360                    level=bonus["level"],
          -2361                    cap=bonus["levelCap"],
          -2362                    daily_limit=bonus["dailyLimit"],
          -2363                    weekly_limit=bonus["weeklyLimit"],
          -2364                    current_progress=bonus["currentProgress"],
          -2365                    daily_progress=bonus["dailyProgress"],
          -2366                    needed=bonus["progressToNextLevel"],
          -2367                    next_level=bonus["nextLevelAt"],
          -2368                )
          -2369            artifact = season.Artifact(
          -2370                net=self._net,
          -2371                hash=raw_artifact["artifactHash"],
          -2372                power_bonus=raw_artifact["powerBonus"],
          -2373                acquired_points=raw_artifact["pointsAcquired"],
          -2374                bonus=power_bonus_prog,
          -2375                points=points_prog,
          -2376            )
          -2377        return artifact
          +            
          2334    def deserialize_seasonal_artifact(
          +2335        self, payload: typedefs.JSONObject
          +2336    ) -> season.Artifact:
          +2337        if raw_artifact := payload.get("seasonalArtifact"):
          +2338            if points := raw_artifact.get("pointProgression"):
          +2339                points_prog = progressions.Progression(
          +2340                    hash=points["progressionHash"],
          +2341                    level=points["level"],
          +2342                    cap=points["levelCap"],
          +2343                    daily_limit=points["dailyLimit"],
          +2344                    weekly_limit=points["weeklyLimit"],
          +2345                    current_progress=points["currentProgress"],
          +2346                    daily_progress=points["dailyProgress"],
          +2347                    needed=points["progressToNextLevel"],
          +2348                    next_level=points["nextLevelAt"],
          +2349                )
          +2350
          +2351            if bonus := raw_artifact.get("powerBonusProgression"):
          +2352                power_bonus_prog = progressions.Progression(
          +2353                    hash=bonus["progressionHash"],
          +2354                    level=bonus["level"],
          +2355                    cap=bonus["levelCap"],
          +2356                    daily_limit=bonus["dailyLimit"],
          +2357                    weekly_limit=bonus["weeklyLimit"],
          +2358                    current_progress=bonus["currentProgress"],
          +2359                    daily_progress=bonus["dailyProgress"],
          +2360                    needed=bonus["progressToNextLevel"],
          +2361                    next_level=bonus["nextLevelAt"],
          +2362                )
          +2363            artifact = season.Artifact(
          +2364                net=self._net,
          +2365                hash=raw_artifact["artifactHash"],
          +2366                power_bonus=raw_artifact["powerBonus"],
          +2367                acquired_points=raw_artifact["pointsAcquired"],
          +2368                bonus=power_bonus_prog,
          +2369                points=points_prog,
          +2370            )
          +2371        return artifact
           
          @@ -8998,16 +8960,16 @@
          Returns
          -
          2379    def deserialize_profile_progression(
          -2380        self, payload: typedefs.JSONObject
          -2381    ) -> profile.ProfileProgression:
          -2382        return profile.ProfileProgression(
          -2383            artifact=self.deserialize_seasonal_artifact(payload["data"]),
          -2384            checklist={
          -2385                int(check_id): checklists
          -2386                for check_id, checklists in payload["data"]["checklists"].items()
          -2387            },
          -2388        )
          +            
          2373    def deserialize_profile_progression(
          +2374        self, payload: typedefs.JSONObject
          +2375    ) -> profile.ProfileProgression:
          +2376        return profile.ProfileProgression(
          +2377            artifact=self.deserialize_seasonal_artifact(payload["data"]),
          +2378            checklist={
          +2379                int(check_id): checklists
          +2380                for check_id, checklists in payload["data"]["checklists"].items()
          +2381            },
          +2382        )
           
          @@ -9040,48 +9002,48 @@
          Returns
          -
          2390    def deserialize_instanced_item(
          -2391        self, payload: typedefs.JSONObject
          -2392    ) -> items.ItemInstance:
          -2393        damage_type_hash: typing.Optional[int] = None
          -2394        if raw_damagetype_hash := payload.get("damageTypeHash"):
          -2395            damage_type_hash = int(raw_damagetype_hash)
          -2396
          -2397        required_hashes: typing.Optional[collections.Collection[int]] = None
          -2398        if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"):
          -2399            required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes]
          -2400
          -2401        breaker_type: typing.Optional[items.ItemBreakerType] = None
          -2402        if raw_break_type := payload.get("breakerType"):
          -2403            breaker_type = items.ItemBreakerType(int(raw_break_type))
          -2404
          -2405        breaker_type_hash: typing.Optional[int] = None
          -2406        if raw_break_type_hash := payload.get("breakerTypeHash"):
          -2407            breaker_type_hash = int(raw_break_type_hash)
          -2408
          -2409        energy: typing.Optional[items.ItemEnergy] = None
          -2410        if raw_energy := payload.get("energy"):
          -2411            energy = self.deserialize_item_energy(raw_energy)
          -2412
          -2413        primary_stats = None
          -2414        if raw_primary_stats := payload.get("primaryStat"):
          -2415            primary_stats = self.deserialize_item_stats_view(raw_primary_stats)
          -2416
          -2417        return items.ItemInstance(
          -2418            damage_type=enums.DamageType(int(payload["damageType"])),
          -2419            damage_type_hash=damage_type_hash,
          -2420            primary_stat=primary_stats,
          -2421            item_level=int(payload["itemLevel"]),
          -2422            quality=int(payload["quality"]),
          -2423            is_equipped=payload["isEquipped"],
          -2424            can_equip=payload["canEquip"],
          -2425            equip_required_level=int(payload["equipRequiredLevel"]),
          -2426            required_equip_unlock_hashes=required_hashes,
          -2427            cant_equip_reason=int(payload["cannotEquipReason"]),
          -2428            breaker_type=breaker_type,
          -2429            breaker_type_hash=breaker_type_hash,
          -2430            energy=energy,
          -2431        )
          +            
          2384    def deserialize_instanced_item(
          +2385        self, payload: typedefs.JSONObject
          +2386    ) -> items.ItemInstance:
          +2387        damage_type_hash: typing.Optional[int] = None
          +2388        if raw_damagetype_hash := payload.get("damageTypeHash"):
          +2389            damage_type_hash = int(raw_damagetype_hash)
          +2390
          +2391        required_hashes: typing.Optional[collections.Collection[int]] = None
          +2392        if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"):
          +2393            required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes]
          +2394
          +2395        breaker_type: typing.Optional[items.ItemBreakerType] = None
          +2396        if raw_break_type := payload.get("breakerType"):
          +2397            breaker_type = items.ItemBreakerType(int(raw_break_type))
          +2398
          +2399        breaker_type_hash: typing.Optional[int] = None
          +2400        if raw_break_type_hash := payload.get("breakerTypeHash"):
          +2401            breaker_type_hash = int(raw_break_type_hash)
          +2402
          +2403        energy: typing.Optional[items.ItemEnergy] = None
          +2404        if raw_energy := payload.get("energy"):
          +2405            energy = self.deserialize_item_energy(raw_energy)
          +2406
          +2407        primary_stats = None
          +2408        if raw_primary_stats := payload.get("primaryStat"):
          +2409            primary_stats = self.deserialize_item_stats_view(raw_primary_stats)
          +2410
          +2411        return items.ItemInstance(
          +2412            damage_type=enums.DamageType(int(payload["damageType"])),
          +2413            damage_type_hash=damage_type_hash,
          +2414            primary_stat=primary_stats,
          +2415            item_level=int(payload["itemLevel"]),
          +2416            quality=int(payload["quality"]),
          +2417            is_equipped=payload["isEquipped"],
          +2418            can_equip=payload["canEquip"],
          +2419            equip_required_level=int(payload["equipRequiredLevel"]),
          +2420            required_equip_unlock_hashes=required_hashes,
          +2421            cant_equip_reason=int(payload["cannotEquipReason"]),
          +2422            breaker_type=breaker_type,
          +2423            breaker_type_hash=breaker_type_hash,
          +2424            energy=energy,
          +2425        )
           
          @@ -9114,18 +9076,18 @@
          Returns
          -
          2433    def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy:
          -2434        energy_hash: typing.Optional[int] = None
          -2435        if raw_energy_hash := payload.get("energyTypeHash"):
          -2436            energy_hash = int(raw_energy_hash)
          -2437
          -2438        return items.ItemEnergy(
          -2439            hash=energy_hash,
          -2440            type=items.ItemEnergyType(int(payload["energyType"])),
          -2441            capacity=int(payload["energyCapacity"]),
          -2442            used_energy=int(payload["energyUsed"]),
          -2443            unused_energy=int(payload["energyUnused"]),
          -2444        )
          +            
          2427    def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy:
          +2428        energy_hash: typing.Optional[int] = None
          +2429        if raw_energy_hash := payload.get("energyTypeHash"):
          +2430            energy_hash = int(raw_energy_hash)
          +2431
          +2432        return items.ItemEnergy(
          +2433            hash=energy_hash,
          +2434            type=items.ItemEnergyType(int(payload["energyType"])),
          +2435            capacity=int(payload["energyCapacity"]),
          +2436            used_energy=int(payload["energyUsed"]),
          +2437            unused_energy=int(payload["energyUnused"]),
          +2438        )
           
          @@ -9143,17 +9105,17 @@
          Returns
          -
          2446    def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk:
          -2447        perk_hash: typing.Optional[int] = None
          -2448        if raw_perk_hash := payload.get("perkHash"):
          -2449            perk_hash = int(raw_perk_hash)
          -2450
          -2451        return items.ItemPerk(
          -2452            hash=perk_hash,
          -2453            icon=assets.Image(payload["iconPath"]),
          -2454            is_active=payload["isActive"],
          -2455            is_visible=payload["visible"],
          -2456        )
          +            
          2440    def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk:
          +2441        perk_hash: typing.Optional[int] = None
          +2442        if raw_perk_hash := payload.get("perkHash"):
          +2443            perk_hash = int(raw_perk_hash)
          +2444
          +2445        return items.ItemPerk(
          +2446            hash=perk_hash,
          +2447            icon=assets.Image(payload["iconPath"]),
          +2448            is_active=payload["isActive"],
          +2449            is_visible=payload["visible"],
          +2450        )
           
          @@ -9171,21 +9133,21 @@
          Returns
          -
          2458    def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket:
          -2459        plug_hash: typing.Optional[int] = None
          -2460        if raw_plug_hash := payload.get("plugHash"):
          -2461            plug_hash = int(raw_plug_hash)
          -2462
          -2463        enable_fail_indexes: typing.Optional[list[int]] = None
          -2464        if raw_indexes := payload.get("enableFailIndexes"):
          -2465            enable_fail_indexes = [int(index) for index in raw_indexes]
          -2466
          -2467        return items.ItemSocket(
          -2468            plug_hash=plug_hash,
          -2469            is_enabled=payload["isEnabled"],
          -2470            enable_fail_indexes=enable_fail_indexes,
          -2471            is_visible=payload.get("visible"),
          -2472        )
          +            
          2452    def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket:
          +2453        plug_hash: typing.Optional[int] = None
          +2454        if raw_plug_hash := payload.get("plugHash"):
          +2455            plug_hash = int(raw_plug_hash)
          +2456
          +2457        enable_fail_indexes: typing.Optional[list[int]] = None
          +2458        if raw_indexes := payload.get("enableFailIndexes"):
          +2459            enable_fail_indexes = [int(index) for index in raw_indexes]
          +2460
          +2461        return items.ItemSocket(
          +2462            plug_hash=plug_hash,
          +2463            is_enabled=payload["isEnabled"],
          +2464            enable_fail_indexes=enable_fail_indexes,
          +2465            is_visible=payload.get("visible"),
          +2466        )
           
          @@ -9203,12 +9165,12 @@
          Returns
          -
          2474    def deserialize_item_stats_view(
          -2475        self, payload: typedefs.JSONObject
          -2476    ) -> items.ItemStatsView:
          -2477        return items.ItemStatsView(
          -2478            stat_hash=payload.get("statHash"), value=payload.get("value")
          -2479        )
          +            
          2468    def deserialize_item_stats_view(
          +2469        self, payload: typedefs.JSONObject
          +2470    ) -> items.ItemStatsView:
          +2471        return items.ItemStatsView(
          +2472            stat_hash=payload.get("statHash"), value=payload.get("value")
          +2473        )
           
          @@ -9226,28 +9188,28 @@
          Returns
          -
          2481    def deserialize_plug_item_state(
          -2482        self, payload: typedefs.JSONObject
          -2483    ) -> items.PlugItemState:
          -2484        item_hash: typing.Optional[int] = None
          -2485        if raw_item_hash := payload.get("plugItemHash"):
          -2486            item_hash = int(raw_item_hash)
          -2487
          -2488        insert_fail_indexes: typedefs.NoneOr[list[int]] = None
          -2489        if raw_fail_indexes := payload.get("insertFailIndexes"):
          -2490            insert_fail_indexes = [int(k) for k in raw_fail_indexes]
          -2491
          -2492        enable_fail_indexes: typedefs.NoneOr[list[int]] = None
          -2493        if raw_enabled_indexes := payload.get("enableFailIndexes"):
          -2494            enable_fail_indexes = [int(k) for k in raw_enabled_indexes]
          -2495
          -2496        return items.PlugItemState(
          -2497            item_hash=item_hash,
          -2498            insert_fail_indexes=insert_fail_indexes,
          -2499            enable_fail_indexes=enable_fail_indexes,
          -2500            is_enabled=payload["enabled"],
          -2501            can_insert=payload["canInsert"],
          -2502        )
          +            
          2475    def deserialize_plug_item_state(
          +2476        self, payload: typedefs.JSONObject
          +2477    ) -> items.PlugItemState:
          +2478        item_hash: typing.Optional[int] = None
          +2479        if raw_item_hash := payload.get("plugItemHash"):
          +2480            item_hash = int(raw_item_hash)
          +2481
          +2482        insert_fail_indexes: typedefs.NoneOr[list[int]] = None
          +2483        if raw_fail_indexes := payload.get("insertFailIndexes"):
          +2484            insert_fail_indexes = [int(k) for k in raw_fail_indexes]
          +2485
          +2486        enable_fail_indexes: typedefs.NoneOr[list[int]] = None
          +2487        if raw_enabled_indexes := payload.get("enableFailIndexes"):
          +2488            enable_fail_indexes = [int(k) for k in raw_enabled_indexes]
          +2489
          +2490        return items.PlugItemState(
          +2491            item_hash=item_hash,
          +2492            insert_fail_indexes=insert_fail_indexes,
          +2493            enable_fail_indexes=enable_fail_indexes,
          +2494            is_enabled=payload["enabled"],
          +2495            can_insert=payload["canInsert"],
          +2496        )
           
          @@ -9358,7 +9320,11 @@
          Returns
          let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/internal/helpers.html b/docs/aiobungie/internal/helpers.html index e0a889a3..c20e31bf 100644 --- a/docs/aiobungie/internal/helpers.html +++ b/docs/aiobungie/internal/helpers.html @@ -3,7 +3,7 @@ - + aiobungie.internal.helpers API documentation @@ -61,9 +61,9 @@

          A helper module the provides functions, classes for various of uses.

          - + - +
            1# MIT License
             2#
          @@ -615,7 +615,11 @@ 
          Parameters
          let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/internal/iterators.html b/docs/aiobungie/internal/iterators.html index 8300a2b2..72648278 100644 --- a/docs/aiobungie/internal/iterators.html +++ b/docs/aiobungie/internal/iterators.html @@ -3,7 +3,7 @@ - + aiobungie.internal.iterators API documentation @@ -31,70 +31,67 @@

          API Documentation

          • - FlatIterator + Iterator @@ -121,9 +118,9 @@

            Module contains a Standard functional iterator implementation.

            - + - +
              1# MIT License
               2#
            @@ -150,7 +147,7 @@ 

            23 24from __future__ import annotations 25 - 26__all__: tuple[str, ...] = ("FlatIterator", "into_iter") + 26__all__: tuple[str, ...] = ("Iterator", "into_iter") 27 28import collections.abc as collections 29import itertools @@ -168,13 +165,13 @@

            41 _B = typing.TypeVar("_B", bound=collections.Callable[..., typing.Any]) 42 43 - 44class FlatIterator(typing.Generic[Item]): + 44class Iterator(typing.Generic[Item]): 45 """A Flat, In-Memory iterator for sequenced based data. 46 47 Example 48 ------- 49 ```py - 50 iterator = FlatIterator([1, 2, 3]) + 50 iterator = Iterator([1, 2, 3]) 51 52 # Map the results. 53 for item in iterator.map(lambda item: item * 2): @@ -194,9 +191,9 @@

            67 # 3 68 69 # Union two iterators. - 70 iterator2 = FlatIterator([4, 5, 6]) + 70 iterator2 = Iterator([4, 5, 6]) 71 final = iterator | iterator2 - 72 # <FlatIterator([1, 2, 3, 4, 5, 6])> + 72 # <Iterator([1, 2, 3, 4, 5, 6])> 73 ``` 74 75 Parameters @@ -225,7 +222,7 @@

            98 99 Example 100 ------- -101 >>> iterator = FlatIterator([1, 2, 3]) +101 >>> iterator = Iterator([1, 2, 3]) 102 >>> iterator.collect(casting=str) 103 ["1", "2", "3"] 104 @@ -250,7 +247,7 @@

            123 Example 124 ------- 125 ```py -126 iterator = FlatIterator(["1", "2", "3"]) +126 iterator = Iterator(["1", "2", "3"]) 127 item = iterator.next() 128 assert item == "1" 129 item = iterator.next() @@ -269,15 +266,15 @@

            142 143 def map( 144 self, predicate: collections.Callable[[Item], OtherItem] -145 ) -> FlatIterator[OtherItem]: +145 ) -> Iterator[OtherItem]: 146 """Maps each item in the iterator to its predicated value. 147 148 Example 149 ------- 150 ```py -151 iterator = FlatIterator(["1", "2", "3"]).map(lambda value: int(value)) +151 iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value)) 152 print(iterator) -153 # <FlatIterator([1, 2, 3])> +153 # <Iterator([1, 2, 3])> 154 ``` 155 156 Parameters @@ -287,7 +284,7 @@

            160 161 Returns 162 ------- -163 `FlatIterator[OtherItem]` +163 `Iterator[OtherItem]` 164 The mapped iterator. 165 166 Raises @@ -295,18 +292,18 @@

            168 `StopIteration` 169 If no elements are left in the iterator. 170 """ -171 return FlatIterator(map(predicate, self._items)) +171 return Iterator(map(predicate, self._items)) 172 -173 def take(self, n: int) -> FlatIterator[Item]: +173 def take(self, n: int) -> Iterator[Item]: 174 """Take the first number of items until the number of items are yielded or 175 the end of the iterator is reached. 176 177 Example 178 ------- 179 ```py -180 iterator = FlatIterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT]) +180 iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT]) 181 print(iterator.take(2)) -182 # <FlatIterator([GameMode.RAID, GameMode.STRIKE])> +182 # <Iterator([GameMode.RAID, GameMode.STRIKE])> 183 ``` 184 185 Parameters @@ -319,19 +316,19 @@

            192 `StopIteration` 193 If no elements are left in the iterator. 194 """ -195 return FlatIterator(itertools.islice(self._items, n)) +195 return Iterator(itertools.islice(self._items, n)) 196 197 def take_while( 198 self, predicate: collections.Callable[[Item], bool] -199 ) -> FlatIterator[Item]: +199 ) -> Iterator[Item]: 200 """Yields items from the iterator while predicate returns `True`. 201 202 Example 203 ------- 204 ```py -205 iterator = FlatIterator([STEAM, XBOX, STADIA]) +205 iterator = Iterator([STEAM, XBOX, STADIA]) 206 print(iterator.take_while(lambda platform: platform is not XBOX)) -207 # <FlatIterator([STEAM])> +207 # <Iterator([STEAM])> 208 ``` 209 210 Parameters @@ -344,19 +341,19 @@

            217 `StopIteration` 218 If no elements are left in the iterator. 219 """ -220 return FlatIterator(itertools.takewhile(predicate, self._items)) +220 return Iterator(itertools.takewhile(predicate, self._items)) 221 222 def drop_while( 223 self, predicate: collections.Callable[[Item], bool] -224 ) -> FlatIterator[Item]: +224 ) -> Iterator[Item]: 225 """Yields items from the iterator while predicate returns `False`. 226 227 Example 228 ------- 229 ```py -230 iterator = FlatIterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")]) +230 iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")]) 231 print(iterator.drop_while(lambda membership: membership.name is not "Jim")) -232 # <FlatIterator([DestinyMembership(name="Bob")])> +232 # <Iterator([DestinyMembership(name="Bob")])> 233 ``` 234 235 Parameters @@ -369,931 +366,873 @@

            242 `StopIteration` 243 If no elements are left in the iterator. 244 """ -245 return FlatIterator(itertools.dropwhile(predicate, self._items)) +245 return Iterator(itertools.dropwhile(predicate, self._items)) 246 -247 def filter( -248 self, predicate: collections.Callable[[Item], bool] -249 ) -> FlatIterator[Item]: -250 """Filters the iterator to only yield items that match the predicate. -251 -252 Example -253 ------- -254 ```py -255 names = FlatIterator(["Jim", "Bob", "Mike", "Jess"]) -256 print(names.filter(lambda n: n != "Jim")) -257 # <FlatIterator(["Bob", "Mike", "Jess"])> -258 ``` -259 """ -260 return FlatIterator(filter(predicate, self._items)) -261 -262 def skip(self, n: int) -> FlatIterator[Item]: -263 """Skips the first number of items in the iterator. -264 -265 Example -266 ------- -267 ```py -268 iterator = FlatIterator([STEAM, XBOX, STADIA]) -269 print(iterator.skip(1)) -270 # <FlatIterator([XBOX, STADIA])> -271 ``` -272 """ -273 return FlatIterator(itertools.islice(self._items, n, None)) -274 -275 def discard( -276 self, predicate: collections.Callable[[Item], bool] -277 ) -> FlatIterator[Item]: -278 """Discards all elements in the iterator for which the predicate function returns true. -279 -280 Example -281 ------- -282 ```py -283 iterator = FlatIterator(['A', 'B', 'C']) -284 print(iterator.discard(lambda x: x == 'B')) -285 # <FlatIterator(['A', 'C'])> -286 ``` -287 -288 Parameters -289 ---------- -290 predicate: `collections.Callable[[Item], bool]` -291 The function to test each item in the iterator. -292 -293 Raises -294 ------ -295 `StopIteration` -296 If no elements are left in the iterator. -297 """ -298 return FlatIterator(filter(lambda x: not predicate(x), self._items)) -299 -300 def zip( -301 self, other: FlatIterator[OtherItem] -302 ) -> FlatIterator[tuple[Item, OtherItem]]: -303 """Zips the iterator with another iterable. -304 -305 Example -306 ------- -307 ```py -308 iterator = FlatIterator([1, 3, 5]) -309 other = FlatIterator([2, 4, 6]) -310 for item, other_item in iterator.zip(other): -311 print(item, other_item) -312 # <FlatIterator([(1, 2), (3, 4), (5, 6)])> -313 ``` -314 -315 Parameters -316 ---------- -317 other: `FlatIterator[OtherItem]` -318 The iterable to zip with. -319 -320 Raises -321 ------ -322 `StopIteration` -323 If no elements are left in the iterator. -324 """ -325 return FlatIterator(zip(self._items, other)) -326 -327 def all(self, predicate: collections.Callable[[Item], bool]) -> bool: -328 """`True` if all items in the iterator match the predicate. -329 -330 Example -331 ------- -332 ```py -333 iterator = FlatIterator([1, 2, 3]) -334 while iterator.all(lambda item: isinstance(item, int)): -335 print("Still all integers") -336 continue -337 # Still all integers -338 ``` +247 def filter(self, predicate: collections.Callable[[Item], bool]) -> Iterator[Item]: +248 """Filters the iterator to only yield items that match the predicate. +249 +250 Example +251 ------- +252 ```py +253 names = Iterator(["Jim", "Bob", "Mike", "Jess"]) +254 print(names.filter(lambda n: n != "Jim")) +255 # <Iterator(["Bob", "Mike", "Jess"])> +256 ``` +257 """ +258 return Iterator(filter(predicate, self._items)) +259 +260 def skip(self, n: int) -> Iterator[Item]: +261 """Skips the first number of items in the iterator. +262 +263 Example +264 ------- +265 ```py +266 iterator = Iterator([STEAM, XBOX, STADIA]) +267 print(iterator.skip(1)) +268 # <Iterator([XBOX, STADIA])> +269 ``` +270 """ +271 return Iterator(itertools.islice(self._items, n, None)) +272 +273 def zip(self, other: Iterator[OtherItem]) -> Iterator[tuple[Item, OtherItem]]: +274 """Zips the iterator with another iterable. +275 +276 Example +277 ------- +278 ```py +279 iterator = Iterator([1, 3, 5]) +280 other = Iterator([2, 4, 6]) +281 for item, other_item in iterator.zip(other): +282 print(item, other_item) +283 # <Iterator([(1, 2), (3, 4), (5, 6)])> +284 ``` +285 +286 Parameters +287 ---------- +288 other: `Iterator[OtherItem]` +289 The iterable to zip with. +290 +291 Raises +292 ------ +293 `StopIteration` +294 If no elements are left in the iterator. +295 """ +296 return Iterator(zip(self._items, other)) +297 +298 def all(self, predicate: collections.Callable[[Item], bool]) -> bool: +299 """`True` if all items in the iterator match the predicate. +300 +301 Example +302 ------- +303 ```py +304 iterator = Iterator([1, 2, 3]) +305 while iterator.all(lambda item: isinstance(item, int)): +306 print("Still all integers") +307 continue +308 # Still all integers +309 ``` +310 +311 Parameters +312 ---------- +313 predicate: `collections.Callable[[Item], bool]` +314 The function to test each item in the iterator. +315 +316 Raises +317 ------ +318 `StopIteration` +319 If no elements are left in the iterator. +320 """ +321 return all(predicate(item) for item in self) +322 +323 def any(self, predicate: collections.Callable[[Item], bool]) -> bool: +324 """`True` if any items in the iterator match the predicate. +325 +326 Example +327 ------- +328 ```py +329 iterator = Iterator([1, 2, 3]) +330 if iterator.any(lambda item: isinstance(item, int)): +331 print("At least one item is an int.") +332 # At least one item is an int. +333 ``` +334 +335 Parameters +336 ---------- +337 predicate: `collections.Callable[[Item], bool]` +338 The function to test each item in the iterator. 339 -340 Parameters -341 ---------- -342 predicate: `collections.Callable[[Item], bool]` -343 The function to test each item in the iterator. -344 -345 Raises -346 ------ -347 `StopIteration` -348 If no elements are left in the iterator. -349 """ -350 return all(predicate(item) for item in self) -351 -352 def any(self, predicate: collections.Callable[[Item], bool]) -> bool: -353 """`True` if any items in the iterator match the predicate. +340 Raises +341 ------ +342 `StopIteration` +343 If no elements are left in the iterator. +344 """ +345 return any(predicate(item) for item in self) +346 +347 def sort( +348 self, +349 *, +350 key: collections.Callable[[Item], typeshed.SupportsRichComparison], +351 reverse: bool = False, +352 ) -> Iterator[Item]: +353 """Sorts the iterator. 354 355 Example 356 ------- 357 ```py -358 iterator = FlatIterator([1, 2, 3]) -359 if iterator.any(lambda item: isinstance(item, int)): -360 print("At least one item is an int.") -361 # At least one item is an int. -362 ``` -363 -364 Parameters -365 ---------- -366 predicate: `collections.Callable[[Item], bool]` -367 The function to test each item in the iterator. -368 -369 Raises -370 ------ -371 `StopIteration` -372 If no elements are left in the iterator. -373 """ -374 return any(predicate(item) for item in self) -375 -376 def sort( -377 self, -378 *, -379 key: collections.Callable[[Item], typeshed.SupportsRichComparison], -380 reverse: bool = False, -381 ) -> FlatIterator[Item]: -382 """Sorts the iterator. -383 -384 Example -385 ------- -386 ```py -387 iterator = FlatIterator([3, 1, 6, 7]) -388 print(iterator.sort(key=lambda item: item)) -389 # <FlatIterator([1, 3, 6, 7])> -390 ``` -391 -392 Parameters -393 ---------- -394 key: `collections.Callable[[Item], Any]` -395 The function to sort by. -396 reverse: `bool` -397 Whether to reverse the sort. -398 -399 Raises -400 ------ -401 `StopIteration` -402 If no elements are left in the iterator. -403 """ -404 return FlatIterator(sorted(self._items, key=key, reverse=reverse)) +358 iterator = Iterator([3, 1, 6, 7]) +359 print(iterator.sort(key=lambda item: item)) +360 # <Iterator([1, 3, 6, 7])> +361 ``` +362 +363 Parameters +364 ---------- +365 key: `collections.Callable[[Item], Any]` +366 The function to sort by. +367 reverse: `bool` +368 Whether to reverse the sort. +369 +370 Raises +371 ------ +372 `StopIteration` +373 If no elements are left in the iterator. +374 """ +375 return Iterator(sorted(self._items, key=key, reverse=reverse)) +376 +377 def first(self) -> Item: +378 """Returns the first item in the iterator. +379 +380 Example +381 ------- +382 ```py +383 iterator = Iterator([3, 1, 6, 7]) +384 print(iterator.first()) +385 3 +386 ``` +387 +388 Raises +389 ------ +390 `StopIteration` +391 If no elements are left in the iterator. +392 """ +393 return self.take(1).next() +394 +395 def reversed(self) -> Iterator[Item]: +396 """Returns a new iterator that yields the items in the iterator in reverse order. +397 +398 Example +399 ------- +400 ```py +401 iterator = Iterator([3, 1, 6, 7]) +402 print(iterator.reversed()) +403 # <Iterator([7, 6, 1, 3])> +404 ``` 405 -406 def first(self) -> Item: -407 """Returns the first item in the iterator. -408 -409 Example -410 ------- -411 ```py -412 iterator = FlatIterator([3, 1, 6, 7]) -413 print(iterator.first()) -414 3 -415 ``` -416 -417 Raises -418 ------ -419 `StopIteration` -420 If no elements are left in the iterator. -421 """ -422 return self.take(1).next() -423 -424 def reversed(self) -> FlatIterator[Item]: -425 """Returns a new iterator that yields the items in the iterator in reverse order. -426 -427 Example -428 ------- -429 ```py -430 iterator = FlatIterator([3, 1, 6, 7]) -431 print(iterator.reversed()) -432 # <FlatIterator([7, 6, 1, 3])> -433 ``` -434 -435 Raises -436 ------ -437 `StopIteration` -438 If no elements are left in the iterator. -439 """ -440 return FlatIterator(reversed(self.collect())) +406 Raises +407 ------ +408 `StopIteration` +409 If no elements are left in the iterator. +410 """ +411 return Iterator(reversed(self.collect())) +412 +413 def count(self) -> int: +414 """Returns the number of items in the iterator. +415 +416 Example +417 ------- +418 ```py +419 iterator = Iterator([3, 1, 6, 7]) +420 print(iterator.count()) +421 4 +422 ``` +423 """ +424 count = 0 +425 for _ in self: +426 count += 1 +427 +428 return count +429 +430 def union(self, other: Iterator[Item]) -> Iterator[Item]: +431 """Returns a new iterator that yields all items from both iterators. +432 +433 Example +434 ------- +435 ```py +436 iterator = Iterator([1, 2, 3]) +437 other = Iterator([4, 5, 6]) +438 print(iterator.union(other)) +439 # <Iterator([1, 2, 3, 4, 5, 6])> +440 ``` 441 -442 def count(self) -> int: -443 """Returns the number of items in the iterator. -444 -445 Example -446 ------- -447 ```py -448 iterator = FlatIterator([3, 1, 6, 7]) -449 print(iterator.count()) -450 4 -451 ``` -452 """ -453 count = 0 -454 for _ in self: -455 count += 1 +442 Parameters +443 ---------- +444 other: `Iterator[Item]` +445 The iterable to union with. +446 +447 Raises +448 ------ +449 `StopIteration` +450 If no elements are left in the iterator. +451 """ +452 return Iterator(itertools.chain(self._items, other)) +453 +454 def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None: +455 """Calls the function on each item in the iterator. 456 -457 return count -458 -459 def union(self, other: FlatIterator[Item]) -> FlatIterator[Item]: -460 """Returns a new iterator that yields all items from both iterators. -461 -462 Example -463 ------- -464 ```py -465 iterator = FlatIterator([1, 2, 3]) -466 other = FlatIterator([4, 5, 6]) -467 print(iterator.union(other)) -468 # <FlatIterator([1, 2, 3, 4, 5, 6])> -469 ``` -470 -471 Parameters -472 ---------- -473 other: `FlatIterator[Item]` -474 The iterable to union with. -475 -476 Raises -477 ------ -478 `StopIteration` -479 If no elements are left in the iterator. -480 """ -481 return FlatIterator(itertools.chain(self._items, other)) -482 -483 def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None: -484 """Calls the function on each item in the iterator. -485 -486 Example -487 ------- -488 ```py -489 iterator = FlatIterator([1, 2, 3]) -490 iterator.for_each(lambda item: print(item)) -491 # 1 -492 # 2 -493 # 3 -494 ``` -495 -496 Parameters -497 ---------- -498 func: `typeshed.Callable[[Item], None]` -499 The function to call on each item in the iterator. -500 """ -501 for item in self: -502 func(item) +457 Example +458 ------- +459 ```py +460 iterator = Iterator([1, 2, 3]) +461 iterator.for_each(lambda item: print(item)) +462 # 1 +463 # 2 +464 # 3 +465 ``` +466 +467 Parameters +468 ---------- +469 func: `typeshed.Callable[[Item], None]` +470 The function to call on each item in the iterator. +471 """ +472 for item in self: +473 func(item) +474 +475 async def async_for_each( +476 self, +477 func: collections.Callable[[Item], collections.Coroutine[None, None, None]], +478 ) -> None: +479 """Calls the async function on each item in the iterator concurrently. +480 +481 Example +482 ------- +483 ```py +484 async def signup(username: str) -> None: +485 async with aiohttp.request('POST', '...') as r: +486 # Actual logic. +487 ... +488 +489 async def main(): +490 users = aiobungie.into_iter(["user_danny", "user_jojo"]) +491 await users.async_for_each(lambda username: signup(username)) +492 ``` +493 +494 Parameters +495 ---------- +496 func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]` +497 The async function to call on each item in the iterator. +498 """ +499 await _helpers.awaits(*(func(item) for item in self)) +500 +501 def enumerate(self, *, start: int = 0) -> Iterator[tuple[int, Item]]: +502 """Returns a new iterator that yields tuples of the index and item. 503 -504 async def async_for_each( -505 self, -506 func: collections.Callable[[Item], collections.Coroutine[None, None, None]], -507 ) -> None: -508 """Calls the async function on each item in the iterator concurrently. -509 -510 Example -511 ------- -512 ```py -513 async def signup(username: str) -> None: -514 async with aiohttp.request('POST', '...') as r: -515 # Actual logic. -516 ... -517 -518 async def main(): -519 users = aiobungie.into_iter(["user_danny", "user_jojo"]) -520 await users.async_for_each(lambda username: signup(username)) -521 ``` -522 -523 Parameters -524 ---------- -525 func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]` -526 The async function to call on each item in the iterator. -527 """ -528 await _helpers.awaits(*(func(item) for item in self)) -529 -530 def enumerate(self, *, start: int = 0) -> FlatIterator[tuple[int, Item]]: -531 """Returns a new iterator that yields tuples of the index and item. -532 -533 Example -534 ------- -535 ```py -536 iterator = FlatIterator([1, 2, 3]) -537 for index, item in iterator.enumerate(): -538 print(index, item) -539 # 0 1 -540 # 1 2 -541 # 2 3 -542 ``` -543 -544 Raises -545 ------ -546 `StopIteration` -547 If no elements are left in the iterator. -548 """ -549 return FlatIterator(enumerate(self._items, start=start)) -550 -551 def _ok(self) -> typing.NoReturn: -552 raise StopIteration("No more items in the iterator.") from None -553 -554 def __getitem__(self, index: int) -> Item: -555 try: -556 return self.skip(index).first() -557 except IndexError: -558 self._ok() -559 -560 def __or__(self, other: FlatIterator[Item]) -> FlatIterator[Item]: -561 return self.union(other) +504 Example +505 ------- +506 ```py +507 iterator = Iterator([1, 2, 3]) +508 for index, item in iterator.enumerate(): +509 print(index, item) +510 # 0 1 +511 # 1 2 +512 # 2 3 +513 ``` +514 +515 Raises +516 ------ +517 `StopIteration` +518 If no elements are left in the iterator. +519 """ +520 return Iterator(enumerate(self._items, start=start)) +521 +522 def _ok(self) -> typing.NoReturn: +523 raise StopIteration("No more items in the iterator.") from None +524 +525 def __getitem__(self, index: int) -> Item: +526 try: +527 return self.skip(index).first() +528 except IndexError: +529 self._ok() +530 +531 def __or__(self, other: Iterator[Item]) -> Iterator[Item]: +532 return self.union(other) +533 +534 # This is a never. +535 def __setitem__(self) -> typing.NoReturn: +536 raise TypeError( +537 f"{type(self).__name__} doesn't support item assignment." +538 ) from None +539 +540 def __repr__(self) -> str: +541 return f'<{self.__class__.__name__}({", ".join([str(item) for item in self])})>' +542 +543 def __len__(self) -> int: +544 return self.count() +545 +546 def __iter__(self) -> Iterator[Item]: +547 return self +548 +549 def __next__(self) -> Item: +550 try: +551 item = next(self._items) +552 except StopIteration: +553 self._ok() +554 +555 return item +556 +557 +558def into_iter( +559 iterable: collections.Iterable[Item], +560) -> Iterator[Item]: +561 """Transform an iterable into an flat iterator. 562 -563 # This is a never. -564 def __setitem__(self) -> typing.NoReturn: -565 raise TypeError( -566 f"{type(self).__name__} doesn't support item assignment." -567 ) from None -568 -569 def __repr__(self) -> str: -570 return f'<{self.__class__.__name__}({", ".join([str(item) for item in self])})>' -571 -572 def __len__(self) -> int: -573 return self.count() -574 -575 def __iter__(self) -> FlatIterator[Item]: -576 return self -577 -578 def __next__(self) -> Item: -579 try: -580 item = next(self._items) -581 except StopIteration: -582 self._ok() -583 -584 return item -585 -586 -587def into_iter( -588 iterable: collections.Iterable[Item], -589) -> FlatIterator[Item]: -590 """Transform an iterable into an flat iterator. -591 -592 Example -593 ------- -594 ```py -595 sequence = [1,2,3] -596 for item in aiobungie.into_iter(sequence).reversed(): -597 print(item) -598 # 3 -599 # 2 -600 # 1 -601 ``` -602 -603 Parameters -604 ---------- -605 iterable: `typing.Iterable[Item]` -606 The iterable to convert. -607 -608 Raises -609 ------ -610 `StopIteration` -611 If no elements are left in the iterator. -612 """ -613 return FlatIterator(iterable) +563 Example +564 ------- +565 ```py +566 sequence = [1,2,3] +567 for item in aiobungie.into_iter(sequence).reversed(): +568 print(item) +569 # 3 +570 # 2 +571 # 1 +572 ``` +573 +574 Parameters +575 ---------- +576 iterable: `typing.Iterable[Item]` +577 The iterable to convert. +578 +579 Raises +580 ------ +581 `StopIteration` +582 If no elements are left in the iterator. +583 """ +584 return Iterator(iterable)

            -
            - +
            +
            class - FlatIterator(typing.Generic[~Item]): + Iterator(typing.Generic[~Item]): - +
            - -
             45class FlatIterator(typing.Generic[Item]):
            - 46    """A Flat, In-Memory iterator for sequenced based data.
            - 47
            - 48    Example
            - 49    -------
            - 50    ```py
            - 51    iterator = FlatIterator([1, 2, 3])
            - 52
            - 53    # Map the results.
            - 54    for item in iterator.map(lambda item: item * 2):
            - 55        print(item)
            - 56    # 2
            - 57    # 4
            - 58
            - 59    # Indexing is also supported.
            - 60    print(iterator[0])
            - 61    # 1
            - 62
            - 63    # Normal iteration.
            - 64    for item in iterator:
            - 65        print(item)
            - 66    # 1
            - 67    # 2
            - 68    # 3
            - 69
            - 70    # Union two iterators.
            - 71    iterator2 = FlatIterator([4, 5, 6])
            - 72    final = iterator | iterator2
            - 73    # <FlatIterator([1, 2, 3, 4, 5, 6])>
            - 74    ```
            - 75
            - 76    Parameters
            - 77    ----------
            - 78    items: `collections.Iterable[Item]`
            - 79        The items to iterate over.
            - 80    """
            - 81
            - 82    __slots__ = ("_items",)
            - 83
            - 84    def __init__(self, items: collections.Iterable[Item]) -> None:
            - 85        self._items = iter(items)
            - 86
            - 87    @typing.overload
            - 88    def collect(self) -> list[Item]:
            - 89        ...
            - 90
            - 91    @typing.overload
            - 92    def collect(self, casting: _B) -> list[_B]:
            - 93        ...
            - 94
            - 95    def collect(
            - 96        self, casting: typing.Optional[_B] = None
            - 97    ) -> typing.Union[list[Item], list[_B]]:
            - 98        """Collects all items in the iterator into a list and cast them into an object if provided.
            - 99
            -100        Example
            -101        -------
            -102        >>> iterator = FlatIterator([1, 2, 3])
            -103        >>> iterator.collect(casting=str)
            -104        ["1", "2", "3"]
            -105
            -106        Parameters
            -107        ----------
            -108        casting: `T | None`
            -109            The type to cast the items to. If `None` is provided, the items will be returned as is.
            -110
            -111        Raises
            -112        ------
            -113        `StopIteration`
            -114            If no elements are left in the iterator.
            -115        """
            -116        if casting is not None:
            -117            return typing.cast(list[_B], list(map(casting, self._items)))
            -118
            -119        return list(self._items)
            -120
            -121    def next(self) -> Item:
            -122        """Returns the next item in the iterator.
            -123
            -124        Example
            -125        -------
            -126        ```py
            -127        iterator = FlatIterator(["1", "2", "3"])
            -128        item = iterator.next()
            -129        assert item == "1"
            -130        item = iterator.next()
            -131        assert item == "2"
            -132        ```
            -133
            -134        Raises
            -135        ------
            -136        `StopIteration`
            -137            If no elements are left in the iterator.
            -138        """
            -139        try:
            -140            return self.__next__()
            -141        except StopIteration:
            -142            self._ok()
            -143
            -144    def map(
            -145        self, predicate: collections.Callable[[Item], OtherItem]
            -146    ) -> FlatIterator[OtherItem]:
            -147        """Maps each item in the iterator to its predicated value.
            -148
            -149        Example
            -150        -------
            -151        ```py
            -152        iterator = FlatIterator(["1", "2", "3"]).map(lambda value: int(value))
            -153        print(iterator)
            -154        # <FlatIterator([1, 2, 3])>
            -155        ```
            -156
            -157        Parameters
            -158        ----------
            -159        predicate: `collections.Callable[[Item], OtherItem]`
            -160            The function to map each item in the iterator to its predicated value.
            -161
            -162        Returns
            -163        -------
            -164        `FlatIterator[OtherItem]`
            -165            The mapped iterator.
            -166
            -167        Raises
            -168        ------
            -169        `StopIteration`
            -170            If no elements are left in the iterator.
            -171        """
            -172        return FlatIterator(map(predicate, self._items))
            -173
            -174    def take(self, n: int) -> FlatIterator[Item]:
            -175        """Take the first number of items until the number of items are yielded or
            -176        the end of the iterator is reached.
            -177
            -178        Example
            -179        -------
            -180        ```py
            -181        iterator = FlatIterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
            -182        print(iterator.take(2))
            -183        # <FlatIterator([GameMode.RAID, GameMode.STRIKE])>
            -184        ```
            -185
            -186        Parameters
            -187        ----------
            -188        n: `int`
            -189            The number of items to take.
            -190
            -191        Raises
            -192        ------
            -193        `StopIteration`
            -194            If no elements are left in the iterator.
            -195        """
            -196        return FlatIterator(itertools.islice(self._items, n))
            -197
            -198    def take_while(
            -199        self, predicate: collections.Callable[[Item], bool]
            -200    ) -> FlatIterator[Item]:
            -201        """Yields items from the iterator while predicate returns `True`.
            -202
            -203        Example
            -204        -------
            -205        ```py
            -206        iterator = FlatIterator([STEAM, XBOX, STADIA])
            -207        print(iterator.take_while(lambda platform: platform is not XBOX))
            -208        # <FlatIterator([STEAM])>
            -209        ```
            -210
            -211        Parameters
            -212        ----------
            -213        predicate: `collections.Callable[[Item], bool]`
            -214            The function to predicate each item in the iterator.
            -215
            -216        Raises
            -217        ------
            -218        `StopIteration`
            -219            If no elements are left in the iterator.
            -220        """
            -221        return FlatIterator(itertools.takewhile(predicate, self._items))
            -222
            -223    def drop_while(
            -224        self, predicate: collections.Callable[[Item], bool]
            -225    ) -> FlatIterator[Item]:
            -226        """Yields items from the iterator while predicate returns `False`.
            -227
            -228        Example
            -229        -------
            -230        ```py
            -231        iterator = FlatIterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
            -232        print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
            -233        # <FlatIterator([DestinyMembership(name="Bob")])>
            -234        ```
            -235
            -236        Parameters
            -237        ----------
            -238        predicate: `collections.Callable[[Item], bool]`
            -239            The function to predicate each item in the iterator.
            -240
            -241        Raises
            -242        ------
            -243        `StopIteration`
            -244            If no elements are left in the iterator.
            -245        """
            -246        return FlatIterator(itertools.dropwhile(predicate, self._items))
            -247
            -248    def filter(
            -249        self, predicate: collections.Callable[[Item], bool]
            -250    ) -> FlatIterator[Item]:
            -251        """Filters the iterator to only yield items that match the predicate.
            -252
            -253        Example
            -254        -------
            -255        ```py
            -256        names = FlatIterator(["Jim", "Bob", "Mike", "Jess"])
            -257        print(names.filter(lambda n: n != "Jim"))
            -258        # <FlatIterator(["Bob", "Mike", "Jess"])>
            -259        ```
            -260        """
            -261        return FlatIterator(filter(predicate, self._items))
            -262
            -263    def skip(self, n: int) -> FlatIterator[Item]:
            -264        """Skips the first number of items in the iterator.
            -265
            -266        Example
            -267        -------
            -268        ```py
            -269        iterator = FlatIterator([STEAM, XBOX, STADIA])
            -270        print(iterator.skip(1))
            -271        # <FlatIterator([XBOX, STADIA])>
            -272        ```
            -273        """
            -274        return FlatIterator(itertools.islice(self._items, n, None))
            -275
            -276    def discard(
            -277        self, predicate: collections.Callable[[Item], bool]
            -278    ) -> FlatIterator[Item]:
            -279        """Discards all elements in the iterator for which the predicate function returns true.
            -280
            -281        Example
            -282        -------
            -283        ```py
            -284        iterator = FlatIterator(['A', 'B', 'C'])
            -285        print(iterator.discard(lambda x: x == 'B'))
            -286        # <FlatIterator(['A', 'C'])>
            -287        ```
            -288
            -289        Parameters
            -290        ----------
            -291        predicate: `collections.Callable[[Item], bool]`
            -292            The function to test each item in the iterator.
            -293
            -294        Raises
            -295        ------
            -296        `StopIteration`
            -297            If no elements are left in the iterator.
            -298        """
            -299        return FlatIterator(filter(lambda x: not predicate(x), self._items))
            -300
            -301    def zip(
            -302        self, other: FlatIterator[OtherItem]
            -303    ) -> FlatIterator[tuple[Item, OtherItem]]:
            -304        """Zips the iterator with another iterable.
            -305
            -306        Example
            -307        -------
            -308        ```py
            -309        iterator = FlatIterator([1, 3, 5])
            -310        other = FlatIterator([2, 4, 6])
            -311        for item, other_item in iterator.zip(other):
            -312            print(item, other_item)
            -313        # <FlatIterator([(1, 2), (3, 4), (5, 6)])>
            -314        ```
            -315
            -316        Parameters
            -317        ----------
            -318        other: `FlatIterator[OtherItem]`
            -319            The iterable to zip with.
            -320
            -321        Raises
            -322        ------
            -323        `StopIteration`
            -324            If no elements are left in the iterator.
            -325        """
            -326        return FlatIterator(zip(self._items, other))
            -327
            -328    def all(self, predicate: collections.Callable[[Item], bool]) -> bool:
            -329        """`True` if all items in the iterator match the predicate.
            -330
            -331        Example
            -332        -------
            -333        ```py
            -334        iterator = FlatIterator([1, 2, 3])
            -335        while iterator.all(lambda item: isinstance(item, int)):
            -336            print("Still all integers")
            -337            continue
            -338        # Still all integers
            -339        ```
            -340
            -341        Parameters
            -342        ----------
            -343        predicate: `collections.Callable[[Item], bool]`
            -344            The function to test each item in the iterator.
            -345
            -346        Raises
            -347        ------
            -348        `StopIteration`
            -349            If no elements are left in the iterator.
            -350        """
            -351        return all(predicate(item) for item in self)
            -352
            -353    def any(self, predicate: collections.Callable[[Item], bool]) -> bool:
            -354        """`True` if any items in the iterator match the predicate.
            -355
            -356        Example
            -357        -------
            -358        ```py
            -359        iterator = FlatIterator([1, 2, 3])
            -360        if iterator.any(lambda item: isinstance(item, int)):
            -361            print("At least one item is an int.")
            -362        # At least one item is an int.
            -363        ```
            -364
            -365        Parameters
            -366        ----------
            -367        predicate: `collections.Callable[[Item], bool]`
            -368            The function to test each item in the iterator.
            -369
            -370        Raises
            -371        ------
            -372        `StopIteration`
            -373            If no elements are left in the iterator.
            -374        """
            -375        return any(predicate(item) for item in self)
            -376
            -377    def sort(
            -378        self,
            -379        *,
            -380        key: collections.Callable[[Item], typeshed.SupportsRichComparison],
            -381        reverse: bool = False,
            -382    ) -> FlatIterator[Item]:
            -383        """Sorts the iterator.
            -384
            -385        Example
            -386        -------
            -387        ```py
            -388        iterator = FlatIterator([3, 1, 6, 7])
            -389        print(iterator.sort(key=lambda item: item))
            -390        # <FlatIterator([1, 3, 6, 7])>
            -391        ```
            -392
            -393        Parameters
            -394        ----------
            -395        key: `collections.Callable[[Item], Any]`
            -396            The function to sort by.
            -397        reverse: `bool`
            -398            Whether to reverse the sort.
            -399
            -400        Raises
            -401        ------
            -402        `StopIteration`
            -403            If no elements are left in the iterator.
            -404        """
            -405        return FlatIterator(sorted(self._items, key=key, reverse=reverse))
            -406
            -407    def first(self) -> Item:
            -408        """Returns the first item in the iterator.
            -409
            -410        Example
            -411        -------
            -412        ```py
            -413        iterator = FlatIterator([3, 1, 6, 7])
            -414        print(iterator.first())
            -415        3
            -416        ```
            -417
            -418        Raises
            -419        ------
            -420        `StopIteration`
            -421            If no elements are left in the iterator.
            -422        """
            -423        return self.take(1).next()
            -424
            -425    def reversed(self) -> FlatIterator[Item]:
            -426        """Returns a new iterator that yields the items in the iterator in reverse order.
            -427
            -428        Example
            -429        -------
            -430        ```py
            -431        iterator = FlatIterator([3, 1, 6, 7])
            -432        print(iterator.reversed())
            -433        # <FlatIterator([7, 6, 1, 3])>
            -434        ```
            -435
            -436        Raises
            -437        ------
            -438        `StopIteration`
            -439            If no elements are left in the iterator.
            -440        """
            -441        return FlatIterator(reversed(self.collect()))
            -442
            -443    def count(self) -> int:
            -444        """Returns the number of items in the iterator.
            -445
            -446        Example
            -447        -------
            -448        ```py
            -449        iterator = FlatIterator([3, 1, 6, 7])
            -450        print(iterator.count())
            -451        4
            -452        ```
            -453        """
            -454        count = 0
            -455        for _ in self:
            -456            count += 1
            -457
            -458        return count
            -459
            -460    def union(self, other: FlatIterator[Item]) -> FlatIterator[Item]:
            -461        """Returns a new iterator that yields all items from both iterators.
            -462
            -463        Example
            -464        -------
            -465        ```py
            -466        iterator = FlatIterator([1, 2, 3])
            -467        other = FlatIterator([4, 5, 6])
            -468        print(iterator.union(other))
            -469        # <FlatIterator([1, 2, 3, 4, 5, 6])>
            -470        ```
            -471
            -472        Parameters
            -473        ----------
            -474        other: `FlatIterator[Item]`
            -475            The iterable to union with.
            -476
            -477        Raises
            -478        ------
            -479        `StopIteration`
            -480            If no elements are left in the iterator.
            -481        """
            -482        return FlatIterator(itertools.chain(self._items, other))
            -483
            -484    def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None:
            -485        """Calls the function on each item in the iterator.
            -486
            -487        Example
            -488        -------
            -489        ```py
            -490        iterator = FlatIterator([1, 2, 3])
            -491        iterator.for_each(lambda item: print(item))
            -492        # 1
            -493        # 2
            -494        # 3
            -495        ```
            -496
            -497        Parameters
            -498        ----------
            -499        func: `typeshed.Callable[[Item], None]`
            -500            The function to call on each item in the iterator.
            -501        """
            -502        for item in self:
            -503            func(item)
            -504
            -505    async def async_for_each(
            -506        self,
            -507        func: collections.Callable[[Item], collections.Coroutine[None, None, None]],
            -508    ) -> None:
            -509        """Calls the async function on each item in the iterator concurrently.
            -510
            -511        Example
            -512        -------
            -513        ```py
            -514        async def signup(username: str) -> None:
            -515            async with aiohttp.request('POST', '...') as r:
            -516                # Actual logic.
            -517                ...
            -518
            -519        async def main():
            -520            users = aiobungie.into_iter(["user_danny", "user_jojo"])
            -521            await users.async_for_each(lambda username: signup(username))
            -522        ```
            -523
            -524        Parameters
            -525        ----------
            -526        func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]`
            -527            The async function to call on each item in the iterator.
            -528        """
            -529        await _helpers.awaits(*(func(item) for item in self))
            -530
            -531    def enumerate(self, *, start: int = 0) -> FlatIterator[tuple[int, Item]]:
            -532        """Returns a new iterator that yields tuples of the index and item.
            -533
            -534        Example
            -535        -------
            -536        ```py
            -537        iterator = FlatIterator([1, 2, 3])
            -538        for index, item in iterator.enumerate():
            -539            print(index, item)
            -540        # 0 1
            -541        # 1 2
            -542        # 2 3
            -543        ```
            -544
            -545        Raises
            -546        ------
            -547        `StopIteration`
            -548            If no elements are left in the iterator.
            -549        """
            -550        return FlatIterator(enumerate(self._items, start=start))
            -551
            -552    def _ok(self) -> typing.NoReturn:
            -553        raise StopIteration("No more items in the iterator.") from None
            -554
            -555    def __getitem__(self, index: int) -> Item:
            -556        try:
            -557            return self.skip(index).first()
            -558        except IndexError:
            -559            self._ok()
            -560
            -561    def __or__(self, other: FlatIterator[Item]) -> FlatIterator[Item]:
            -562        return self.union(other)
            -563
            -564    # This is a never.
            -565    def __setitem__(self) -> typing.NoReturn:
            -566        raise TypeError(
            -567            f"{type(self).__name__} doesn't support item assignment."
            -568        ) from None
            -569
            -570    def __repr__(self) -> str:
            -571        return f'<{self.__class__.__name__}({", ".join([str(item) for item in self])})>'
            -572
            -573    def __len__(self) -> int:
            -574        return self.count()
            -575
            -576    def __iter__(self) -> FlatIterator[Item]:
            -577        return self
            -578
            -579    def __next__(self) -> Item:
            -580        try:
            -581            item = next(self._items)
            -582        except StopIteration:
            -583            self._ok()
            -584
            -585        return item
            +    
            +            
             45class Iterator(typing.Generic[Item]):
            + 46    """A Flat, In-Memory iterator for sequenced based data.
            + 47
            + 48    Example
            + 49    -------
            + 50    ```py
            + 51    iterator = Iterator([1, 2, 3])
            + 52
            + 53    # Map the results.
            + 54    for item in iterator.map(lambda item: item * 2):
            + 55        print(item)
            + 56    # 2
            + 57    # 4
            + 58
            + 59    # Indexing is also supported.
            + 60    print(iterator[0])
            + 61    # 1
            + 62
            + 63    # Normal iteration.
            + 64    for item in iterator:
            + 65        print(item)
            + 66    # 1
            + 67    # 2
            + 68    # 3
            + 69
            + 70    # Union two iterators.
            + 71    iterator2 = Iterator([4, 5, 6])
            + 72    final = iterator | iterator2
            + 73    # <Iterator([1, 2, 3, 4, 5, 6])>
            + 74    ```
            + 75
            + 76    Parameters
            + 77    ----------
            + 78    items: `collections.Iterable[Item]`
            + 79        The items to iterate over.
            + 80    """
            + 81
            + 82    __slots__ = ("_items",)
            + 83
            + 84    def __init__(self, items: collections.Iterable[Item]) -> None:
            + 85        self._items = iter(items)
            + 86
            + 87    @typing.overload
            + 88    def collect(self) -> list[Item]:
            + 89        ...
            + 90
            + 91    @typing.overload
            + 92    def collect(self, casting: _B) -> list[_B]:
            + 93        ...
            + 94
            + 95    def collect(
            + 96        self, casting: typing.Optional[_B] = None
            + 97    ) -> typing.Union[list[Item], list[_B]]:
            + 98        """Collects all items in the iterator into a list and cast them into an object if provided.
            + 99
            +100        Example
            +101        -------
            +102        >>> iterator = Iterator([1, 2, 3])
            +103        >>> iterator.collect(casting=str)
            +104        ["1", "2", "3"]
            +105
            +106        Parameters
            +107        ----------
            +108        casting: `T | None`
            +109            The type to cast the items to. If `None` is provided, the items will be returned as is.
            +110
            +111        Raises
            +112        ------
            +113        `StopIteration`
            +114            If no elements are left in the iterator.
            +115        """
            +116        if casting is not None:
            +117            return typing.cast(list[_B], list(map(casting, self._items)))
            +118
            +119        return list(self._items)
            +120
            +121    def next(self) -> Item:
            +122        """Returns the next item in the iterator.
            +123
            +124        Example
            +125        -------
            +126        ```py
            +127        iterator = Iterator(["1", "2", "3"])
            +128        item = iterator.next()
            +129        assert item == "1"
            +130        item = iterator.next()
            +131        assert item == "2"
            +132        ```
            +133
            +134        Raises
            +135        ------
            +136        `StopIteration`
            +137            If no elements are left in the iterator.
            +138        """
            +139        try:
            +140            return self.__next__()
            +141        except StopIteration:
            +142            self._ok()
            +143
            +144    def map(
            +145        self, predicate: collections.Callable[[Item], OtherItem]
            +146    ) -> Iterator[OtherItem]:
            +147        """Maps each item in the iterator to its predicated value.
            +148
            +149        Example
            +150        -------
            +151        ```py
            +152        iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value))
            +153        print(iterator)
            +154        # <Iterator([1, 2, 3])>
            +155        ```
            +156
            +157        Parameters
            +158        ----------
            +159        predicate: `collections.Callable[[Item], OtherItem]`
            +160            The function to map each item in the iterator to its predicated value.
            +161
            +162        Returns
            +163        -------
            +164        `Iterator[OtherItem]`
            +165            The mapped iterator.
            +166
            +167        Raises
            +168        ------
            +169        `StopIteration`
            +170            If no elements are left in the iterator.
            +171        """
            +172        return Iterator(map(predicate, self._items))
            +173
            +174    def take(self, n: int) -> Iterator[Item]:
            +175        """Take the first number of items until the number of items are yielded or
            +176        the end of the iterator is reached.
            +177
            +178        Example
            +179        -------
            +180        ```py
            +181        iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
            +182        print(iterator.take(2))
            +183        # <Iterator([GameMode.RAID, GameMode.STRIKE])>
            +184        ```
            +185
            +186        Parameters
            +187        ----------
            +188        n: `int`
            +189            The number of items to take.
            +190
            +191        Raises
            +192        ------
            +193        `StopIteration`
            +194            If no elements are left in the iterator.
            +195        """
            +196        return Iterator(itertools.islice(self._items, n))
            +197
            +198    def take_while(
            +199        self, predicate: collections.Callable[[Item], bool]
            +200    ) -> Iterator[Item]:
            +201        """Yields items from the iterator while predicate returns `True`.
            +202
            +203        Example
            +204        -------
            +205        ```py
            +206        iterator = Iterator([STEAM, XBOX, STADIA])
            +207        print(iterator.take_while(lambda platform: platform is not XBOX))
            +208        # <Iterator([STEAM])>
            +209        ```
            +210
            +211        Parameters
            +212        ----------
            +213        predicate: `collections.Callable[[Item], bool]`
            +214            The function to predicate each item in the iterator.
            +215
            +216        Raises
            +217        ------
            +218        `StopIteration`
            +219            If no elements are left in the iterator.
            +220        """
            +221        return Iterator(itertools.takewhile(predicate, self._items))
            +222
            +223    def drop_while(
            +224        self, predicate: collections.Callable[[Item], bool]
            +225    ) -> Iterator[Item]:
            +226        """Yields items from the iterator while predicate returns `False`.
            +227
            +228        Example
            +229        -------
            +230        ```py
            +231        iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
            +232        print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
            +233        # <Iterator([DestinyMembership(name="Bob")])>
            +234        ```
            +235
            +236        Parameters
            +237        ----------
            +238        predicate: `collections.Callable[[Item], bool]`
            +239            The function to predicate each item in the iterator.
            +240
            +241        Raises
            +242        ------
            +243        `StopIteration`
            +244            If no elements are left in the iterator.
            +245        """
            +246        return Iterator(itertools.dropwhile(predicate, self._items))
            +247
            +248    def filter(self, predicate: collections.Callable[[Item], bool]) -> Iterator[Item]:
            +249        """Filters the iterator to only yield items that match the predicate.
            +250
            +251        Example
            +252        -------
            +253        ```py
            +254        names = Iterator(["Jim", "Bob", "Mike", "Jess"])
            +255        print(names.filter(lambda n: n != "Jim"))
            +256        # <Iterator(["Bob", "Mike", "Jess"])>
            +257        ```
            +258        """
            +259        return Iterator(filter(predicate, self._items))
            +260
            +261    def skip(self, n: int) -> Iterator[Item]:
            +262        """Skips the first number of items in the iterator.
            +263
            +264        Example
            +265        -------
            +266        ```py
            +267        iterator = Iterator([STEAM, XBOX, STADIA])
            +268        print(iterator.skip(1))
            +269        # <Iterator([XBOX, STADIA])>
            +270        ```
            +271        """
            +272        return Iterator(itertools.islice(self._items, n, None))
            +273
            +274    def zip(self, other: Iterator[OtherItem]) -> Iterator[tuple[Item, OtherItem]]:
            +275        """Zips the iterator with another iterable.
            +276
            +277        Example
            +278        -------
            +279        ```py
            +280        iterator = Iterator([1, 3, 5])
            +281        other = Iterator([2, 4, 6])
            +282        for item, other_item in iterator.zip(other):
            +283            print(item, other_item)
            +284        # <Iterator([(1, 2), (3, 4), (5, 6)])>
            +285        ```
            +286
            +287        Parameters
            +288        ----------
            +289        other: `Iterator[OtherItem]`
            +290            The iterable to zip with.
            +291
            +292        Raises
            +293        ------
            +294        `StopIteration`
            +295            If no elements are left in the iterator.
            +296        """
            +297        return Iterator(zip(self._items, other))
            +298
            +299    def all(self, predicate: collections.Callable[[Item], bool]) -> bool:
            +300        """`True` if all items in the iterator match the predicate.
            +301
            +302        Example
            +303        -------
            +304        ```py
            +305        iterator = Iterator([1, 2, 3])
            +306        while iterator.all(lambda item: isinstance(item, int)):
            +307            print("Still all integers")
            +308            continue
            +309        # Still all integers
            +310        ```
            +311
            +312        Parameters
            +313        ----------
            +314        predicate: `collections.Callable[[Item], bool]`
            +315            The function to test each item in the iterator.
            +316
            +317        Raises
            +318        ------
            +319        `StopIteration`
            +320            If no elements are left in the iterator.
            +321        """
            +322        return all(predicate(item) for item in self)
            +323
            +324    def any(self, predicate: collections.Callable[[Item], bool]) -> bool:
            +325        """`True` if any items in the iterator match the predicate.
            +326
            +327        Example
            +328        -------
            +329        ```py
            +330        iterator = Iterator([1, 2, 3])
            +331        if iterator.any(lambda item: isinstance(item, int)):
            +332            print("At least one item is an int.")
            +333        # At least one item is an int.
            +334        ```
            +335
            +336        Parameters
            +337        ----------
            +338        predicate: `collections.Callable[[Item], bool]`
            +339            The function to test each item in the iterator.
            +340
            +341        Raises
            +342        ------
            +343        `StopIteration`
            +344            If no elements are left in the iterator.
            +345        """
            +346        return any(predicate(item) for item in self)
            +347
            +348    def sort(
            +349        self,
            +350        *,
            +351        key: collections.Callable[[Item], typeshed.SupportsRichComparison],
            +352        reverse: bool = False,
            +353    ) -> Iterator[Item]:
            +354        """Sorts the iterator.
            +355
            +356        Example
            +357        -------
            +358        ```py
            +359        iterator = Iterator([3, 1, 6, 7])
            +360        print(iterator.sort(key=lambda item: item))
            +361        # <Iterator([1, 3, 6, 7])>
            +362        ```
            +363
            +364        Parameters
            +365        ----------
            +366        key: `collections.Callable[[Item], Any]`
            +367            The function to sort by.
            +368        reverse: `bool`
            +369            Whether to reverse the sort.
            +370
            +371        Raises
            +372        ------
            +373        `StopIteration`
            +374            If no elements are left in the iterator.
            +375        """
            +376        return Iterator(sorted(self._items, key=key, reverse=reverse))
            +377
            +378    def first(self) -> Item:
            +379        """Returns the first item in the iterator.
            +380
            +381        Example
            +382        -------
            +383        ```py
            +384        iterator = Iterator([3, 1, 6, 7])
            +385        print(iterator.first())
            +386        3
            +387        ```
            +388
            +389        Raises
            +390        ------
            +391        `StopIteration`
            +392            If no elements are left in the iterator.
            +393        """
            +394        return self.take(1).next()
            +395
            +396    def reversed(self) -> Iterator[Item]:
            +397        """Returns a new iterator that yields the items in the iterator in reverse order.
            +398
            +399        Example
            +400        -------
            +401        ```py
            +402        iterator = Iterator([3, 1, 6, 7])
            +403        print(iterator.reversed())
            +404        # <Iterator([7, 6, 1, 3])>
            +405        ```
            +406
            +407        Raises
            +408        ------
            +409        `StopIteration`
            +410            If no elements are left in the iterator.
            +411        """
            +412        return Iterator(reversed(self.collect()))
            +413
            +414    def count(self) -> int:
            +415        """Returns the number of items in the iterator.
            +416
            +417        Example
            +418        -------
            +419        ```py
            +420        iterator = Iterator([3, 1, 6, 7])
            +421        print(iterator.count())
            +422        4
            +423        ```
            +424        """
            +425        count = 0
            +426        for _ in self:
            +427            count += 1
            +428
            +429        return count
            +430
            +431    def union(self, other: Iterator[Item]) -> Iterator[Item]:
            +432        """Returns a new iterator that yields all items from both iterators.
            +433
            +434        Example
            +435        -------
            +436        ```py
            +437        iterator = Iterator([1, 2, 3])
            +438        other = Iterator([4, 5, 6])
            +439        print(iterator.union(other))
            +440        # <Iterator([1, 2, 3, 4, 5, 6])>
            +441        ```
            +442
            +443        Parameters
            +444        ----------
            +445        other: `Iterator[Item]`
            +446            The iterable to union with.
            +447
            +448        Raises
            +449        ------
            +450        `StopIteration`
            +451            If no elements are left in the iterator.
            +452        """
            +453        return Iterator(itertools.chain(self._items, other))
            +454
            +455    def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None:
            +456        """Calls the function on each item in the iterator.
            +457
            +458        Example
            +459        -------
            +460        ```py
            +461        iterator = Iterator([1, 2, 3])
            +462        iterator.for_each(lambda item: print(item))
            +463        # 1
            +464        # 2
            +465        # 3
            +466        ```
            +467
            +468        Parameters
            +469        ----------
            +470        func: `typeshed.Callable[[Item], None]`
            +471            The function to call on each item in the iterator.
            +472        """
            +473        for item in self:
            +474            func(item)
            +475
            +476    async def async_for_each(
            +477        self,
            +478        func: collections.Callable[[Item], collections.Coroutine[None, None, None]],
            +479    ) -> None:
            +480        """Calls the async function on each item in the iterator concurrently.
            +481
            +482        Example
            +483        -------
            +484        ```py
            +485        async def signup(username: str) -> None:
            +486            async with aiohttp.request('POST', '...') as r:
            +487                # Actual logic.
            +488                ...
            +489
            +490        async def main():
            +491            users = aiobungie.into_iter(["user_danny", "user_jojo"])
            +492            await users.async_for_each(lambda username: signup(username))
            +493        ```
            +494
            +495        Parameters
            +496        ----------
            +497        func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]`
            +498            The async function to call on each item in the iterator.
            +499        """
            +500        await _helpers.awaits(*(func(item) for item in self))
            +501
            +502    def enumerate(self, *, start: int = 0) -> Iterator[tuple[int, Item]]:
            +503        """Returns a new iterator that yields tuples of the index and item.
            +504
            +505        Example
            +506        -------
            +507        ```py
            +508        iterator = Iterator([1, 2, 3])
            +509        for index, item in iterator.enumerate():
            +510            print(index, item)
            +511        # 0 1
            +512        # 1 2
            +513        # 2 3
            +514        ```
            +515
            +516        Raises
            +517        ------
            +518        `StopIteration`
            +519            If no elements are left in the iterator.
            +520        """
            +521        return Iterator(enumerate(self._items, start=start))
            +522
            +523    def _ok(self) -> typing.NoReturn:
            +524        raise StopIteration("No more items in the iterator.") from None
            +525
            +526    def __getitem__(self, index: int) -> Item:
            +527        try:
            +528            return self.skip(index).first()
            +529        except IndexError:
            +530            self._ok()
            +531
            +532    def __or__(self, other: Iterator[Item]) -> Iterator[Item]:
            +533        return self.union(other)
            +534
            +535    # This is a never.
            +536    def __setitem__(self) -> typing.NoReturn:
            +537        raise TypeError(
            +538            f"{type(self).__name__} doesn't support item assignment."
            +539        ) from None
            +540
            +541    def __repr__(self) -> str:
            +542        return f'<{self.__class__.__name__}({", ".join([str(item) for item in self])})>'
            +543
            +544    def __len__(self) -> int:
            +545        return self.count()
            +546
            +547    def __iter__(self) -> Iterator[Item]:
            +548        return self
            +549
            +550    def __next__(self) -> Item:
            +551        try:
            +552            item = next(self._items)
            +553        except StopIteration:
            +554            self._ok()
            +555
            +556        return item
             
            @@ -1301,7 +1240,8 @@

            Example
            -
            iterator = FlatIterator([1, 2, 3])
            +
            +
            iterator = Iterator([1, 2, 3])
             
             # Map the results.
             for item in iterator.map(lambda item: item * 2):
            @@ -1321,10 +1261,11 @@ 
            Example
            # 3 # Union two iterators. -iterator2 = FlatIterator([4, 5, 6]) +iterator2 = Iterator([4, 5, 6]) final = iterator | iterator2 -# <FlatIterator([1, 2, 3, 4, 5, 6])> -
            +# <Iterator([1, 2, 3, 4, 5, 6])> +
            +
            Parameters
            @@ -1335,60 +1276,60 @@
            Parameters
            -
            - +
            +
            - FlatIterator(items: collections.abc.Iterable[~Item]) + Iterator(items: collections.abc.Iterable[~Item]) - +
            - -
            84    def __init__(self, items: collections.Iterable[Item]) -> None:
            -85        self._items = iter(items)
            +    
            +            
            84    def __init__(self, items: collections.Iterable[Item]) -> None:
            +85        self._items = iter(items)
             
            -
            - +
            +
            def collect( self, casting: 'typing.Optional[_B]' = None) -> 'typing.Union[list[Item], list[_B]]': - +
            - -
             95    def collect(
            - 96        self, casting: typing.Optional[_B] = None
            - 97    ) -> typing.Union[list[Item], list[_B]]:
            - 98        """Collects all items in the iterator into a list and cast them into an object if provided.
            - 99
            -100        Example
            -101        -------
            -102        >>> iterator = FlatIterator([1, 2, 3])
            -103        >>> iterator.collect(casting=str)
            -104        ["1", "2", "3"]
            -105
            -106        Parameters
            -107        ----------
            -108        casting: `T | None`
            -109            The type to cast the items to. If `None` is provided, the items will be returned as is.
            -110
            -111        Raises
            -112        ------
            -113        `StopIteration`
            -114            If no elements are left in the iterator.
            -115        """
            -116        if casting is not None:
            -117            return typing.cast(list[_B], list(map(casting, self._items)))
            -118
            -119        return list(self._items)
            +    
            +            
             95    def collect(
            + 96        self, casting: typing.Optional[_B] = None
            + 97    ) -> typing.Union[list[Item], list[_B]]:
            + 98        """Collects all items in the iterator into a list and cast them into an object if provided.
            + 99
            +100        Example
            +101        -------
            +102        >>> iterator = Iterator([1, 2, 3])
            +103        >>> iterator.collect(casting=str)
            +104        ["1", "2", "3"]
            +105
            +106        Parameters
            +107        ----------
            +108        casting: `T | None`
            +109            The type to cast the items to. If `None` is provided, the items will be returned as is.
            +110
            +111        Raises
            +112        ------
            +113        `StopIteration`
            +114            If no elements are left in the iterator.
            +115        """
            +116        if casting is not None:
            +117            return typing.cast(list[_B], list(map(casting, self._items)))
            +118
            +119        return list(self._items)
             
            @@ -1396,10 +1337,12 @@
            Parameters
            Example
            -
            >>> iterator = FlatIterator([1, 2, 3])
            +
            +
            >>> iterator = Iterator([1, 2, 3])
             >>> iterator.collect(casting=str)
             ["1", "2", "3"]
            -
            +
            +
            Parameters
            @@ -1417,39 +1360,39 @@
            Raises
            -
            - +
            +
            def next(self) -> ~Item: - +
            - -
            121    def next(self) -> Item:
            -122        """Returns the next item in the iterator.
            -123
            -124        Example
            -125        -------
            -126        ```py
            -127        iterator = FlatIterator(["1", "2", "3"])
            -128        item = iterator.next()
            -129        assert item == "1"
            -130        item = iterator.next()
            -131        assert item == "2"
            -132        ```
            -133
            -134        Raises
            -135        ------
            -136        `StopIteration`
            -137            If no elements are left in the iterator.
            -138        """
            -139        try:
            -140            return self.__next__()
            -141        except StopIteration:
            -142            self._ok()
            +    
            +            
            121    def next(self) -> Item:
            +122        """Returns the next item in the iterator.
            +123
            +124        Example
            +125        -------
            +126        ```py
            +127        iterator = Iterator(["1", "2", "3"])
            +128        item = iterator.next()
            +129        assert item == "1"
            +130        item = iterator.next()
            +131        assert item == "2"
            +132        ```
            +133
            +134        Raises
            +135        ------
            +136        `StopIteration`
            +137            If no elements are left in the iterator.
            +138        """
            +139        try:
            +140            return self.__next__()
            +141        except StopIteration:
            +142            self._ok()
             
            @@ -1457,12 +1400,14 @@
            Raises
            Example
            -
            iterator = FlatIterator(["1", "2", "3"])
            +
            +
            iterator = Iterator(["1", "2", "3"])
             item = iterator.next()
             assert item == "1"
             item = iterator.next()
             assert item == "2"
            -
            +
            +
            Raises
            @@ -1473,46 +1418,46 @@
            Raises
            -
            - +
            +
            def - map( self, predicate: 'collections.Callable[[Item], OtherItem]') -> 'FlatIterator[OtherItem]': + map( self, predicate: 'collections.Callable[[Item], OtherItem]') -> 'Iterator[OtherItem]': - +
            - -
            144    def map(
            -145        self, predicate: collections.Callable[[Item], OtherItem]
            -146    ) -> FlatIterator[OtherItem]:
            -147        """Maps each item in the iterator to its predicated value.
            -148
            -149        Example
            -150        -------
            -151        ```py
            -152        iterator = FlatIterator(["1", "2", "3"]).map(lambda value: int(value))
            -153        print(iterator)
            -154        # <FlatIterator([1, 2, 3])>
            -155        ```
            -156
            -157        Parameters
            -158        ----------
            -159        predicate: `collections.Callable[[Item], OtherItem]`
            -160            The function to map each item in the iterator to its predicated value.
            -161
            -162        Returns
            -163        -------
            -164        `FlatIterator[OtherItem]`
            -165            The mapped iterator.
            -166
            -167        Raises
            -168        ------
            -169        `StopIteration`
            -170            If no elements are left in the iterator.
            -171        """
            -172        return FlatIterator(map(predicate, self._items))
            +    
            +            
            144    def map(
            +145        self, predicate: collections.Callable[[Item], OtherItem]
            +146    ) -> Iterator[OtherItem]:
            +147        """Maps each item in the iterator to its predicated value.
            +148
            +149        Example
            +150        -------
            +151        ```py
            +152        iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value))
            +153        print(iterator)
            +154        # <Iterator([1, 2, 3])>
            +155        ```
            +156
            +157        Parameters
            +158        ----------
            +159        predicate: `collections.Callable[[Item], OtherItem]`
            +160            The function to map each item in the iterator to its predicated value.
            +161
            +162        Returns
            +163        -------
            +164        `Iterator[OtherItem]`
            +165            The mapped iterator.
            +166
            +167        Raises
            +168        ------
            +169        `StopIteration`
            +170            If no elements are left in the iterator.
            +171        """
            +172        return Iterator(map(predicate, self._items))
             
            @@ -1520,10 +1465,12 @@
            Raises
            Example
            -
            iterator = FlatIterator(["1", "2", "3"]).map(lambda value: int(value))
            +
            +
            iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value))
             print(iterator)
            -# <FlatIterator([1, 2, 3])>
            -
            +# <Iterator([1, 2, 3])> +
            +
            Parameters
            @@ -1535,7 +1482,7 @@
            Parameters
            Returns
              -
            • FlatIterator[OtherItem]: The mapped iterator.
            • +
            • Iterator[OtherItem]: The mapped iterator.
            Raises
            @@ -1547,40 +1494,40 @@
            Raises
            -
            - +
            +
            def - take(self, n: int) -> aiobungie.internal.iterators.FlatIterator[~Item]: + take(self, n: int) -> aiobungie.internal.iterators.Iterator[~Item]: - +
            - -
            174    def take(self, n: int) -> FlatIterator[Item]:
            -175        """Take the first number of items until the number of items are yielded or
            -176        the end of the iterator is reached.
            -177
            -178        Example
            -179        -------
            -180        ```py
            -181        iterator = FlatIterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
            -182        print(iterator.take(2))
            -183        # <FlatIterator([GameMode.RAID, GameMode.STRIKE])>
            -184        ```
            -185
            -186        Parameters
            -187        ----------
            -188        n: `int`
            -189            The number of items to take.
            -190
            -191        Raises
            -192        ------
            -193        `StopIteration`
            -194            If no elements are left in the iterator.
            -195        """
            -196        return FlatIterator(itertools.islice(self._items, n))
            +    
            +            
            174    def take(self, n: int) -> Iterator[Item]:
            +175        """Take the first number of items until the number of items are yielded or
            +176        the end of the iterator is reached.
            +177
            +178        Example
            +179        -------
            +180        ```py
            +181        iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
            +182        print(iterator.take(2))
            +183        # <Iterator([GameMode.RAID, GameMode.STRIKE])>
            +184        ```
            +185
            +186        Parameters
            +187        ----------
            +188        n: `int`
            +189            The number of items to take.
            +190
            +191        Raises
            +192        ------
            +193        `StopIteration`
            +194            If no elements are left in the iterator.
            +195        """
            +196        return Iterator(itertools.islice(self._items, n))
             
            @@ -1589,10 +1536,12 @@
            Raises
            Example
            -
            iterator = FlatIterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
            +
            +
            iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
             print(iterator.take(2))
            -# <FlatIterator([GameMode.RAID, GameMode.STRIKE])>
            -
            +# <Iterator([GameMode.RAID, GameMode.STRIKE])> +
            +
            Parameters
            @@ -1610,41 +1559,41 @@
            Raises
            -
            - +
            +
            def - take_while( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.internal.iterators.FlatIterator[~Item]: + take_while( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.internal.iterators.Iterator[~Item]: - +
            - -
            198    def take_while(
            -199        self, predicate: collections.Callable[[Item], bool]
            -200    ) -> FlatIterator[Item]:
            -201        """Yields items from the iterator while predicate returns `True`.
            -202
            -203        Example
            -204        -------
            -205        ```py
            -206        iterator = FlatIterator([STEAM, XBOX, STADIA])
            -207        print(iterator.take_while(lambda platform: platform is not XBOX))
            -208        # <FlatIterator([STEAM])>
            -209        ```
            -210
            -211        Parameters
            -212        ----------
            -213        predicate: `collections.Callable[[Item], bool]`
            -214            The function to predicate each item in the iterator.
            -215
            -216        Raises
            -217        ------
            -218        `StopIteration`
            -219            If no elements are left in the iterator.
            -220        """
            -221        return FlatIterator(itertools.takewhile(predicate, self._items))
            +    
            +            
            198    def take_while(
            +199        self, predicate: collections.Callable[[Item], bool]
            +200    ) -> Iterator[Item]:
            +201        """Yields items from the iterator while predicate returns `True`.
            +202
            +203        Example
            +204        -------
            +205        ```py
            +206        iterator = Iterator([STEAM, XBOX, STADIA])
            +207        print(iterator.take_while(lambda platform: platform is not XBOX))
            +208        # <Iterator([STEAM])>
            +209        ```
            +210
            +211        Parameters
            +212        ----------
            +213        predicate: `collections.Callable[[Item], bool]`
            +214            The function to predicate each item in the iterator.
            +215
            +216        Raises
            +217        ------
            +218        `StopIteration`
            +219            If no elements are left in the iterator.
            +220        """
            +221        return Iterator(itertools.takewhile(predicate, self._items))
             
            @@ -1652,10 +1601,12 @@
            Raises
            Example
            -
            iterator = FlatIterator([STEAM, XBOX, STADIA])
            +
            +
            iterator = Iterator([STEAM, XBOX, STADIA])
             print(iterator.take_while(lambda platform: platform is not XBOX))
            -# <FlatIterator([STEAM])>
            -
            +# <Iterator([STEAM])> +
            +
            Parameters
            @@ -1673,41 +1624,41 @@
            Raises
            -
            - +
            +
            def - drop_while( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.internal.iterators.FlatIterator[~Item]: + drop_while( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.internal.iterators.Iterator[~Item]: - +
            - -
            223    def drop_while(
            -224        self, predicate: collections.Callable[[Item], bool]
            -225    ) -> FlatIterator[Item]:
            -226        """Yields items from the iterator while predicate returns `False`.
            -227
            -228        Example
            -229        -------
            -230        ```py
            -231        iterator = FlatIterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
            -232        print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
            -233        # <FlatIterator([DestinyMembership(name="Bob")])>
            -234        ```
            -235
            -236        Parameters
            -237        ----------
            -238        predicate: `collections.Callable[[Item], bool]`
            -239            The function to predicate each item in the iterator.
            -240
            -241        Raises
            -242        ------
            -243        `StopIteration`
            -244            If no elements are left in the iterator.
            -245        """
            -246        return FlatIterator(itertools.dropwhile(predicate, self._items))
            +    
            +            
            223    def drop_while(
            +224        self, predicate: collections.Callable[[Item], bool]
            +225    ) -> Iterator[Item]:
            +226        """Yields items from the iterator while predicate returns `False`.
            +227
            +228        Example
            +229        -------
            +230        ```py
            +231        iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
            +232        print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
            +233        # <Iterator([DestinyMembership(name="Bob")])>
            +234        ```
            +235
            +236        Parameters
            +237        ----------
            +238        predicate: `collections.Callable[[Item], bool]`
            +239            The function to predicate each item in the iterator.
            +240
            +241        Raises
            +242        ------
            +243        `StopIteration`
            +244            If no elements are left in the iterator.
            +245        """
            +246        return Iterator(itertools.dropwhile(predicate, self._items))
             
            @@ -1715,10 +1666,12 @@
            Raises
            Example
            -
            iterator = FlatIterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
            +
            +
            iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
             print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
            -# <FlatIterator([DestinyMembership(name="Bob")])>
            -
            +# <Iterator([DestinyMembership(name="Bob")])> +
            +
            Parameters
            @@ -1736,31 +1689,29 @@
            Raises
            -
            - +
            +
            def - filter( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.internal.iterators.FlatIterator[~Item]: + filter( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.internal.iterators.Iterator[~Item]: - +
            - -
            248    def filter(
            -249        self, predicate: collections.Callable[[Item], bool]
            -250    ) -> FlatIterator[Item]:
            -251        """Filters the iterator to only yield items that match the predicate.
            -252
            -253        Example
            -254        -------
            -255        ```py
            -256        names = FlatIterator(["Jim", "Bob", "Mike", "Jess"])
            -257        print(names.filter(lambda n: n != "Jim"))
            -258        # <FlatIterator(["Bob", "Mike", "Jess"])>
            -259        ```
            -260        """
            -261        return FlatIterator(filter(predicate, self._items))
            +    
            +            
            248    def filter(self, predicate: collections.Callable[[Item], bool]) -> Iterator[Item]:
            +249        """Filters the iterator to only yield items that match the predicate.
            +250
            +251        Example
            +252        -------
            +253        ```py
            +254        names = Iterator(["Jim", "Bob", "Mike", "Jess"])
            +255        print(names.filter(lambda n: n != "Jim"))
            +256        # <Iterator(["Bob", "Mike", "Jess"])>
            +257        ```
            +258        """
            +259        return Iterator(filter(predicate, self._items))
             
            @@ -1768,37 +1719,39 @@
            Raises
            Example
            -
            names = FlatIterator(["Jim", "Bob", "Mike", "Jess"])
            +
            +
            names = Iterator(["Jim", "Bob", "Mike", "Jess"])
             print(names.filter(lambda n: n != "Jim"))
            -# <FlatIterator(["Bob", "Mike", "Jess"])>
            -
            +# <Iterator(["Bob", "Mike", "Jess"])> +
            +
            -
            - +
            +
            def - skip(self, n: int) -> aiobungie.internal.iterators.FlatIterator[~Item]: + skip(self, n: int) -> aiobungie.internal.iterators.Iterator[~Item]: - +
            - -
            263    def skip(self, n: int) -> FlatIterator[Item]:
            -264        """Skips the first number of items in the iterator.
            -265
            -266        Example
            -267        -------
            -268        ```py
            -269        iterator = FlatIterator([STEAM, XBOX, STADIA])
            -270        print(iterator.skip(1))
            -271        # <FlatIterator([XBOX, STADIA])>
            -272        ```
            -273        """
            -274        return FlatIterator(itertools.islice(self._items, n, None))
            +    
            +            
            261    def skip(self, n: int) -> Iterator[Item]:
            +262        """Skips the first number of items in the iterator.
            +263
            +264        Example
            +265        -------
            +266        ```py
            +267        iterator = Iterator([STEAM, XBOX, STADIA])
            +268        print(iterator.skip(1))
            +269        # <Iterator([XBOX, STADIA])>
            +270        ```
            +271        """
            +272        return Iterator(itertools.islice(self._items, n, None))
             
            @@ -1806,114 +1759,51 @@
            Example
            Example
            -
            iterator = FlatIterator([STEAM, XBOX, STADIA])
            +
            +
            iterator = Iterator([STEAM, XBOX, STADIA])
             print(iterator.skip(1))
            -# <FlatIterator([XBOX, STADIA])>
            -
            +# <Iterator([XBOX, STADIA])> +
            - - -
            -
            - -
            - - def - discard( self, predicate: collections.abc.Callable[[~Item], bool]) -> aiobungie.internal.iterators.FlatIterator[~Item]: - - - -
            - -
            276    def discard(
            -277        self, predicate: collections.Callable[[Item], bool]
            -278    ) -> FlatIterator[Item]:
            -279        """Discards all elements in the iterator for which the predicate function returns true.
            -280
            -281        Example
            -282        -------
            -283        ```py
            -284        iterator = FlatIterator(['A', 'B', 'C'])
            -285        print(iterator.discard(lambda x: x == 'B'))
            -286        # <FlatIterator(['A', 'C'])>
            -287        ```
            -288
            -289        Parameters
            -290        ----------
            -291        predicate: `collections.Callable[[Item], bool]`
            -292            The function to test each item in the iterator.
            -293
            -294        Raises
            -295        ------
            -296        `StopIteration`
            -297            If no elements are left in the iterator.
            -298        """
            -299        return FlatIterator(filter(lambda x: not predicate(x), self._items))
            -
            - - -

            Discards all elements in the iterator for which the predicate function returns true.

            - -
            Example
            - -
            iterator = FlatIterator(['A', 'B', 'C'])
            -print(iterator.discard(lambda x: x == 'B'))
            -# <FlatIterator(['A', 'C'])>
            -
            - -
            Parameters
            - -
              -
            • predicate (collections.Callable[[Item], bool]): -The function to test each item in the iterator.
            • -
            - -
            Raises
            - -
              -
            • StopIteration: If no elements are left in the iterator.
            • -
            -
            - +
            +
            def - zip( self, other: 'FlatIterator[OtherItem]') -> 'FlatIterator[tuple[Item, OtherItem]]': + zip(self, other: 'Iterator[OtherItem]') -> 'Iterator[tuple[Item, OtherItem]]': - +
            - -
            301    def zip(
            -302        self, other: FlatIterator[OtherItem]
            -303    ) -> FlatIterator[tuple[Item, OtherItem]]:
            -304        """Zips the iterator with another iterable.
            -305
            -306        Example
            -307        -------
            -308        ```py
            -309        iterator = FlatIterator([1, 3, 5])
            -310        other = FlatIterator([2, 4, 6])
            -311        for item, other_item in iterator.zip(other):
            -312            print(item, other_item)
            -313        # <FlatIterator([(1, 2), (3, 4), (5, 6)])>
            -314        ```
            -315
            -316        Parameters
            -317        ----------
            -318        other: `FlatIterator[OtherItem]`
            -319            The iterable to zip with.
            -320
            -321        Raises
            -322        ------
            -323        `StopIteration`
            -324            If no elements are left in the iterator.
            -325        """
            -326        return FlatIterator(zip(self._items, other))
            +    
            +            
            274    def zip(self, other: Iterator[OtherItem]) -> Iterator[tuple[Item, OtherItem]]:
            +275        """Zips the iterator with another iterable.
            +276
            +277        Example
            +278        -------
            +279        ```py
            +280        iterator = Iterator([1, 3, 5])
            +281        other = Iterator([2, 4, 6])
            +282        for item, other_item in iterator.zip(other):
            +283            print(item, other_item)
            +284        # <Iterator([(1, 2), (3, 4), (5, 6)])>
            +285        ```
            +286
            +287        Parameters
            +288        ----------
            +289        other: `Iterator[OtherItem]`
            +290            The iterable to zip with.
            +291
            +292        Raises
            +293        ------
            +294        `StopIteration`
            +295            If no elements are left in the iterator.
            +296        """
            +297        return Iterator(zip(self._items, other))
             
            @@ -1921,17 +1811,19 @@
            Raises
            Example
            -
            iterator = FlatIterator([1, 3, 5])
            -other = FlatIterator([2, 4, 6])
            +
            +
            iterator = Iterator([1, 3, 5])
            +other = Iterator([2, 4, 6])
             for item, other_item in iterator.zip(other):
                 print(item, other_item)
            -# <FlatIterator([(1, 2), (3, 4), (5, 6)])>
            -
            +# <Iterator([(1, 2), (3, 4), (5, 6)])> +
            +
            Parameters
              -
            • other (FlatIterator[OtherItem]): +
            • other (Iterator[OtherItem]): The iterable to zip with.
            @@ -1944,41 +1836,41 @@
            Raises
            -
            - +
            +
            def all(self, predicate: collections.abc.Callable[[~Item], bool]) -> bool: - +
            - -
            328    def all(self, predicate: collections.Callable[[Item], bool]) -> bool:
            -329        """`True` if all items in the iterator match the predicate.
            -330
            -331        Example
            -332        -------
            -333        ```py
            -334        iterator = FlatIterator([1, 2, 3])
            -335        while iterator.all(lambda item: isinstance(item, int)):
            -336            print("Still all integers")
            -337            continue
            -338        # Still all integers
            -339        ```
            -340
            -341        Parameters
            -342        ----------
            -343        predicate: `collections.Callable[[Item], bool]`
            -344            The function to test each item in the iterator.
            -345
            -346        Raises
            -347        ------
            -348        `StopIteration`
            -349            If no elements are left in the iterator.
            -350        """
            -351        return all(predicate(item) for item in self)
            +    
            +            
            299    def all(self, predicate: collections.Callable[[Item], bool]) -> bool:
            +300        """`True` if all items in the iterator match the predicate.
            +301
            +302        Example
            +303        -------
            +304        ```py
            +305        iterator = Iterator([1, 2, 3])
            +306        while iterator.all(lambda item: isinstance(item, int)):
            +307            print("Still all integers")
            +308            continue
            +309        # Still all integers
            +310        ```
            +311
            +312        Parameters
            +313        ----------
            +314        predicate: `collections.Callable[[Item], bool]`
            +315            The function to test each item in the iterator.
            +316
            +317        Raises
            +318        ------
            +319        `StopIteration`
            +320            If no elements are left in the iterator.
            +321        """
            +322        return all(predicate(item) for item in self)
             
            @@ -1986,12 +1878,14 @@
            Raises
            Example
            -
            iterator = FlatIterator([1, 2, 3])
            +
            +
            iterator = Iterator([1, 2, 3])
             while iterator.all(lambda item: isinstance(item, int)):
                 print("Still all integers")
                 continue
             # Still all integers
            -
            +
            +
            Parameters
            @@ -2009,40 +1903,40 @@
            Raises
            -
            - +
            +
            def any(self, predicate: collections.abc.Callable[[~Item], bool]) -> bool: - +
            - -
            353    def any(self, predicate: collections.Callable[[Item], bool]) -> bool:
            -354        """`True` if any items in the iterator match the predicate.
            -355
            -356        Example
            -357        -------
            -358        ```py
            -359        iterator = FlatIterator([1, 2, 3])
            -360        if iterator.any(lambda item: isinstance(item, int)):
            -361            print("At least one item is an int.")
            -362        # At least one item is an int.
            -363        ```
            -364
            -365        Parameters
            -366        ----------
            -367        predicate: `collections.Callable[[Item], bool]`
            -368            The function to test each item in the iterator.
            -369
            -370        Raises
            -371        ------
            -372        `StopIteration`
            -373            If no elements are left in the iterator.
            -374        """
            -375        return any(predicate(item) for item in self)
            +    
            +            
            324    def any(self, predicate: collections.Callable[[Item], bool]) -> bool:
            +325        """`True` if any items in the iterator match the predicate.
            +326
            +327        Example
            +328        -------
            +329        ```py
            +330        iterator = Iterator([1, 2, 3])
            +331        if iterator.any(lambda item: isinstance(item, int)):
            +332            print("At least one item is an int.")
            +333        # At least one item is an int.
            +334        ```
            +335
            +336        Parameters
            +337        ----------
            +338        predicate: `collections.Callable[[Item], bool]`
            +339            The function to test each item in the iterator.
            +340
            +341        Raises
            +342        ------
            +343        `StopIteration`
            +344            If no elements are left in the iterator.
            +345        """
            +346        return any(predicate(item) for item in self)
             
            @@ -2050,11 +1944,13 @@
            Raises
            Example
            -
            iterator = FlatIterator([1, 2, 3])
            +
            +
            iterator = Iterator([1, 2, 3])
             if iterator.any(lambda item: isinstance(item, int)):
                 print("At least one item is an int.")
             # At least one item is an int.
            -
            +
            +
            Parameters
            @@ -2072,46 +1968,46 @@
            Raises
            -
            - +
            +
            def - sort( self, *, key: 'collections.Callable[[Item], typeshed.SupportsRichComparison]', reverse: bool = False) -> aiobungie.internal.iterators.FlatIterator[~Item]: + sort( self, *, key: 'collections.Callable[[Item], typeshed.SupportsRichComparison]', reverse: bool = False) -> aiobungie.internal.iterators.Iterator[~Item]: - +
            - -
            377    def sort(
            -378        self,
            -379        *,
            -380        key: collections.Callable[[Item], typeshed.SupportsRichComparison],
            -381        reverse: bool = False,
            -382    ) -> FlatIterator[Item]:
            -383        """Sorts the iterator.
            -384
            -385        Example
            -386        -------
            -387        ```py
            -388        iterator = FlatIterator([3, 1, 6, 7])
            -389        print(iterator.sort(key=lambda item: item))
            -390        # <FlatIterator([1, 3, 6, 7])>
            -391        ```
            -392
            -393        Parameters
            -394        ----------
            -395        key: `collections.Callable[[Item], Any]`
            -396            The function to sort by.
            -397        reverse: `bool`
            -398            Whether to reverse the sort.
            -399
            -400        Raises
            -401        ------
            -402        `StopIteration`
            -403            If no elements are left in the iterator.
            -404        """
            -405        return FlatIterator(sorted(self._items, key=key, reverse=reverse))
            +    
            +            
            348    def sort(
            +349        self,
            +350        *,
            +351        key: collections.Callable[[Item], typeshed.SupportsRichComparison],
            +352        reverse: bool = False,
            +353    ) -> Iterator[Item]:
            +354        """Sorts the iterator.
            +355
            +356        Example
            +357        -------
            +358        ```py
            +359        iterator = Iterator([3, 1, 6, 7])
            +360        print(iterator.sort(key=lambda item: item))
            +361        # <Iterator([1, 3, 6, 7])>
            +362        ```
            +363
            +364        Parameters
            +365        ----------
            +366        key: `collections.Callable[[Item], Any]`
            +367            The function to sort by.
            +368        reverse: `bool`
            +369            Whether to reverse the sort.
            +370
            +371        Raises
            +372        ------
            +373        `StopIteration`
            +374            If no elements are left in the iterator.
            +375        """
            +376        return Iterator(sorted(self._items, key=key, reverse=reverse))
             
            @@ -2119,10 +2015,12 @@
            Raises
            Example
            -
            iterator = FlatIterator([3, 1, 6, 7])
            +
            +
            iterator = Iterator([3, 1, 6, 7])
             print(iterator.sort(key=lambda item: item))
            -# <FlatIterator([1, 3, 6, 7])>
            -
            +# <Iterator([1, 3, 6, 7])> +
            +
            Parameters
            @@ -2142,34 +2040,34 @@
            Raises
            -
            - +
            +
            def first(self) -> ~Item: - +
            - -
            407    def first(self) -> Item:
            -408        """Returns the first item in the iterator.
            -409
            -410        Example
            -411        -------
            -412        ```py
            -413        iterator = FlatIterator([3, 1, 6, 7])
            -414        print(iterator.first())
            -415        3
            -416        ```
            -417
            -418        Raises
            -419        ------
            -420        `StopIteration`
            -421            If no elements are left in the iterator.
            -422        """
            -423        return self.take(1).next()
            +    
            +            
            378    def first(self) -> Item:
            +379        """Returns the first item in the iterator.
            +380
            +381        Example
            +382        -------
            +383        ```py
            +384        iterator = Iterator([3, 1, 6, 7])
            +385        print(iterator.first())
            +386        3
            +387        ```
            +388
            +389        Raises
            +390        ------
            +391        `StopIteration`
            +392            If no elements are left in the iterator.
            +393        """
            +394        return self.take(1).next()
             
            @@ -2177,10 +2075,12 @@
            Raises
            Example
            -
            iterator = FlatIterator([3, 1, 6, 7])
            +
            +
            iterator = Iterator([3, 1, 6, 7])
             print(iterator.first())
             3
            -
            +
            +
            Raises
            @@ -2191,34 +2091,34 @@
            Raises
            -
            - +
            +
            def - reversed(self) -> aiobungie.internal.iterators.FlatIterator[~Item]: + reversed(self) -> aiobungie.internal.iterators.Iterator[~Item]: - +
            - -
            425    def reversed(self) -> FlatIterator[Item]:
            -426        """Returns a new iterator that yields the items in the iterator in reverse order.
            -427
            -428        Example
            -429        -------
            -430        ```py
            -431        iterator = FlatIterator([3, 1, 6, 7])
            -432        print(iterator.reversed())
            -433        # <FlatIterator([7, 6, 1, 3])>
            -434        ```
            -435
            -436        Raises
            -437        ------
            -438        `StopIteration`
            -439            If no elements are left in the iterator.
            -440        """
            -441        return FlatIterator(reversed(self.collect()))
            +    
            +            
            396    def reversed(self) -> Iterator[Item]:
            +397        """Returns a new iterator that yields the items in the iterator in reverse order.
            +398
            +399        Example
            +400        -------
            +401        ```py
            +402        iterator = Iterator([3, 1, 6, 7])
            +403        print(iterator.reversed())
            +404        # <Iterator([7, 6, 1, 3])>
            +405        ```
            +406
            +407        Raises
            +408        ------
            +409        `StopIteration`
            +410            If no elements are left in the iterator.
            +411        """
            +412        return Iterator(reversed(self.collect()))
             
            @@ -2226,10 +2126,12 @@
            Raises
            Example
            -
            iterator = FlatIterator([3, 1, 6, 7])
            +
            +
            iterator = Iterator([3, 1, 6, 7])
             print(iterator.reversed())
            -# <FlatIterator([7, 6, 1, 3])>
            -
            +# <Iterator([7, 6, 1, 3])> +
            +
            Raises
            @@ -2240,33 +2142,33 @@
            Raises
            -
            - +
            +
            def count(self) -> int: - +
            - -
            443    def count(self) -> int:
            -444        """Returns the number of items in the iterator.
            -445
            -446        Example
            -447        -------
            -448        ```py
            -449        iterator = FlatIterator([3, 1, 6, 7])
            -450        print(iterator.count())
            -451        4
            -452        ```
            -453        """
            -454        count = 0
            -455        for _ in self:
            -456            count += 1
            -457
            -458        return count
            +    
            +            
            414    def count(self) -> int:
            +415        """Returns the number of items in the iterator.
            +416
            +417        Example
            +418        -------
            +419        ```py
            +420        iterator = Iterator([3, 1, 6, 7])
            +421        print(iterator.count())
            +422        4
            +423        ```
            +424        """
            +425        count = 0
            +426        for _ in self:
            +427            count += 1
            +428
            +429        return count
             
            @@ -2274,48 +2176,50 @@
            Raises
            Example
            -
            iterator = FlatIterator([3, 1, 6, 7])
            +
            +
            iterator = Iterator([3, 1, 6, 7])
             print(iterator.count())
             4
            -
            +
            +
            -
            - +
            +
            def - union( self, other: aiobungie.internal.iterators.FlatIterator[~Item]) -> aiobungie.internal.iterators.FlatIterator[~Item]: + union( self, other: aiobungie.internal.iterators.Iterator[~Item]) -> aiobungie.internal.iterators.Iterator[~Item]: - +
            - -
            460    def union(self, other: FlatIterator[Item]) -> FlatIterator[Item]:
            -461        """Returns a new iterator that yields all items from both iterators.
            -462
            -463        Example
            -464        -------
            -465        ```py
            -466        iterator = FlatIterator([1, 2, 3])
            -467        other = FlatIterator([4, 5, 6])
            -468        print(iterator.union(other))
            -469        # <FlatIterator([1, 2, 3, 4, 5, 6])>
            -470        ```
            -471
            -472        Parameters
            -473        ----------
            -474        other: `FlatIterator[Item]`
            -475            The iterable to union with.
            -476
            -477        Raises
            -478        ------
            -479        `StopIteration`
            -480            If no elements are left in the iterator.
            -481        """
            -482        return FlatIterator(itertools.chain(self._items, other))
            +    
            +            
            431    def union(self, other: Iterator[Item]) -> Iterator[Item]:
            +432        """Returns a new iterator that yields all items from both iterators.
            +433
            +434        Example
            +435        -------
            +436        ```py
            +437        iterator = Iterator([1, 2, 3])
            +438        other = Iterator([4, 5, 6])
            +439        print(iterator.union(other))
            +440        # <Iterator([1, 2, 3, 4, 5, 6])>
            +441        ```
            +442
            +443        Parameters
            +444        ----------
            +445        other: `Iterator[Item]`
            +446            The iterable to union with.
            +447
            +448        Raises
            +449        ------
            +450        `StopIteration`
            +451            If no elements are left in the iterator.
            +452        """
            +453        return Iterator(itertools.chain(self._items, other))
             
            @@ -2323,16 +2227,18 @@
            Example
            Example
            -
            iterator = FlatIterator([1, 2, 3])
            -other = FlatIterator([4, 5, 6])
            +
            +
            iterator = Iterator([1, 2, 3])
            +other = Iterator([4, 5, 6])
             print(iterator.union(other))
            -# <FlatIterator([1, 2, 3, 4, 5, 6])>
            -
            +# <Iterator([1, 2, 3, 4, 5, 6])> +
            +
            Parameters
              -
            • other (FlatIterator[Item]): +
            • other (Iterator[Item]): The iterable to union with.
            @@ -2345,37 +2251,37 @@
            Raises
            -
            - +
            +
            def for_each(self, func: collections.abc.Callable[[~Item], typing.Any]) -> None: - +
            - -
            484    def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None:
            -485        """Calls the function on each item in the iterator.
            -486
            -487        Example
            -488        -------
            -489        ```py
            -490        iterator = FlatIterator([1, 2, 3])
            -491        iterator.for_each(lambda item: print(item))
            -492        # 1
            -493        # 2
            -494        # 3
            -495        ```
            -496
            -497        Parameters
            -498        ----------
            -499        func: `typeshed.Callable[[Item], None]`
            -500            The function to call on each item in the iterator.
            -501        """
            -502        for item in self:
            -503            func(item)
            +    
            +            
            455    def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None:
            +456        """Calls the function on each item in the iterator.
            +457
            +458        Example
            +459        -------
            +460        ```py
            +461        iterator = Iterator([1, 2, 3])
            +462        iterator.for_each(lambda item: print(item))
            +463        # 1
            +464        # 2
            +465        # 3
            +466        ```
            +467
            +468        Parameters
            +469        ----------
            +470        func: `typeshed.Callable[[Item], None]`
            +471            The function to call on each item in the iterator.
            +472        """
            +473        for item in self:
            +474            func(item)
             
            @@ -2383,12 +2289,14 @@
            Raises
            Example
            -
            iterator = FlatIterator([1, 2, 3])
            +
            +
            iterator = Iterator([1, 2, 3])
             iterator.for_each(lambda item: print(item))
             # 1
             # 2
             # 3
            -
            +
            +
            Parameters
            @@ -2400,42 +2308,42 @@
            Parameters
            -
            - +
            +
            async def async_for_each( self, func: collections.abc.Callable[[~Item], collections.abc.Coroutine[None, None, None]]) -> None: - +
            - -
            505    async def async_for_each(
            -506        self,
            -507        func: collections.Callable[[Item], collections.Coroutine[None, None, None]],
            -508    ) -> None:
            -509        """Calls the async function on each item in the iterator concurrently.
            -510
            -511        Example
            -512        -------
            -513        ```py
            -514        async def signup(username: str) -> None:
            -515            async with aiohttp.request('POST', '...') as r:
            -516                # Actual logic.
            -517                ...
            -518
            -519        async def main():
            -520            users = aiobungie.into_iter(["user_danny", "user_jojo"])
            -521            await users.async_for_each(lambda username: signup(username))
            -522        ```
            -523
            -524        Parameters
            -525        ----------
            -526        func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]`
            -527            The async function to call on each item in the iterator.
            -528        """
            -529        await _helpers.awaits(*(func(item) for item in self))
            +    
            +            
            476    async def async_for_each(
            +477        self,
            +478        func: collections.Callable[[Item], collections.Coroutine[None, None, None]],
            +479    ) -> None:
            +480        """Calls the async function on each item in the iterator concurrently.
            +481
            +482        Example
            +483        -------
            +484        ```py
            +485        async def signup(username: str) -> None:
            +486            async with aiohttp.request('POST', '...') as r:
            +487                # Actual logic.
            +488                ...
            +489
            +490        async def main():
            +491            users = aiobungie.into_iter(["user_danny", "user_jojo"])
            +492            await users.async_for_each(lambda username: signup(username))
            +493        ```
            +494
            +495        Parameters
            +496        ----------
            +497        func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]`
            +498            The async function to call on each item in the iterator.
            +499        """
            +500        await _helpers.awaits(*(func(item) for item in self))
             
            @@ -2443,7 +2351,8 @@
            Parameters
            Example
            -
            async def signup(username: str) -> None:
            +
            +
            async def signup(username: str) -> None:
                 async with aiohttp.request('POST', '...') as r:
                     # Actual logic.
                     ...
            @@ -2451,7 +2360,8 @@ 
            Example
            async def main(): users = aiobungie.into_iter(["user_danny", "user_jojo"]) await users.async_for_each(lambda username: signup(username)) -
            +
            +
            Parameters
            @@ -2463,37 +2373,37 @@
            Parameters
            -
            - +
            +
            def - enumerate( self, *, start: int = 0) -> aiobungie.internal.iterators.FlatIterator[tuple[int, ~Item]]: + enumerate( self, *, start: int = 0) -> aiobungie.internal.iterators.Iterator[tuple[int, ~Item]]: - +
            - -
            531    def enumerate(self, *, start: int = 0) -> FlatIterator[tuple[int, Item]]:
            -532        """Returns a new iterator that yields tuples of the index and item.
            -533
            -534        Example
            -535        -------
            -536        ```py
            -537        iterator = FlatIterator([1, 2, 3])
            -538        for index, item in iterator.enumerate():
            -539            print(index, item)
            -540        # 0 1
            -541        # 1 2
            -542        # 2 3
            -543        ```
            -544
            -545        Raises
            -546        ------
            -547        `StopIteration`
            -548            If no elements are left in the iterator.
            -549        """
            -550        return FlatIterator(enumerate(self._items, start=start))
            +    
            +            
            502    def enumerate(self, *, start: int = 0) -> Iterator[tuple[int, Item]]:
            +503        """Returns a new iterator that yields tuples of the index and item.
            +504
            +505        Example
            +506        -------
            +507        ```py
            +508        iterator = Iterator([1, 2, 3])
            +509        for index, item in iterator.enumerate():
            +510            print(index, item)
            +511        # 0 1
            +512        # 1 2
            +513        # 2 3
            +514        ```
            +515
            +516        Raises
            +517        ------
            +518        `StopIteration`
            +519            If no elements are left in the iterator.
            +520        """
            +521        return Iterator(enumerate(self._items, start=start))
             
            @@ -2501,13 +2411,15 @@
            Parameters
            Example
            -
            iterator = FlatIterator([1, 2, 3])
            +
            +
            iterator = Iterator([1, 2, 3])
             for index, item in iterator.enumerate():
                 print(index, item)
             # 0 1
             # 1 2
             # 2 3
            -
            +
            +
            Raises
            @@ -2524,39 +2436,39 @@
            Raises
            def - into_iter( iterable: collections.abc.Iterable[~Item]) -> aiobungie.internal.iterators.FlatIterator[~Item]: + into_iter( iterable: collections.abc.Iterable[~Item]) -> aiobungie.internal.iterators.Iterator[~Item]:
            -
            588def into_iter(
            -589    iterable: collections.Iterable[Item],
            -590) -> FlatIterator[Item]:
            -591    """Transform an iterable into an flat iterator.
            -592
            -593    Example
            -594    -------
            -595    ```py
            -596    sequence = [1,2,3]
            -597    for item in aiobungie.into_iter(sequence).reversed():
            -598        print(item)
            -599    # 3
            -600    # 2
            -601    # 1
            -602    ```
            -603
            -604    Parameters
            -605    ----------
            -606    iterable: `typing.Iterable[Item]`
            -607        The iterable to convert.
            -608
            -609    Raises
            -610    ------
            -611    `StopIteration`
            -612        If no elements are left in the iterator.
            -613    """
            -614    return FlatIterator(iterable)
            +            
            559def into_iter(
            +560    iterable: collections.Iterable[Item],
            +561) -> Iterator[Item]:
            +562    """Transform an iterable into an flat iterator.
            +563
            +564    Example
            +565    -------
            +566    ```py
            +567    sequence = [1,2,3]
            +568    for item in aiobungie.into_iter(sequence).reversed():
            +569        print(item)
            +570    # 3
            +571    # 2
            +572    # 1
            +573    ```
            +574
            +575    Parameters
            +576    ----------
            +577    iterable: `typing.Iterable[Item]`
            +578        The iterable to convert.
            +579
            +580    Raises
            +581    ------
            +582    `StopIteration`
            +583        If no elements are left in the iterator.
            +584    """
            +585    return Iterator(iterable)
             
            @@ -2564,13 +2476,15 @@
            Raises
            Example
            -
            sequence = [1,2,3]
            +
            +
            sequence = [1,2,3]
             for item in aiobungie.into_iter(sequence).reversed():
                 print(item)
             # 3
             # 2
             # 1
            -
            +
            +
            Parameters
            @@ -2691,7 +2605,11 @@
            Raises
            let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/internal/time.html b/docs/aiobungie/internal/time.html index ae1e4462..f8cc2857 100644 --- a/docs/aiobungie/internal/time.html +++ b/docs/aiobungie/internal/time.html @@ -3,7 +3,7 @@ - + aiobungie.internal.time API documentation @@ -67,9 +67,9 @@

            Time helper functions.

            - + - +
             1# MIT License
              2#
            @@ -423,7 +423,11 @@ 

            let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/rest.html b/docs/aiobungie/rest.html index 56099550..eaf10d6f 100644 --- a/docs/aiobungie/rest.html +++ b/docs/aiobungie/rest.html @@ -3,7 +3,7 @@ - + aiobungie.rest API documentation @@ -390,9 +390,6 @@

            API Documentation

          • RESTPool
          • -
          • - client_id -
          • metadata
          • @@ -447,9 +444,9 @@

            This client only makes HTTP requests to the API and returns pure JSON objects.

            - + - +
               1# MIT License
                2#
            @@ -648,2172 +645,2160 @@ 

            195 connect: typing.Optional[float] = None, 196 socket_read: typing.Optional[float] = None, 197 socket_connect: typing.Optional[float] = None, - 198 **kwargs: typing.Any, - 199 ) -> _Session: - 200 """Creates a new TCP connection client session.""" - 201 session = aiohttp.ClientSession( - 202 connector=aiohttp.TCPConnector(ssl=False, **kwargs), - 203 connector_owner=owner, - 204 raise_for_status=raise_status, - 205 timeout=aiohttp.ClientTimeout( - 206 total=total_timeout, - 207 sock_read=socket_read, - 208 sock_connect=socket_connect, - 209 connect=connect, - 210 ), - 211 ) - 212 _LOG.debug("New session created.") - 213 return _Session(client_session=session) - 214 - 215 async def close(self) -> None: - 216 # Close the TCP connector and all sessions. - 217 _LOG.debug("Closing session...") - 218 if self.client_session.connector is not None: - 219 await self.client_session.connector.close() - 220 await asyncio.sleep(0.025) - 221 _LOG.debug("Session closed.") - 222 - 223 - 224class RequestMethod(str, enums.Enum): - 225 """HTTP request methods enum.""" - 226 - 227 GET = "GET" - 228 """GET methods.""" - 229 POST = "POST" - 230 """POST methods.""" - 231 PUT = "PUT" - 232 """PUT methods.""" - 233 PATCH = "PATCH" - 234 """PATCH methods.""" - 235 DELETE = "DELETE" - 236 """DELETE methods""" - 237 - 238 - 239class _Dyn(RuntimeError): - 240 ... - 241 - 242 - 243class RESTPool: - 244 """Pool of `RESTClient` instances. - 245 - 246 This allows to create multiple instances of `RESTClient`s that can be acquired - 247 which share the same config and metadata. - 248 - 249 Example - 250 ------- - 251 ```py - 252 import aiobungie - 253 import asyncio + 198 ) -> _Session: + 199 """Creates a new TCP connection client session.""" + 200 session = aiohttp.ClientSession( + 201 connector=aiohttp.TCPConnector(ssl=False), + 202 connector_owner=owner, + 203 raise_for_status=raise_status, + 204 timeout=aiohttp.ClientTimeout( + 205 total=total_timeout, + 206 sock_read=socket_read, + 207 sock_connect=socket_connect, + 208 connect=connect, + 209 ), + 210 ) + 211 _LOG.debug("New session created.") + 212 return _Session(client_session=session) + 213 + 214 async def close(self) -> None: + 215 # Close the TCP connector and all sessions. + 216 _LOG.debug("Closing session...") + 217 if self.client_session.connector is not None: + 218 await self.client_session.connector.close() + 219 _LOG.debug("Session closed.") + 220 + 221 + 222class RequestMethod(str, enums.Enum): + 223 """HTTP request methods enum.""" + 224 + 225 GET = "GET" + 226 """GET methods.""" + 227 POST = "POST" + 228 """POST methods.""" + 229 PUT = "PUT" + 230 """PUT methods.""" + 231 PATCH = "PATCH" + 232 """PATCH methods.""" + 233 DELETE = "DELETE" + 234 """DELETE methods""" + 235 + 236 + 237class _Dyn(RuntimeError): + 238 ... + 239 + 240 + 241class RESTPool: + 242 """Pool of `RESTClient` instances. + 243 + 244 This allows to create multiple instances of `RESTClient`s that can be acquired + 245 which share the same config and metadata. + 246 + 247 Example + 248 ------- + 249 ```py + 250 import aiobungie + 251 import asyncio + 252 + 253 client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret') 254 - 255 client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret') - 256 - 257 # Using a context manager to acquire an instance - 258 # of the pool and close the connection after finishing. - 259 - 260 async def first() -> str: - 261 async with client_pool.acquire() as client: - 262 return client.build_oauth2_url() - 263 - 264 async def second() -> None: - 265 async with client_pool.acquire() as client: - 266 new_tokens = await client.refresh_access_token("token") - 267 client.metadata['tokens'] = new_tokens - 268 - 269 # Client instances are independent from first and second. - 270 await asyncio.gather(first(), second()) - 271 ``` - 272 - 273 Parameters - 274 ---------- - 275 token : `str` - 276 A valid application token from Bungie's developer portal. - 277 - 278 Other Parameters - 279 ---------------- - 280 max_retries : `int` - 281 The max retries number to retry if the request hit a `5xx` status code. - 282 max_ratelimit_retries : `int` - 283 The max retries number to retry if the request hit a `429` status code. Defaults to `3`. - 284 client_secret : `typing.Optional[str]` - 285 An optional application client secret, - 286 This is only needed if you're fetching OAuth2 tokens with this client. - 287 client_id : `typing.Optional[int]` - 288 An optional application client id, - 289 This is only needed if you're fetching OAuth2 tokens with this client. - 290 enable_debugging : `bool | str` - 291 Whether to enable logging responses or not. - 292 - 293 Logging Levels - 294 -------------- - 295 * `False`: This will disable logging. - 296 * `True`: This will set the level to `DEBUG` and enable logging minimal information. - 297 Like the response status, route, taken time and so on. - 298 * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information. - 299 """ - 300 - 301 __slots__ = ( - 302 "_token", - 303 "_max_retries", - 304 "_client_secret", - 305 "_client_id", - 306 "_max_rate_limit_retries", - 307 "_metadata", - 308 "_enable_debug", - 309 ) - 310 - 311 # Looks like mypy doesn't like this. - 312 if typing.TYPE_CHECKING: - 313 _enable_debug: typing.Union[typing.Literal["TRACE"], bool, int] - 314 - 315 def __init__( - 316 self, - 317 token: str, - 318 /, - 319 client_secret: typing.Optional[str] = None, - 320 client_id: typing.Optional[int] = None, - 321 *, - 322 max_retries: int = 4, - 323 max_rate_limit_retries: int = 3, - 324 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, - 325 ) -> None: - 326 self._client_secret = client_secret - 327 self._client_id = client_id - 328 self._token: str = token - 329 self._max_retries = max_retries - 330 self._max_rate_limit_retries = max_rate_limit_retries - 331 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} - 332 self._enable_debug = enable_debugging - 333 - 334 @property - 335 def client_id(self) -> typing.Optional[int]: - 336 return self._client_id - 337 - 338 @property - 339 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: - 340 """Pool's Metadata. This is different from client instance metadata.""" - 341 return self._metadata - 342 - 343 @typing.final - 344 def acquire(self) -> RESTClient: - 345 """Acquires a new `RESTClient` instance from this REST pool. - 346 - 347 Returns - 348 ------- - 349 `RESTClient` - 350 An instance of a REST client. - 351 """ - 352 instance = RESTClient( - 353 self._token, - 354 client_secret=self._client_secret, - 355 client_id=self._client_id, - 356 max_retries=self._max_retries, - 357 max_ratelimit_retries=self._max_rate_limit_retries, - 358 enable_debugging=self._enable_debug, - 359 ) - 360 return instance - 361 - 362 - 363class RESTClient(interfaces.RESTInterface): - 364 """A RESTful client implementation for Bungie's API. - 365 - 366 This client is designed to only make HTTP requests and return JSON objects - 367 to provide RESTful functionality. - 368 - 369 This client is also used within `aiobungie.Client` which deserialize those returned JSON objects - 370 using the factory into Pythonic data classes objects which provide Python functionality. - 371 - 372 Example - 373 ------- - 374 ```py - 375 import aiobungie - 376 - 377 async def main(): - 378 async with aiobungie.RESTClient("TOKEN") as rest_client: - 379 req = await rest_client.fetch_clan_members(4389205) - 380 clan_members = req['results'] - 381 for member in clan_members: - 382 for k, v in member['destinyUserInfo'].items(): - 383 print(k, v) - 384 ``` - 385 - 386 Parameters - 387 ---------- - 388 token : `str` - 389 A valid application token from Bungie's developer portal. - 390 - 391 Other Parameters - 392 ---------------- - 393 max_retries : `int` - 394 The max retries number to retry if the request hit a `5xx` status code. - 395 max_ratelimit_retries : `int` - 396 The max retries number to retry if the request hit a `429` status code. Defaults to `3`. - 397 client_secret : `typing.Optional[str]` - 398 An optional application client secret, - 399 This is only needed if you're fetching OAuth2 tokens with this client. - 400 client_id : `typing.Optional[int]` - 401 An optional application client id, - 402 This is only needed if you're fetching OAuth2 tokens with this client. - 403 enable_debugging : `bool | str` - 404 Whether to enable logging responses or not. - 405 - 406 Logging Levels - 407 -------------- - 408 * `False`: This will disable logging. - 409 * `True`: This will set the level to `DEBUG` and enable logging minimal information. - 410 * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information. - 411 """ - 412 - 413 __slots__ = ( - 414 "_token", - 415 "_session", - 416 "_lock", - 417 "_max_retries", - 418 "_client_secret", - 419 "_client_id", - 420 "_metadata", - 421 "_max_rate_limit_retries", - 422 ) - 423 - 424 def __init__( - 425 self, - 426 token: str, - 427 /, - 428 client_secret: typing.Optional[str] = None, - 429 client_id: typing.Optional[int] = None, - 430 *, - 431 max_retries: int = 4, - 432 max_ratelimit_retries: int = 3, - 433 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, - 434 ) -> None: - 435 self._session: typing.Optional[_Session] = None - 436 self._lock: typing.Optional[asyncio.Lock] = None - 437 self._client_secret = client_secret - 438 self._client_id = client_id - 439 self._token: str = token - 440 self._max_retries = max_retries - 441 self._max_rate_limit_retries = max_ratelimit_retries - 442 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} + 255 # Using a context manager to acquire an instance + 256 # of the pool and close the connection after finishing. + 257 + 258 async def first() -> str: + 259 async with client_pool.acquire() as client: + 260 return client.build_oauth2_url() + 261 + 262 async def second() -> None: + 263 async with client_pool.acquire() as client: + 264 new_tokens = await client.refresh_access_token("token") + 265 client.metadata['tokens'] = new_tokens + 266 + 267 # Client instances are independent from first and second. + 268 await asyncio.gather(first(), second()) + 269 ``` + 270 + 271 Parameters + 272 ---------- + 273 token : `str` + 274 A valid application token from Bungie's developer portal. + 275 + 276 Other Parameters + 277 ---------------- + 278 max_retries : `int` + 279 The max retries number to retry if the request hit a `5xx` status code. + 280 max_ratelimit_retries : `int` + 281 The max retries number to retry if the request hit a `429` status code. Defaults to `3`. + 282 client_secret : `typing.Optional[str]` + 283 An optional application client secret, + 284 This is only needed if you're fetching OAuth2 tokens with this client. + 285 client_id : `typing.Optional[int]` + 286 An optional application client id, + 287 This is only needed if you're fetching OAuth2 tokens with this client. + 288 enable_debugging : `bool | str` + 289 Whether to enable logging responses or not. + 290 + 291 Logging Levels + 292 -------------- + 293 * `False`: This will disable logging. + 294 * `True`: This will set the level to `DEBUG` and enable logging minimal information. + 295 Like the response status, route, taken time and so on. + 296 * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information. + 297 """ + 298 + 299 __slots__ = ( + 300 "_token", + 301 "_max_retries", + 302 "_client_secret", + 303 "_client_id", + 304 "_max_rate_limit_retries", + 305 "_metadata", + 306 "_enable_debug", + 307 ) + 308 + 309 # Looks like mypy doesn't like this. + 310 if typing.TYPE_CHECKING: + 311 _enable_debug: typing.Union[typing.Literal["TRACE"], bool, int] + 312 + 313 def __init__( + 314 self, + 315 token: str, + 316 /, + 317 client_secret: typing.Optional[str] = None, + 318 client_id: typing.Optional[int] = None, + 319 *, + 320 max_retries: int = 4, + 321 max_rate_limit_retries: int = 3, + 322 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, + 323 ) -> None: + 324 self._client_secret = client_secret + 325 self._client_id = client_id + 326 self._token: str = token + 327 self._max_retries = max_retries + 328 self._max_rate_limit_retries = max_rate_limit_retries + 329 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} + 330 self._enable_debug = enable_debugging + 331 + 332 @property + 333 def client_id(self) -> typing.Optional[int]: + 334 return self._client_id + 335 + 336 @property + 337 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: + 338 """Pool's Metadata. This is different from client instance metadata.""" + 339 return self._metadata + 340 + 341 @typing.final + 342 def acquire(self) -> RESTClient: + 343 """Acquires a new `RESTClient` instance from this REST pool. + 344 + 345 Returns + 346 ------- + 347 `RESTClient` + 348 An instance of a REST client. + 349 """ + 350 instance = RESTClient( + 351 self._token, + 352 client_secret=self._client_secret, + 353 client_id=self._client_id, + 354 max_retries=self._max_retries, + 355 max_ratelimit_retries=self._max_rate_limit_retries, + 356 enable_debugging=self._enable_debug, + 357 ) + 358 return instance + 359 + 360 + 361class RESTClient(interfaces.RESTInterface): + 362 """A RESTful client implementation for Bungie's API. + 363 + 364 This client is designed to only make HTTP requests and return JSON objects + 365 to provide RESTful functionality. + 366 + 367 This client is also used within `aiobungie.Client` which deserialize those returned JSON objects + 368 using the factory into Pythonic data classes objects which provide Python functionality. + 369 + 370 Example + 371 ------- + 372 ```py + 373 import aiobungie + 374 + 375 async def main(): + 376 async with aiobungie.RESTClient("TOKEN") as rest_client: + 377 req = await rest_client.fetch_clan_members(4389205) + 378 clan_members = req['results'] + 379 for member in clan_members: + 380 for k, v in member['destinyUserInfo'].items(): + 381 print(k, v) + 382 ``` + 383 + 384 Parameters + 385 ---------- + 386 token : `str` + 387 A valid application token from Bungie's developer portal. + 388 + 389 Other Parameters + 390 ---------------- + 391 max_retries : `int` + 392 The max retries number to retry if the request hit a `5xx` status code. + 393 max_ratelimit_retries : `int` + 394 The max retries number to retry if the request hit a `429` status code. Defaults to `3`. + 395 client_secret : `typing.Optional[str]` + 396 An optional application client secret, + 397 This is only needed if you're fetching OAuth2 tokens with this client. + 398 client_id : `typing.Optional[int]` + 399 An optional application client id, + 400 This is only needed if you're fetching OAuth2 tokens with this client. + 401 enable_debugging : `bool | str` + 402 Whether to enable logging responses or not. + 403 + 404 Logging Levels + 405 -------------- + 406 * `False`: This will disable logging. + 407 * `True`: This will set the level to `DEBUG` and enable logging minimal information. + 408 * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information. + 409 """ + 410 + 411 __slots__ = ( + 412 "_token", + 413 "_session", + 414 "_lock", + 415 "_max_retries", + 416 "_client_secret", + 417 "_client_id", + 418 "_metadata", + 419 "_max_rate_limit_retries", + 420 ) + 421 + 422 def __init__( + 423 self, + 424 token: str, + 425 /, + 426 client_secret: typing.Optional[str] = None, + 427 client_id: typing.Optional[int] = None, + 428 *, + 429 max_retries: int = 4, + 430 max_ratelimit_retries: int = 3, + 431 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, + 432 ) -> None: + 433 self._session: typing.Optional[_Session] = None + 434 self._lock: typing.Optional[asyncio.Lock] = None + 435 self._client_secret = client_secret + 436 self._client_id = client_id + 437 self._token: str = token + 438 self._max_retries = max_retries + 439 self._max_rate_limit_retries = max_ratelimit_retries + 440 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} + 441 + 442 self._set_debug_level(enable_debugging) 443 - 444 self._set_debug_level(enable_debugging) - 445 - 446 @property - 447 def client_id(self) -> typing.Optional[int]: - 448 return self._client_id - 449 - 450 @property - 451 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: - 452 return self._metadata - 453 - 454 @property - 455 def is_alive(self) -> bool: - 456 return self._session is not None - 457 - 458 @typing.final - 459 async def close(self) -> None: - 460 session = self._get_session() - 461 await session.close() - 462 self._session = None - 463 - 464 @typing.final - 465 def open(self) -> None: - 466 """Open a new client session. This is called internally with contextmanager usage.""" - 467 if self.is_alive: - 468 raise RuntimeError("Cannot open a new session while it's already open.") + 444 @property + 445 def client_id(self) -> typing.Optional[int]: + 446 return self._client_id + 447 + 448 @property + 449 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: + 450 return self._metadata + 451 + 452 @property + 453 def is_alive(self) -> bool: + 454 return self._session is not None + 455 + 456 @typing.final + 457 async def close(self) -> None: + 458 session = self._get_session() + 459 await session.close() + 460 self._session = None + 461 + 462 @typing.final + 463 def open(self) -> None: + 464 """Open a new client session. This is called internally with contextmanager usage.""" + 465 if self.is_alive: + 466 raise RuntimeError("Cannot open a new session while it's already open.") + 467 + 468 self._session = _Session.create(owner=False, raise_status=False) 469 - 470 self._session = _Session.create( - 471 owner=False, - 472 raise_status=False, - 473 connect=None, - 474 socket_read=None, - 475 socket_connect=None, - 476 ) - 477 - 478 @typing.final - 479 def enable_debugging( - 480 self, - 481 level: typing.Union[typing.Literal["TRACE"], bool, int] = False, - 482 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, - 483 /, - 484 ) -> None: - 485 self._set_debug_level(level, file) - 486 - 487 @typing.final - 488 async def static_request( - 489 self, - 490 method: typing.Union[RequestMethod, str], - 491 path: str, - 492 *, - 493 auth: typing.Optional[str] = None, - 494 json: typing.Optional[dict[str, typing.Any]] = None, - 495 ) -> ResponseSig: - 496 return await self._request(method, path, auth=auth, json=json) + 470 @typing.final + 471 def enable_debugging( + 472 self, + 473 level: typing.Union[typing.Literal["TRACE"], bool, int] = False, + 474 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, + 475 /, + 476 ) -> None: + 477 self._set_debug_level(level, file) + 478 + 479 @typing.final + 480 async def static_request( + 481 self, + 482 method: typing.Union[RequestMethod, str], + 483 path: str, + 484 *, + 485 auth: typing.Optional[str] = None, + 486 json: typing.Optional[dict[str, typing.Any]] = None, + 487 ) -> ResponseSig: + 488 return await self._request(method, path, auth=auth, json=json) + 489 + 490 @typing.final + 491 def build_oauth2_url( + 492 self, client_id: typing.Optional[int] = None + 493 ) -> typing.Optional[builders.OAuthURL]: + 494 client_id = client_id or self._client_id + 495 if client_id is None: + 496 return None 497 - 498 @typing.final - 499 def build_oauth2_url( - 500 self, client_id: typing.Optional[int] = None - 501 ) -> typing.Optional[str]: - 502 client_id = client_id or self._client_id - 503 if client_id is None: - 504 return None + 498 return builders.OAuthURL(client_id=client_id) + 499 + 500 @staticmethod + 501 def _set_debug_level( + 502 level: typing.Union[typing.Literal["TRACE"], bool, int] = False, + 503 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, + 504 ) -> None: 505 - 506 return url.OAUTH2_EP_BUILDER.format( - 507 oauth_endpoint=url.OAUTH_EP, - 508 client_id=client_id, - 509 uuid=_uuid(), - 510 ) + 506 file_handler = logging.FileHandler(file, mode="w") if file else None + 507 if level == "TRACE" or level == TRACE: + 508 logging.basicConfig( + 509 level=TRACE, handlers=[file_handler] if file_handler else None + 510 ) 511 - 512 @staticmethod - 513 def _set_debug_level( - 514 level: typing.Union[typing.Literal["TRACE"], bool, int] = False, - 515 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, - 516 ) -> None: - 517 - 518 file_handler = logging.FileHandler(file, mode="w") if file else None - 519 if level == "TRACE" or level == TRACE: - 520 logging.basicConfig( - 521 level=TRACE, handlers=[file_handler] if file_handler else None - 522 ) - 523 - 524 elif level: - 525 logging.basicConfig( - 526 level=logging.DEBUG, handlers=[file_handler] if file_handler else None - 527 ) - 528 - 529 def _get_session(self) -> _Session: - 530 if self._session: - 531 return self._session - 532 - 533 raise RuntimeError( - 534 "Cannot return a session while its close. Make sure you use `async with` before making requests." - 535 ) - 536 - 537 async def _request( - 538 self, - 539 method: typing.Union[RequestMethod, str], - 540 route: str, - 541 *, - 542 base: bool = False, - 543 oauth2: bool = False, - 544 auth: typing.Optional[str] = None, - 545 unwrapping: typing.Literal["json", "read"] = "json", - 546 json: typing.Optional[dict[str, typing.Any]] = None, - 547 headers: typing.Optional[dict[str, typing.Any]] = None, - 548 data: typing.Optional[typing.Union[str, dict[str, typing.Any]]] = None, - 549 ) -> ResponseSig: - 550 - 551 retries: int = 0 - 552 session = self._get_session() - 553 headers = headers or {} + 512 elif level: + 513 logging.basicConfig( + 514 level=logging.DEBUG, handlers=[file_handler] if file_handler else None + 515 ) + 516 + 517 def _get_session(self) -> _Session: + 518 if self._session: + 519 return self._session + 520 + 521 raise RuntimeError( + 522 "Cannot return a session while its close. Make sure you use `async with` before making requests." + 523 ) + 524 + 525 async def _request( + 526 self, + 527 method: typing.Union[RequestMethod, str], + 528 route: str, + 529 *, + 530 base: bool = False, + 531 oauth2: bool = False, + 532 auth: typing.Optional[str] = None, + 533 unwrapping: typing.Literal["json", "read"] = "json", + 534 json: typing.Optional[dict[str, typing.Any]] = None, + 535 headers: typing.Optional[dict[str, typing.Any]] = None, + 536 data: typing.Optional[typing.Union[str, dict[str, typing.Any]]] = None, + 537 ) -> ResponseSig: + 538 + 539 retries: int = 0 + 540 session = self._get_session() + 541 headers = headers or {} + 542 + 543 headers.setdefault(_USER_AGENT_HEADERS, _USER_AGENT) + 544 headers["X-API-KEY"] = self._token + 545 + 546 if auth is not None: + 547 headers[_AUTH_HEADER] = f"Bearer {auth}" + 548 + 549 # Handling endpoints + 550 endpoint = url.BASE + 551 + 552 if not base: + 553 endpoint = endpoint + url.REST_EP 554 - 555 headers.setdefault(_USER_AGENT_HEADERS, _USER_AGENT) - 556 headers["X-API-KEY"] = self._token - 557 - 558 if auth is not None: - 559 headers[_AUTH_HEADER] = f"Bearer {auth}" - 560 - 561 # Handling endpoints - 562 endpoint = url.BASE - 563 - 564 if not base: - 565 endpoint = endpoint + url.REST_EP + 555 if oauth2: + 556 headers["Content-Type"] = "application/x-www-form-urlencoded" + 557 endpoint = endpoint + url.TOKEN_EP + 558 + 559 if self._lock is None: + 560 self._lock = asyncio.Lock() + 561 + 562 while True: + 563 try: + 564 async with (stack := contextlib.AsyncExitStack()): + 565 await stack.enter_async_context(self._lock) 566 - 567 if oauth2: - 568 headers["Content-Type"] = "application/x-www-form-urlencoded" - 569 endpoint = endpoint + url.TOKEN_EP - 570 - 571 if self._lock is None: - 572 self._lock = asyncio.Lock() - 573 - 574 while True: - 575 try: - 576 async with (stack := contextlib.AsyncExitStack()): - 577 await stack.enter_async_context(self._lock) - 578 - 579 # We make the request here. - 580 taken_time = time.monotonic() - 581 response = await stack.enter_async_context( - 582 session.client_session.request( - 583 method=method, - 584 url=f"{endpoint}/{route}", - 585 json=json, - 586 headers=headers, - 587 data=data, - 588 ) - 589 ) - 590 response_time = (time.monotonic() - taken_time) * 1_000 + 567 # We make the request here. + 568 taken_time = time.monotonic() + 569 response = await stack.enter_async_context( + 570 session.client_session.request( + 571 method=method, + 572 url=f"{endpoint}/{route}", + 573 json=json, + 574 headers=headers, + 575 data=data, + 576 ) + 577 ) + 578 response_time = (time.monotonic() - taken_time) * 1_000 + 579 + 580 _LOG.debug( + 581 "%s %s %s Time %.4fms", + 582 method, + 583 f"{endpoint}/{route}", + 584 f"{response.status} {response.reason}", + 585 response_time, + 586 ) + 587 + 588 await self._handle_ratelimit( + 589 response, method, route, self._max_rate_limit_retries + 590 ) 591 - 592 _LOG.debug( - 593 "%s %s %s Time %.4fms", - 594 method, - 595 f"{endpoint}/{route}", - 596 f"{response.status} {response.reason}", - 597 response_time, - 598 ) + 592 if response.status == http.HTTPStatus.NO_CONTENT: + 593 return None + 594 + 595 if 300 > response.status >= 200: + 596 if unwrapping == "read": + 597 # We need to read the bytes for the manifest response. + 598 return await response.read() 599 - 600 await self._handle_ratelimit( - 601 response, method, route, self._max_rate_limit_retries - 602 ) - 603 - 604 if response.status == http.HTTPStatus.NO_CONTENT: - 605 return None - 606 - 607 if 300 > response.status >= 200: - 608 if unwrapping == "read": - 609 # We need to read the bytes for the manifest response. - 610 return await response.read() - 611 - 612 if response.content_type == _APP_JSON: - 613 json_data = await response.json() - 614 - 615 _LOG.debug( - 616 "%s %s %s Time %.4fms", - 617 method, - 618 f"{endpoint}/{route}", - 619 f"{response.status} {response.reason}", - 620 response_time, - 621 ) - 622 - 623 if _LOG.isEnabledFor(TRACE): - 624 headers.update(response.headers) # type: ignore - 625 - 626 _LOG.log( - 627 TRACE, - 628 "%s", - 629 error.stringify_http_message(headers), - 630 ) - 631 - 632 # Return the response. - 633 # oauth2 responses are not packed inside a Response object. - 634 if oauth2: - 635 return json_data # type: ignore[no-any-return] - 636 - 637 return json_data["Response"] # type: ignore[no-any-return] - 638 - 639 if ( - 640 response.status in _RETRY_5XX - 641 and retries < self._max_retries # noqa: W503 - 642 ): - 643 backoff_ = backoff.ExponentialBackOff(maximum=6) - 644 sleep_time = next(backoff_) - 645 _LOG.warning( - 646 "Got %i - %s. Sleeping for %.2f seconds. Remaining retries: %i", - 647 response.status, - 648 response.reason, - 649 sleep_time, - 650 self._max_retries - retries, - 651 ) - 652 - 653 retries += 1 - 654 await asyncio.sleep(sleep_time) - 655 continue - 656 - 657 raise await error.raise_error(response) - 658 # eol - 659 except _Dyn: - 660 continue - 661 - 662 if not typing.TYPE_CHECKING: - 663 - 664 def __enter__(self) -> typing.NoReturn: - 665 cls = type(self) - 666 raise TypeError( - 667 f"{cls.__qualname__} is async only, use 'async with' instead." - 668 ) + 600 if response.content_type == _APP_JSON: + 601 json_data = await response.json() + 602 + 603 _LOG.debug( + 604 "%s %s %s Time %.4fms", + 605 method, + 606 f"{endpoint}/{route}", + 607 f"{response.status} {response.reason}", + 608 response_time, + 609 ) + 610 + 611 if _LOG.isEnabledFor(TRACE): + 612 headers.update(response.headers) # type: ignore + 613 + 614 _LOG.log( + 615 TRACE, + 616 "%s", + 617 error.stringify_http_message(headers), + 618 ) + 619 + 620 # Return the response. + 621 # oauth2 responses are not packed inside a Response object. + 622 if oauth2: + 623 return json_data # type: ignore[no-any-return] + 624 + 625 return json_data["Response"] # type: ignore[no-any-return] + 626 + 627 if ( + 628 response.status in _RETRY_5XX + 629 and retries < self._max_retries # noqa: W503 + 630 ): + 631 backoff_ = backoff.ExponentialBackOff(maximum=6) + 632 sleep_time = next(backoff_) + 633 _LOG.warning( + 634 "Got %i - %s. Sleeping for %.2f seconds. Remaining retries: %i", + 635 response.status, + 636 response.reason, + 637 sleep_time, + 638 self._max_retries - retries, + 639 ) + 640 + 641 retries += 1 + 642 await asyncio.sleep(sleep_time) + 643 continue + 644 + 645 raise await error.raise_error(response) + 646 # eol + 647 except _Dyn: + 648 continue + 649 + 650 if not typing.TYPE_CHECKING: + 651 + 652 def __enter__(self) -> typing.NoReturn: + 653 cls = type(self) + 654 raise TypeError( + 655 f"{cls.__qualname__} is async only, use 'async with' instead." + 656 ) + 657 + 658 def __exit__( + 659 self, + 660 exception_type: typing.Optional[type[BaseException]], + 661 exception: typing.Optional[BaseException], + 662 exception_traceback: typing.Optional[types.TracebackType], + 663 ) -> None: + 664 ... + 665 + 666 async def __aenter__(self) -> RESTClient: + 667 self.open() + 668 return self 669 - 670 def __exit__( - 671 self, - 672 exception_type: typing.Optional[type[BaseException]], - 673 exception: typing.Optional[BaseException], - 674 exception_traceback: typing.Optional[types.TracebackType], - 675 ) -> None: - 676 ... + 670 async def __aexit__( + 671 self, + 672 exception_type: typing.Optional[type[BaseException]], + 673 exception: typing.Optional[BaseException], + 674 exception_traceback: typing.Optional[types.TracebackType], + 675 ) -> None: + 676 await self.close() 677 - 678 async def __aenter__(self) -> RESTClient: - 679 self.open() - 680 return self - 681 - 682 async def __aexit__( - 683 self, - 684 exception_type: typing.Optional[type[BaseException]], - 685 exception: typing.Optional[BaseException], - 686 exception_traceback: typing.Optional[types.TracebackType], - 687 ) -> None: - 688 await self.close() - 689 - 690 # We don't want this to be super complicated. - 691 @staticmethod - 692 @typing.final - 693 async def _handle_ratelimit( - 694 response: aiohttp.ClientResponse, - 695 method: str, - 696 route: str, - 697 max_ratelimit_retries: int = 3, - 698 ) -> None: - 699 - 700 if response.status != http.HTTPStatus.TOO_MANY_REQUESTS: - 701 return - 702 - 703 if response.content_type != _APP_JSON: - 704 raise error.HTTPError( - 705 f"Being ratelimited on non JSON request, {response.content_type}.", - 706 http.HTTPStatus.TOO_MANY_REQUESTS, - 707 ) + 678 # We don't want this to be super complicated. + 679 @staticmethod + 680 @typing.final + 681 async def _handle_ratelimit( + 682 response: aiohttp.ClientResponse, + 683 method: str, + 684 route: str, + 685 max_ratelimit_retries: int = 3, + 686 ) -> None: + 687 + 688 if response.status != http.HTTPStatus.TOO_MANY_REQUESTS: + 689 return + 690 + 691 if response.content_type != _APP_JSON: + 692 raise error.HTTPError( + 693 f"Being ratelimited on non JSON request, {response.content_type}.", + 694 http.HTTPStatus.TOO_MANY_REQUESTS, + 695 ) + 696 + 697 count: int = 0 + 698 json: typedefs.JSONObject = await response.json() + 699 retry_after = float(json["ThrottleSeconds"]) + 700 + 701 while True: + 702 if count == max_ratelimit_retries: + 703 raise _Dyn + 704 + 705 if retry_after <= 0: + 706 # We sleep for a little bit to avoid funky behavior. + 707 sleep_time = float(random.random() + 0.93) / 2 708 - 709 count: int = 0 - 710 json: typedefs.JSONObject = await response.json() - 711 retry_after = float(json["ThrottleSeconds"]) - 712 - 713 while True: - 714 if count == max_ratelimit_retries: - 715 raise _Dyn - 716 - 717 if retry_after <= 0: - 718 # We sleep for a little bit to avoid funky behavior. - 719 sleep_time = float(random.random() + 0.93) / 2 - 720 - 721 _LOG.warning( - 722 "We're being ratelimited with method %s route %s. Sleeping for %.2fs.", - 723 method, - 724 route, - 725 sleep_time, - 726 ) - 727 count += 1 - 728 await asyncio.sleep(sleep_time) - 729 continue - 730 - 731 raise error.RateLimitedError( - 732 body=json, - 733 url=str(response.real_url), - 734 retry_after=retry_after, + 709 _LOG.warning( + 710 "We're being ratelimited with method %s route %s. Sleeping for %.2fs.", + 711 method, + 712 route, + 713 sleep_time, + 714 ) + 715 count += 1 + 716 await asyncio.sleep(sleep_time) + 717 continue + 718 + 719 raise error.RateLimitedError( + 720 body=json, + 721 url=str(response.real_url), + 722 retry_after=retry_after, + 723 ) + 724 + 725 async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response: + 726 + 727 if not isinstance(self._client_id, int): + 728 raise TypeError( + 729 f"Expected (int) for client id but got {type(self._client_id).__qualname__}" # type: ignore + 730 ) + 731 + 732 if not isinstance(self._client_secret, str): + 733 raise TypeError( + 734 f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}" # type: ignore 735 ) 736 - 737 async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response: - 738 - 739 if not isinstance(self._client_id, int): - 740 raise TypeError( - 741 f"Expected (int) for client id but got {type(self._client_id).__qualname__}" # type: ignore - 742 ) - 743 - 744 if not isinstance(self._client_secret, str): - 745 raise TypeError( - 746 f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}" # type: ignore - 747 ) - 748 - 749 headers = { - 750 "client_secret": self._client_secret, - 751 } - 752 - 753 data = ( - 754 f"grant_type=authorization_code&code={code}" - 755 f"&client_id={self._client_id}&client_secret={self._client_secret}" - 756 ) - 757 - 758 response = await self._request( - 759 RequestMethod.POST, "", headers=headers, data=data, oauth2=True - 760 ) - 761 assert isinstance(response, dict) - 762 return builders.OAuth2Response.build_response(response) - 763 - 764 async def refresh_access_token( - 765 self, refresh_token: str, / - 766 ) -> builders.OAuth2Response: - 767 if not isinstance(self._client_id, int): - 768 raise TypeError( - 769 f"Expected (int) for client id but got {type(self._client_id).__qualname__}" # type: ignore - 770 ) - 771 - 772 if not isinstance(self._client_secret, str): - 773 raise TypeError( - 774 f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}" # type: ignore - 775 ) + 737 headers = { + 738 "client_secret": self._client_secret, + 739 } + 740 + 741 data = ( + 742 f"grant_type=authorization_code&code={code}" + 743 f"&client_id={self._client_id}&client_secret={self._client_secret}" + 744 ) + 745 + 746 response = await self._request( + 747 RequestMethod.POST, "", headers=headers, data=data, oauth2=True + 748 ) + 749 assert isinstance(response, dict) + 750 return builders.OAuth2Response.build_response(response) + 751 + 752 async def refresh_access_token( + 753 self, refresh_token: str, / + 754 ) -> builders.OAuth2Response: + 755 if not isinstance(self._client_id, int): + 756 raise TypeError( + 757 f"Expected (int) for client id but got {type(self._client_id).__qualname__}" # type: ignore + 758 ) + 759 + 760 if not isinstance(self._client_secret, str): + 761 raise TypeError( + 762 f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}" # type: ignore + 763 ) + 764 + 765 data = { + 766 "grant_type": "refresh_token", + 767 "refresh_token": refresh_token, + 768 "client_id": self._client_id, + 769 "client_secret": self._client_secret, + 770 "Content-Type": "application/x-www-form-urlencoded", + 771 } + 772 + 773 response = await self._request(RequestMethod.POST, "", data=data, oauth2=True) + 774 assert isinstance(response, dict) + 775 return builders.OAuth2Response.build_response(response) 776 - 777 data = { - 778 "grant_type": "refresh_token", - 779 "refresh_token": refresh_token, - 780 "client_id": self._client_id, - 781 "client_secret": self._client_secret, - 782 "Content-Type": "application/x-www-form-urlencoded", - 783 } + 777 async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject: + 778 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 779 resp = await self._request( + 780 RequestMethod.GET, f"User/GetBungieNetUserById/{id}/" + 781 ) + 782 assert isinstance(resp, dict) + 783 return resp 784 - 785 response = await self._request(RequestMethod.POST, "", data=data, oauth2=True) - 786 assert isinstance(response, dict) - 787 return builders.OAuth2Response.build_response(response) - 788 - 789 async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject: - 790 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 791 resp = await self._request( - 792 RequestMethod.GET, f"User/GetBungieNetUserById/{id}/" - 793 ) - 794 assert isinstance(resp, dict) - 795 return resp - 796 - 797 async def fetch_user_themes(self) -> typedefs.JSONArray: - 798 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 799 resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/") - 800 assert isinstance(resp, list) - 801 return resp - 802 - 803 async def fetch_membership_from_id( - 804 self, - 805 id: int, - 806 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, - 807 /, - 808 ) -> typedefs.JSONObject: - 809 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 810 resp = await self._request( - 811 RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}" - 812 ) - 813 assert isinstance(resp, dict) - 814 return resp - 815 - 816 async def fetch_player( - 817 self, - 818 name: str, - 819 code: int, - 820 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL, - 821 /, - 822 ) -> typedefs.JSONArray: - 823 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 824 resp = await self._request( - 825 RequestMethod.POST, - 826 f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}", - 827 json={"displayName": name, "displayNameCode": code}, - 828 ) - 829 assert isinstance(resp, list) - 830 return resp - 831 - 832 async def search_users(self, name: str, /) -> typedefs.JSONObject: + 785 async def fetch_user_themes(self) -> typedefs.JSONArray: + 786 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 787 resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/") + 788 assert isinstance(resp, list) + 789 return resp + 790 + 791 async def fetch_membership_from_id( + 792 self, + 793 id: int, + 794 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, + 795 /, + 796 ) -> typedefs.JSONObject: + 797 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 798 resp = await self._request( + 799 RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}" + 800 ) + 801 assert isinstance(resp, dict) + 802 return resp + 803 + 804 async def fetch_player( + 805 self, + 806 name: str, + 807 code: int, + 808 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL, + 809 /, + 810 ) -> typedefs.JSONArray: + 811 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 812 resp = await self._request( + 813 RequestMethod.POST, + 814 f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}", + 815 json={"displayName": name, "displayNameCode": code}, + 816 ) + 817 assert isinstance(resp, list) + 818 return resp + 819 + 820 async def search_users(self, name: str, /) -> typedefs.JSONObject: + 821 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 822 resp = await self._request( + 823 RequestMethod.POST, + 824 "User/Search/GlobalName/0", + 825 json={"displayNamePrefix": name}, + 826 ) + 827 assert isinstance(resp, dict) + 828 return resp + 829 + 830 async def fetch_clan_from_id( + 831 self, id: int, /, access_token: typing.Optional[str] = None + 832 ) -> typedefs.JSONObject: 833 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 834 resp = await self._request( - 835 RequestMethod.POST, - 836 "User/Search/GlobalName/0", - 837 json={"displayNamePrefix": name}, - 838 ) - 839 assert isinstance(resp, dict) - 840 return resp - 841 - 842 async def fetch_clan_from_id( - 843 self, id: int, /, access_token: typing.Optional[str] = None - 844 ) -> typedefs.JSONObject: - 845 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 846 resp = await self._request( - 847 RequestMethod.GET, f"GroupV2/{id}", auth=access_token - 848 ) - 849 assert isinstance(resp, dict) - 850 return resp - 851 - 852 async def fetch_clan( - 853 self, - 854 name: str, - 855 /, - 856 access_token: typing.Optional[str] = None, - 857 *, - 858 type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, - 859 ) -> typedefs.JSONObject: - 860 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 861 resp = await self._request( - 862 RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token - 863 ) - 864 assert isinstance(resp, dict) - 865 return resp - 866 - 867 async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject: - 868 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 869 resp = await self._request( - 870 RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/" - 871 ) - 872 assert isinstance(resp, dict) - 873 return resp - 874 - 875 async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray: - 876 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 877 resp = await self._request( - 878 RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/" - 879 ) - 880 assert isinstance(resp, list) - 881 return resp - 882 - 883 async def fetch_application(self, appid: int, /) -> typedefs.JSONObject: - 884 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 885 resp = await self._request(RequestMethod.GET, f"App/Application/{appid}") - 886 assert isinstance(resp, dict) - 887 return resp - 888 - 889 async def fetch_character( - 890 self, - 891 member_id: int, - 892 membership_type: typedefs.IntAnd[enums.MembershipType], - 893 character_id: int, - 894 components: list[enums.ComponentType], - 895 auth: typing.Optional[str] = None, - 896 ) -> typedefs.JSONObject: - 897 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 898 collector = _collect_components(components) - 899 response = await self._request( - 900 RequestMethod.GET, - 901 f"Destiny2/{int(membership_type)}/Profile/{member_id}/" - 902 f"Character/{character_id}/?components={collector}", - 903 auth=auth, - 904 ) - 905 assert isinstance(response, dict) - 906 return response - 907 - 908 async def fetch_activities( - 909 self, - 910 member_id: int, - 911 character_id: int, - 912 mode: typedefs.IntAnd[enums.GameMode], - 913 membership_type: typedefs.IntAnd[ - 914 enums.MembershipType - 915 ] = enums.MembershipType.ALL, - 916 *, - 917 page: int = 0, - 918 limit: int = 1, - 919 ) -> typedefs.JSONObject: - 920 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 921 resp = await self._request( - 922 RequestMethod.GET, - 923 f"Destiny2/{int(membership_type)}/Account/" - 924 f"{member_id}/Character/{character_id}/Stats/Activities" - 925 f"/?mode={int(mode)}&count={limit}&page={page}", - 926 ) - 927 assert isinstance(resp, dict) - 928 return resp - 929 - 930 async def fetch_vendor_sales(self) -> typedefs.JSONObject: - 931 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 932 resp = await self._request( - 933 RequestMethod.GET, - 934 f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}", - 935 ) - 936 assert isinstance(resp, dict) - 937 return resp - 938 - 939 async def fetch_profile( - 940 self, - 941 membership_id: int, - 942 type: typedefs.IntAnd[enums.MembershipType], - 943 components: list[enums.ComponentType], - 944 auth: typing.Optional[str] = None, - 945 ) -> typedefs.JSONObject: - 946 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 947 collector = _collect_components(components) - 948 response = await self._request( - 949 RequestMethod.GET, - 950 f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}", - 951 auth=auth, - 952 ) - 953 assert isinstance(response, dict) - 954 return response - 955 - 956 async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject: - 957 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 958 response = await self._request( - 959 RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}" - 960 ) - 961 assert isinstance(response, dict) - 962 return response + 835 RequestMethod.GET, f"GroupV2/{id}", auth=access_token + 836 ) + 837 assert isinstance(resp, dict) + 838 return resp + 839 + 840 async def fetch_clan( + 841 self, + 842 name: str, + 843 /, + 844 access_token: typing.Optional[str] = None, + 845 *, + 846 type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, + 847 ) -> typedefs.JSONObject: + 848 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 849 resp = await self._request( + 850 RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token + 851 ) + 852 assert isinstance(resp, dict) + 853 return resp + 854 + 855 async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject: + 856 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 857 resp = await self._request( + 858 RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/" + 859 ) + 860 assert isinstance(resp, dict) + 861 return resp + 862 + 863 async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray: + 864 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 865 resp = await self._request( + 866 RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/" + 867 ) + 868 assert isinstance(resp, list) + 869 return resp + 870 + 871 async def fetch_application(self, appid: int, /) -> typedefs.JSONObject: + 872 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 873 resp = await self._request(RequestMethod.GET, f"App/Application/{appid}") + 874 assert isinstance(resp, dict) + 875 return resp + 876 + 877 async def fetch_character( + 878 self, + 879 member_id: int, + 880 membership_type: typedefs.IntAnd[enums.MembershipType], + 881 character_id: int, + 882 components: list[enums.ComponentType], + 883 auth: typing.Optional[str] = None, + 884 ) -> typedefs.JSONObject: + 885 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 886 collector = _collect_components(components) + 887 response = await self._request( + 888 RequestMethod.GET, + 889 f"Destiny2/{int(membership_type)}/Profile/{member_id}/" + 890 f"Character/{character_id}/?components={collector}", + 891 auth=auth, + 892 ) + 893 assert isinstance(response, dict) + 894 return response + 895 + 896 async def fetch_activities( + 897 self, + 898 member_id: int, + 899 character_id: int, + 900 mode: typedefs.IntAnd[enums.GameMode], + 901 membership_type: typedefs.IntAnd[ + 902 enums.MembershipType + 903 ] = enums.MembershipType.ALL, + 904 *, + 905 page: int = 0, + 906 limit: int = 1, + 907 ) -> typedefs.JSONObject: + 908 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 909 resp = await self._request( + 910 RequestMethod.GET, + 911 f"Destiny2/{int(membership_type)}/Account/" + 912 f"{member_id}/Character/{character_id}/Stats/Activities" + 913 f"/?mode={int(mode)}&count={limit}&page={page}", + 914 ) + 915 assert isinstance(resp, dict) + 916 return resp + 917 + 918 async def fetch_vendor_sales(self) -> typedefs.JSONObject: + 919 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 920 resp = await self._request( + 921 RequestMethod.GET, + 922 f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}", + 923 ) + 924 assert isinstance(resp, dict) + 925 return resp + 926 + 927 async def fetch_profile( + 928 self, + 929 membership_id: int, + 930 type: typedefs.IntAnd[enums.MembershipType], + 931 components: list[enums.ComponentType], + 932 auth: typing.Optional[str] = None, + 933 ) -> typedefs.JSONObject: + 934 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 935 collector = _collect_components(components) + 936 response = await self._request( + 937 RequestMethod.GET, + 938 f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}", + 939 auth=auth, + 940 ) + 941 assert isinstance(response, dict) + 942 return response + 943 + 944 async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject: + 945 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 946 response = await self._request( + 947 RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}" + 948 ) + 949 assert isinstance(response, dict) + 950 return response + 951 + 952 async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject: + 953 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 954 resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash) + 955 assert isinstance(resp, dict) + 956 return resp + 957 + 958 async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject: + 959 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. + 960 resp = await self.fetch_entity("DestinyObjectiveDefinition", hash) + 961 assert isinstance(resp, dict) + 962 return resp 963 - 964 async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject: - 965 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 966 resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash) - 967 assert isinstance(resp, dict) - 968 return resp - 969 - 970 async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject: - 971 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. - 972 resp = await self.fetch_entity("DestinyObjectiveDefinition", hash) - 973 assert isinstance(resp, dict) - 974 return resp - 975 - 976 async def fetch_groups_for_member( - 977 self, - 978 member_id: int, - 979 member_type: typedefs.IntAnd[enums.MembershipType], - 980 /, - 981 *, - 982 filter: int = 0, - 983 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, - 984 ) -> typedefs.JSONObject: - 985 resp = await self._request( - 986 RequestMethod.GET, - 987 f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", - 988 ) - 989 assert isinstance(resp, dict) - 990 return resp - 991 - 992 async def fetch_potential_groups_for_member( - 993 self, - 994 member_id: int, - 995 member_type: typedefs.IntAnd[enums.MembershipType], - 996 /, - 997 *, - 998 filter: int = 0, - 999 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, -1000 ) -> typedefs.JSONObject: -1001 resp = await self._request( -1002 RequestMethod.GET, -1003 f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", -1004 ) -1005 assert isinstance(resp, dict) -1006 return resp -1007 -1008 async def fetch_clan_members( -1009 self, -1010 clan_id: int, -1011 /, -1012 *, -1013 name: typing.Optional[str] = None, -1014 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, -1015 ) -> typedefs.JSONObject: -1016 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1017 resp = await self._request( -1018 RequestMethod.GET, -1019 f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}&currentpage=1", -1020 ) -1021 assert isinstance(resp, dict) -1022 return resp -1023 -1024 async def fetch_hardlinked_credentials( -1025 self, -1026 credential: int, -1027 type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID, -1028 /, -1029 ) -> typedefs.JSONObject: -1030 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1031 resp = await self._request( -1032 RequestMethod.GET, -1033 f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/", -1034 ) -1035 assert isinstance(resp, dict) -1036 return resp -1037 -1038 async def fetch_user_credentials( -1039 self, access_token: str, membership_id: int, / -1040 ) -> typedefs.JSONArray: -1041 resp = await self._request( -1042 RequestMethod.GET, -1043 f"User/GetCredentialTypesForTargetAccount/{membership_id}", -1044 auth=access_token, -1045 ) -1046 assert isinstance(resp, list) -1047 return resp -1048 -1049 async def insert_socket_plug( -1050 self, -1051 action_token: str, -1052 /, -1053 instance_id: int, -1054 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], -1055 character_id: int, -1056 membership_type: typedefs.IntAnd[enums.MembershipType], -1057 ) -> typedefs.JSONObject: -1058 -1059 if isinstance(plug, builders.PlugSocketBuilder): -1060 plug = plug.collect() -1061 -1062 body = { -1063 "actionToken": action_token, -1064 "itemInstanceId": instance_id, -1065 "plug": plug, -1066 "characterId": character_id, -1067 "membershipType": int(membership_type), -1068 } -1069 resp = await self._request( -1070 RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body -1071 ) -1072 assert isinstance(resp, dict) -1073 return resp -1074 -1075 async def insert_socket_plug_free( -1076 self, -1077 access_token: str, -1078 /, -1079 instance_id: int, -1080 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], -1081 character_id: int, -1082 membership_type: typedefs.IntAnd[enums.MembershipType], -1083 ) -> typedefs.JSONObject: -1084 -1085 if isinstance(plug, builders.PlugSocketBuilder): -1086 plug = plug.collect() -1087 -1088 body = { -1089 "itemInstanceId": instance_id, -1090 "plug": plug, -1091 "characterId": character_id, -1092 "membershipType": int(membership_type), -1093 } -1094 resp = await self._request( -1095 RequestMethod.POST, -1096 "Destiny2/Actions/Items/InsertSocketPlugFree", -1097 json=body, -1098 auth=access_token, -1099 ) -1100 assert isinstance(resp, dict) -1101 return resp -1102 -1103 async def set_item_lock_state( -1104 self, -1105 access_token: str, -1106 state: bool, -1107 /, -1108 item_id: int, -1109 character_id: int, -1110 membership_type: typedefs.IntAnd[enums.MembershipType], -1111 ) -> int: -1112 body = { -1113 "state": state, -1114 "itemId": item_id, -1115 "characterId": character_id, -1116 "membership_type": int(membership_type), -1117 } -1118 response = await self._request( -1119 RequestMethod.POST, -1120 "Destiny2/Actions/Items/SetLockState", -1121 json=body, -1122 auth=access_token, -1123 ) -1124 assert isinstance(response, int) -1125 return response -1126 -1127 async def set_quest_track_state( -1128 self, -1129 access_token: str, -1130 state: bool, -1131 /, -1132 item_id: int, -1133 character_id: int, -1134 membership_type: typedefs.IntAnd[enums.MembershipType], -1135 ) -> int: -1136 body = { -1137 "state": state, -1138 "itemId": item_id, -1139 "characterId": character_id, -1140 "membership_type": int(membership_type), -1141 } -1142 response = await self._request( -1143 RequestMethod.POST, -1144 "Destiny2/Actions/Items/SetTrackedState", -1145 json=body, -1146 auth=access_token, -1147 ) -1148 assert isinstance(response, int) -1149 return response -1150 -1151 async def fetch_manifest_path(self) -> typedefs.JSONObject: -1152 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1153 path = await self._request(RequestMethod.GET, "Destiny2/Manifest") -1154 assert isinstance(path, dict) -1155 return path -1156 -1157 async def read_manifest_bytes(self, language: str = "en", /) -> bytes: -1158 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1159 _ensure_manifest_language(language) -1160 -1161 content = await self.fetch_manifest_path() -1162 resp = await self._request( -1163 RequestMethod.GET, -1164 content["mobileWorldContentPaths"][language], -1165 unwrapping="read", -1166 base=True, -1167 ) -1168 assert isinstance(resp, bytes) -1169 return resp -1170 -1171 async def download_manifest( -1172 self, -1173 language: str = "en", -1174 name: str = "manifest", -1175 path: typing.Union[pathlib.Path, str] = ".", -1176 *, -1177 force: bool = False, -1178 ) -> None: -1179 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1180 complete_path = _get_path(name, path, sql=True) -1181 -1182 if complete_path.exists() and force: -1183 if force: -1184 _LOG.info( -1185 f"Found manifest in {complete_path!s}. Forcing to Re-Download." -1186 ) -1187 complete_path.unlink(missing_ok=True) -1188 -1189 return await self.download_manifest(language, name, path, force=force) + 964 async def fetch_groups_for_member( + 965 self, + 966 member_id: int, + 967 member_type: typedefs.IntAnd[enums.MembershipType], + 968 /, + 969 *, + 970 filter: int = 0, + 971 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, + 972 ) -> typedefs.JSONObject: + 973 resp = await self._request( + 974 RequestMethod.GET, + 975 f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", + 976 ) + 977 assert isinstance(resp, dict) + 978 return resp + 979 + 980 async def fetch_potential_groups_for_member( + 981 self, + 982 member_id: int, + 983 member_type: typedefs.IntAnd[enums.MembershipType], + 984 /, + 985 *, + 986 filter: int = 0, + 987 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, + 988 ) -> typedefs.JSONObject: + 989 resp = await self._request( + 990 RequestMethod.GET, + 991 f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", + 992 ) + 993 assert isinstance(resp, dict) + 994 return resp + 995 + 996 async def fetch_clan_members( + 997 self, + 998 clan_id: int, + 999 /, +1000 *, +1001 name: typing.Optional[str] = None, +1002 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, +1003 ) -> typedefs.JSONObject: +1004 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1005 resp = await self._request( +1006 RequestMethod.GET, +1007 f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}&currentpage=1", +1008 ) +1009 assert isinstance(resp, dict) +1010 return resp +1011 +1012 async def fetch_hardlinked_credentials( +1013 self, +1014 credential: int, +1015 type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID, +1016 /, +1017 ) -> typedefs.JSONObject: +1018 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1019 resp = await self._request( +1020 RequestMethod.GET, +1021 f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/", +1022 ) +1023 assert isinstance(resp, dict) +1024 return resp +1025 +1026 async def fetch_user_credentials( +1027 self, access_token: str, membership_id: int, / +1028 ) -> typedefs.JSONArray: +1029 resp = await self._request( +1030 RequestMethod.GET, +1031 f"User/GetCredentialTypesForTargetAccount/{membership_id}", +1032 auth=access_token, +1033 ) +1034 assert isinstance(resp, list) +1035 return resp +1036 +1037 async def insert_socket_plug( +1038 self, +1039 action_token: str, +1040 /, +1041 instance_id: int, +1042 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], +1043 character_id: int, +1044 membership_type: typedefs.IntAnd[enums.MembershipType], +1045 ) -> typedefs.JSONObject: +1046 +1047 if isinstance(plug, builders.PlugSocketBuilder): +1048 plug = plug.collect() +1049 +1050 body = { +1051 "actionToken": action_token, +1052 "itemInstanceId": instance_id, +1053 "plug": plug, +1054 "characterId": character_id, +1055 "membershipType": int(membership_type), +1056 } +1057 resp = await self._request( +1058 RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body +1059 ) +1060 assert isinstance(resp, dict) +1061 return resp +1062 +1063 async def insert_socket_plug_free( +1064 self, +1065 access_token: str, +1066 /, +1067 instance_id: int, +1068 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], +1069 character_id: int, +1070 membership_type: typedefs.IntAnd[enums.MembershipType], +1071 ) -> typedefs.JSONObject: +1072 +1073 if isinstance(plug, builders.PlugSocketBuilder): +1074 plug = plug.collect() +1075 +1076 body = { +1077 "itemInstanceId": instance_id, +1078 "plug": plug, +1079 "characterId": character_id, +1080 "membershipType": int(membership_type), +1081 } +1082 resp = await self._request( +1083 RequestMethod.POST, +1084 "Destiny2/Actions/Items/InsertSocketPlugFree", +1085 json=body, +1086 auth=access_token, +1087 ) +1088 assert isinstance(resp, dict) +1089 return resp +1090 +1091 async def set_item_lock_state( +1092 self, +1093 access_token: str, +1094 state: bool, +1095 /, +1096 item_id: int, +1097 character_id: int, +1098 membership_type: typedefs.IntAnd[enums.MembershipType], +1099 ) -> int: +1100 body = { +1101 "state": state, +1102 "itemId": item_id, +1103 "characterId": character_id, +1104 "membership_type": int(membership_type), +1105 } +1106 response = await self._request( +1107 RequestMethod.POST, +1108 "Destiny2/Actions/Items/SetLockState", +1109 json=body, +1110 auth=access_token, +1111 ) +1112 assert isinstance(response, int) +1113 return response +1114 +1115 async def set_quest_track_state( +1116 self, +1117 access_token: str, +1118 state: bool, +1119 /, +1120 item_id: int, +1121 character_id: int, +1122 membership_type: typedefs.IntAnd[enums.MembershipType], +1123 ) -> int: +1124 body = { +1125 "state": state, +1126 "itemId": item_id, +1127 "characterId": character_id, +1128 "membership_type": int(membership_type), +1129 } +1130 response = await self._request( +1131 RequestMethod.POST, +1132 "Destiny2/Actions/Items/SetTrackedState", +1133 json=body, +1134 auth=access_token, +1135 ) +1136 assert isinstance(response, int) +1137 return response +1138 +1139 async def fetch_manifest_path(self) -> typedefs.JSONObject: +1140 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1141 path = await self._request(RequestMethod.GET, "Destiny2/Manifest") +1142 assert isinstance(path, dict) +1143 return path +1144 +1145 async def read_manifest_bytes(self, language: str = "en", /) -> bytes: +1146 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1147 _ensure_manifest_language(language) +1148 +1149 content = await self.fetch_manifest_path() +1150 resp = await self._request( +1151 RequestMethod.GET, +1152 content["mobileWorldContentPaths"][language], +1153 unwrapping="read", +1154 base=True, +1155 ) +1156 assert isinstance(resp, bytes) +1157 return resp +1158 +1159 async def download_manifest( +1160 self, +1161 language: str = "en", +1162 name: str = "manifest", +1163 path: typing.Union[pathlib.Path, str] = ".", +1164 *, +1165 force: bool = False, +1166 ) -> None: +1167 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1168 complete_path = _get_path(name, path, sql=True) +1169 +1170 if complete_path.exists() and force: +1171 if force: +1172 _LOG.info( +1173 f"Found manifest in {complete_path!s}. Forcing to Re-Download." +1174 ) +1175 complete_path.unlink(missing_ok=True) +1176 +1177 return await self.download_manifest(language, name, path, force=force) +1178 +1179 else: +1180 raise FileExistsError( +1181 "Manifest file already exists, " +1182 "To force download, set the `force` parameter to `True`." +1183 ) +1184 +1185 _LOG.info(f"Downloading manifest. Location: {complete_path!s}") +1186 data_bytes = await self.read_manifest_bytes(language) +1187 await asyncio.get_running_loop().run_in_executor( +1188 None, _write_sqlite_bytes, data_bytes, path, name +1189 ) 1190 -1191 else: -1192 raise FileExistsError( -1193 "Manifest file already exists, " -1194 "To force download, set the `force` parameter to `True`." -1195 ) -1196 -1197 _LOG.info(f"Downloading manifest. Location: {complete_path!s}") -1198 data_bytes = await self.read_manifest_bytes(language) -1199 await asyncio.get_running_loop().run_in_executor( -1200 None, _write_sqlite_bytes, data_bytes, path, name -1201 ) -1202 -1203 async def download_json_manifest( -1204 self, -1205 file_name: str = "manifest", -1206 path: typing.Union[str, pathlib.Path] = ".", -1207 language: str = "en", -1208 ) -> None: -1209 _ensure_manifest_language(language) -1210 -1211 _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...") -1212 -1213 content = await self.fetch_manifest_path() -1214 json_bytes = await self._request( -1215 RequestMethod.GET, -1216 content["jsonWorldContentPaths"][language], -1217 unwrapping="read", -1218 base=True, -1219 ) -1220 -1221 await asyncio.get_running_loop().run_in_executor( -1222 None, _write_json_bytes, json_bytes, file_name, path -1223 ) -1224 _LOG.info("Finished downloading manifest JSON.") -1225 -1226 async def fetch_manifest_version(self) -> str: -1227 return typing.cast(str, (await self.fetch_manifest_path())["version"]) -1228 -1229 async def fetch_linked_profiles( -1230 self, -1231 member_id: int, -1232 member_type: typedefs.IntAnd[enums.MembershipType], -1233 /, -1234 *, -1235 all: bool = False, -1236 ) -> typedefs.JSONObject: -1237 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1238 resp = await self._request( -1239 RequestMethod.GET, -1240 f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}", -1241 ) -1242 assert isinstance(resp, dict) -1243 return resp -1244 -1245 async def fetch_clan_banners(self) -> typedefs.JSONObject: -1246 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1247 resp = await self._request( -1248 RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/" -1249 ) -1250 assert isinstance(resp, dict) -1251 return resp -1252 -1253 async def fetch_public_milestones(self) -> typedefs.JSONObject: -1254 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1255 resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/") -1256 assert isinstance(resp, dict) -1257 return resp -1258 -1259 async def fetch_public_milestone_content( -1260 self, milestone_hash: int, / -1261 ) -> typedefs.JSONObject: -1262 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1263 resp = await self._request( -1264 RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/" +1191 async def download_json_manifest( +1192 self, +1193 file_name: str = "manifest", +1194 path: typing.Union[str, pathlib.Path] = ".", +1195 language: str = "en", +1196 ) -> None: +1197 _ensure_manifest_language(language) +1198 +1199 _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...") +1200 +1201 content = await self.fetch_manifest_path() +1202 json_bytes = await self._request( +1203 RequestMethod.GET, +1204 content["jsonWorldContentPaths"][language], +1205 unwrapping="read", +1206 base=True, +1207 ) +1208 +1209 await asyncio.get_running_loop().run_in_executor( +1210 None, _write_json_bytes, json_bytes, file_name, path +1211 ) +1212 _LOG.info("Finished downloading manifest JSON.") +1213 +1214 async def fetch_manifest_version(self) -> str: +1215 return typing.cast(str, (await self.fetch_manifest_path())["version"]) +1216 +1217 async def fetch_linked_profiles( +1218 self, +1219 member_id: int, +1220 member_type: typedefs.IntAnd[enums.MembershipType], +1221 /, +1222 *, +1223 all: bool = False, +1224 ) -> typedefs.JSONObject: +1225 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1226 resp = await self._request( +1227 RequestMethod.GET, +1228 f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}", +1229 ) +1230 assert isinstance(resp, dict) +1231 return resp +1232 +1233 async def fetch_clan_banners(self) -> typedefs.JSONObject: +1234 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1235 resp = await self._request( +1236 RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/" +1237 ) +1238 assert isinstance(resp, dict) +1239 return resp +1240 +1241 async def fetch_public_milestones(self) -> typedefs.JSONObject: +1242 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1243 resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/") +1244 assert isinstance(resp, dict) +1245 return resp +1246 +1247 async def fetch_public_milestone_content( +1248 self, milestone_hash: int, / +1249 ) -> typedefs.JSONObject: +1250 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1251 resp = await self._request( +1252 RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/" +1253 ) +1254 assert isinstance(resp, dict) +1255 return resp +1256 +1257 async def fetch_current_user_memberships( +1258 self, access_token: str, / +1259 ) -> typedefs.JSONObject: +1260 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1261 resp = await self._request( +1262 RequestMethod.GET, +1263 "User/GetMembershipsForCurrentUser/", +1264 auth=access_token, 1265 ) 1266 assert isinstance(resp, dict) 1267 return resp 1268 -1269 async def fetch_current_user_memberships( -1270 self, access_token: str, / -1271 ) -> typedefs.JSONObject: -1272 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1273 resp = await self._request( -1274 RequestMethod.GET, -1275 "User/GetMembershipsForCurrentUser/", -1276 auth=access_token, -1277 ) -1278 assert isinstance(resp, dict) -1279 return resp -1280 -1281 async def equip_item( -1282 self, -1283 access_token: str, -1284 /, -1285 item_id: int, -1286 character_id: int, -1287 membership_type: typedefs.IntAnd[enums.MembershipType], -1288 ) -> None: -1289 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1290 payload = { -1291 "itemId": item_id, -1292 "characterId": character_id, -1293 "membershipType": int(membership_type), -1294 } -1295 -1296 await self._request( -1297 RequestMethod.POST, -1298 "Destiny2/Actions/Items/EquipItem/", -1299 json=payload, -1300 auth=access_token, -1301 ) -1302 -1303 async def equip_items( -1304 self, -1305 access_token: str, -1306 /, -1307 item_ids: list[int], -1308 character_id: int, -1309 membership_type: typedefs.IntAnd[enums.MembershipType], -1310 ) -> None: -1311 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1312 payload = { -1313 "itemIds": item_ids, -1314 "characterId": character_id, -1315 "membershipType": int(membership_type), -1316 } -1317 await self._request( -1318 RequestMethod.POST, -1319 "Destiny2/Actions/Items/EquipItems/", -1320 json=payload, -1321 auth=access_token, -1322 ) -1323 -1324 async def ban_clan_member( -1325 self, -1326 access_token: str, -1327 /, -1328 group_id: int, -1329 membership_id: int, -1330 membership_type: typedefs.IntAnd[enums.MembershipType], -1331 *, -1332 length: int = 0, -1333 comment: undefined.UndefinedOr[str] = undefined.Undefined, -1334 ) -> None: -1335 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1336 payload = {"comment": str(comment), "length": length} -1337 await self._request( -1338 RequestMethod.POST, -1339 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/", -1340 json=payload, -1341 auth=access_token, -1342 ) -1343 -1344 async def unban_clan_member( -1345 self, -1346 access_token: str, -1347 /, -1348 group_id: int, -1349 membership_id: int, -1350 membership_type: typedefs.IntAnd[enums.MembershipType], -1351 ) -> None: -1352 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1353 await self._request( -1354 RequestMethod.POST, -1355 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/", -1356 auth=access_token, -1357 ) -1358 -1359 async def kick_clan_member( -1360 self, -1361 access_token: str, -1362 /, -1363 group_id: int, -1364 membership_id: int, -1365 membership_type: typedefs.IntAnd[enums.MembershipType], -1366 ) -> typedefs.JSONObject: -1367 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1368 resp = await self._request( -1369 RequestMethod.POST, -1370 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/", -1371 auth=access_token, -1372 ) -1373 assert isinstance(resp, dict) -1374 return resp -1375 -1376 async def edit_clan( -1377 self, -1378 access_token: str, -1379 /, -1380 group_id: int, -1381 *, -1382 name: typedefs.NoneOr[str] = None, -1383 about: typedefs.NoneOr[str] = None, -1384 motto: typedefs.NoneOr[str] = None, -1385 theme: typedefs.NoneOr[str] = None, -1386 tags: typedefs.NoneOr[collections.Sequence[str]] = None, -1387 is_public: typedefs.NoneOr[bool] = None, -1388 locale: typedefs.NoneOr[str] = None, -1389 avatar_image_index: typedefs.NoneOr[int] = None, -1390 membership_option: typedefs.NoneOr[ -1391 typedefs.IntAnd[enums.MembershipOption] -1392 ] = None, -1393 allow_chat: typedefs.NoneOr[bool] = None, -1394 chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None, -1395 call_sign: typedefs.NoneOr[str] = None, -1396 homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, -1397 enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None, -1398 default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, -1399 is_public_topic_admin: typedefs.NoneOr[bool] = None, -1400 ) -> None: -1401 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1402 payload = { -1403 "name": name, -1404 "about": about, -1405 "motto": motto, -1406 "theme": theme, -1407 "tags": tags, -1408 "isPublic": is_public, -1409 "avatarImageIndex": avatar_image_index, -1410 "isPublicTopicAdminOnly": is_public_topic_admin, -1411 "allowChat": allow_chat, -1412 "chatSecurity": chat_security, -1413 "callsign": call_sign, -1414 "homepage": homepage, -1415 "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins, -1416 "defaultPublicity": default_publicity, -1417 "locale": locale, -1418 } -1419 if membership_option is not None: -1420 payload["membershipOption"] = int(membership_option) -1421 -1422 await self._request( -1423 RequestMethod.POST, -1424 f"GroupV2/{group_id}/Edit", -1425 json=payload, -1426 auth=access_token, -1427 ) -1428 -1429 async def edit_clan_options( -1430 self, -1431 access_token: str, -1432 /, -1433 group_id: int, -1434 *, -1435 invite_permissions_override: typedefs.NoneOr[bool] = None, -1436 update_culture_permissionOverride: typedefs.NoneOr[bool] = None, -1437 host_guided_game_permission_override: typedefs.NoneOr[ -1438 typing.Literal[0, 1, 2] -1439 ] = None, -1440 update_banner_permission_override: typedefs.NoneOr[bool] = None, -1441 join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None, -1442 ) -> None: -1443 -1444 payload = { -1445 "InvitePermissionOverride": invite_permissions_override, -1446 "UpdateCulturePermissionOverride": update_culture_permissionOverride, -1447 "HostGuidedGamePermissionOverride": host_guided_game_permission_override, -1448 "UpdateBannerPermissionOverride": update_banner_permission_override, -1449 "JoinLevel": int(join_level) if join_level else None, -1450 } -1451 -1452 await self._request( -1453 RequestMethod.POST, -1454 f"GroupV2/{group_id}/EditFounderOptions", -1455 json=payload, -1456 auth=access_token, -1457 ) -1458 -1459 async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject: -1460 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1461 resp = await self._request( -1462 RequestMethod.GET, -1463 "Social/Friends/", -1464 auth=access_token, -1465 ) -1466 assert isinstance(resp, dict) -1467 return resp -1468 -1469 async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject: -1470 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1471 resp = await self._request( -1472 RequestMethod.GET, -1473 "Social/Friends/Requests", -1474 auth=access_token, -1475 ) -1476 assert isinstance(resp, dict) -1477 return resp -1478 -1479 async def accept_friend_request(self, access_token: str, /, member_id: int) -> None: -1480 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1481 await self._request( -1482 RequestMethod.POST, -1483 f"Social/Friends/Requests/Accept/{member_id}", -1484 auth=access_token, -1485 ) -1486 -1487 async def send_friend_request(self, access_token: str, /, member_id: int) -> None: -1488 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1489 await self._request( -1490 RequestMethod.POST, -1491 f"Social/Friends/Add/{member_id}", -1492 auth=access_token, -1493 ) -1494 -1495 async def decline_friend_request( -1496 self, access_token: str, /, member_id: int -1497 ) -> None: -1498 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1499 await self._request( -1500 RequestMethod.POST, -1501 f"Social/Friends/Requests/Decline/{member_id}", -1502 auth=access_token, -1503 ) -1504 -1505 async def remove_friend(self, access_token: str, /, member_id: int) -> None: -1506 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1507 await self._request( -1508 RequestMethod.POST, -1509 f"Social/Friends/Remove/{member_id}", -1510 auth=access_token, -1511 ) -1512 -1513 async def remove_friend_request(self, access_token: str, /, member_id: int) -> None: -1514 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> -1515 await self._request( -1516 RequestMethod.POST, -1517 f"Social/Friends/Requests/Remove/{member_id}", -1518 auth=access_token, -1519 ) -1520 -1521 async def approve_all_pending_group_users( -1522 self, -1523 access_token: str, -1524 /, -1525 group_id: int, -1526 message: undefined.UndefinedOr[str] = undefined.Undefined, -1527 ) -> None: -1528 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> -1529 await self._request( -1530 RequestMethod.POST, -1531 f"GroupV2/{group_id}/Members/ApproveAll", -1532 auth=access_token, -1533 json={"message": str(message)}, -1534 ) -1535 -1536 async def deny_all_pending_group_users( -1537 self, -1538 access_token: str, -1539 /, -1540 group_id: int, -1541 *, -1542 message: undefined.UndefinedOr[str] = undefined.Undefined, -1543 ) -> None: -1544 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> -1545 await self._request( -1546 RequestMethod.POST, -1547 f"GroupV2/{group_id}/Members/DenyAll", -1548 auth=access_token, -1549 json={"message": str(message)}, -1550 ) -1551 -1552 async def add_optional_conversation( -1553 self, -1554 access_token: str, -1555 /, -1556 group_id: int, -1557 *, -1558 name: undefined.UndefinedOr[str] = undefined.Undefined, -1559 security: typing.Literal[0, 1] = 0, -1560 ) -> None: -1561 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> -1562 payload = {"chatName": str(name), "chatSecurity": security} -1563 await self._request( -1564 RequestMethod.POST, -1565 f"GroupV2/{group_id}/OptionalConversations/Add", -1566 json=payload, -1567 auth=access_token, -1568 ) -1569 -1570 async def edit_optional_conversation( -1571 self, -1572 access_token: str, -1573 /, -1574 group_id: int, -1575 conversation_id: int, -1576 *, -1577 name: undefined.UndefinedOr[str] = undefined.Undefined, -1578 security: typing.Literal[0, 1] = 0, -1579 enable_chat: bool = False, -1580 ) -> None: -1581 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> -1582 payload = { -1583 "chatEnabled": enable_chat, -1584 "chatName": str(name), -1585 "chatSecurity": security, -1586 } -1587 await self._request( -1588 RequestMethod.POST, -1589 f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}", -1590 json=payload, -1591 auth=access_token, -1592 ) -1593 -1594 async def transfer_item( -1595 self, -1596 access_token: str, -1597 /, -1598 item_id: int, -1599 item_hash: int, -1600 character_id: int, -1601 member_type: typedefs.IntAnd[enums.MembershipType], -1602 *, -1603 stack_size: int = 1, -1604 vault: bool = False, -1605 ) -> None: -1606 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> -1607 payload = { -1608 "characterId": character_id, -1609 "membershipType": int(member_type), -1610 "itemId": item_id, -1611 "itemReferenceHash": item_hash, -1612 "stackSize": stack_size, -1613 "transferToVault": vault, -1614 } -1615 await self._request( -1616 RequestMethod.POST, -1617 "Destiny2/Actions/Items/TransferItem", -1618 json=payload, -1619 auth=access_token, -1620 ) -1621 -1622 async def pull_item( -1623 self, -1624 access_token: str, -1625 /, -1626 item_id: int, -1627 item_hash: int, -1628 character_id: int, -1629 member_type: typedefs.IntAnd[enums.MembershipType], -1630 *, -1631 stack_size: int = 1, -1632 vault: bool = False, -1633 ) -> None: -1634 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> -1635 payload = { -1636 "characterId": character_id, -1637 "membershipType": int(member_type), -1638 "itemId": item_id, -1639 "itemReferenceHash": item_hash, -1640 "stackSize": stack_size, -1641 "transferToVault": vault, -1642 } -1643 await self._request( -1644 RequestMethod.POST, -1645 "Destiny2/Actions/Items/PullFromPostmaster", -1646 json=payload, -1647 auth=access_token, -1648 ) -1649 -1650 async def fetch_fireteams( -1651 self, -1652 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], -1653 *, -1654 platform: typedefs.IntAnd[ -1655 fireteams.FireteamPlatform -1656 ] = fireteams.FireteamPlatform.ANY, -1657 language: typing.Union[ -1658 fireteams.FireteamLanguage, str -1659 ] = fireteams.FireteamLanguage.ALL, -1660 date_range: typedefs.IntAnd[ -1661 fireteams.FireteamDate -1662 ] = fireteams.FireteamDate.ALL, -1663 page: int = 0, -1664 slots_filter: int = 0, -1665 ) -> typedefs.JSONObject: -1666 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1667 resp = await self._request( -1668 RequestMethod.GET, -1669 f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}", # noqa: E501 Line too long -1670 ) -1671 assert isinstance(resp, dict) -1672 return resp -1673 -1674 async def fetch_avaliable_clan_fireteams( -1675 self, -1676 access_token: str, -1677 group_id: int, -1678 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], -1679 *, -1680 platform: typedefs.IntAnd[fireteams.FireteamPlatform], -1681 language: typing.Union[fireteams.FireteamLanguage, str], -1682 date_range: typedefs.IntAnd[ -1683 fireteams.FireteamDate -1684 ] = fireteams.FireteamDate.ALL, -1685 page: int = 0, -1686 public_only: bool = False, -1687 slots_filter: int = 0, -1688 ) -> typedefs.JSONObject: -1689 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1690 resp = await self._request( -1691 RequestMethod.GET, -1692 f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}", # noqa: E501 -1693 json={"langFilter": str(language)}, +1269 async def equip_item( +1270 self, +1271 access_token: str, +1272 /, +1273 item_id: int, +1274 character_id: int, +1275 membership_type: typedefs.IntAnd[enums.MembershipType], +1276 ) -> None: +1277 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1278 payload = { +1279 "itemId": item_id, +1280 "characterId": character_id, +1281 "membershipType": int(membership_type), +1282 } +1283 +1284 await self._request( +1285 RequestMethod.POST, +1286 "Destiny2/Actions/Items/EquipItem/", +1287 json=payload, +1288 auth=access_token, +1289 ) +1290 +1291 async def equip_items( +1292 self, +1293 access_token: str, +1294 /, +1295 item_ids: list[int], +1296 character_id: int, +1297 membership_type: typedefs.IntAnd[enums.MembershipType], +1298 ) -> None: +1299 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1300 payload = { +1301 "itemIds": item_ids, +1302 "characterId": character_id, +1303 "membershipType": int(membership_type), +1304 } +1305 await self._request( +1306 RequestMethod.POST, +1307 "Destiny2/Actions/Items/EquipItems/", +1308 json=payload, +1309 auth=access_token, +1310 ) +1311 +1312 async def ban_clan_member( +1313 self, +1314 access_token: str, +1315 /, +1316 group_id: int, +1317 membership_id: int, +1318 membership_type: typedefs.IntAnd[enums.MembershipType], +1319 *, +1320 length: int = 0, +1321 comment: undefined.UndefinedOr[str] = undefined.Undefined, +1322 ) -> None: +1323 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1324 payload = {"comment": str(comment), "length": length} +1325 await self._request( +1326 RequestMethod.POST, +1327 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/", +1328 json=payload, +1329 auth=access_token, +1330 ) +1331 +1332 async def unban_clan_member( +1333 self, +1334 access_token: str, +1335 /, +1336 group_id: int, +1337 membership_id: int, +1338 membership_type: typedefs.IntAnd[enums.MembershipType], +1339 ) -> None: +1340 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1341 await self._request( +1342 RequestMethod.POST, +1343 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/", +1344 auth=access_token, +1345 ) +1346 +1347 async def kick_clan_member( +1348 self, +1349 access_token: str, +1350 /, +1351 group_id: int, +1352 membership_id: int, +1353 membership_type: typedefs.IntAnd[enums.MembershipType], +1354 ) -> typedefs.JSONObject: +1355 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1356 resp = await self._request( +1357 RequestMethod.POST, +1358 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/", +1359 auth=access_token, +1360 ) +1361 assert isinstance(resp, dict) +1362 return resp +1363 +1364 async def edit_clan( +1365 self, +1366 access_token: str, +1367 /, +1368 group_id: int, +1369 *, +1370 name: typedefs.NoneOr[str] = None, +1371 about: typedefs.NoneOr[str] = None, +1372 motto: typedefs.NoneOr[str] = None, +1373 theme: typedefs.NoneOr[str] = None, +1374 tags: typedefs.NoneOr[collections.Sequence[str]] = None, +1375 is_public: typedefs.NoneOr[bool] = None, +1376 locale: typedefs.NoneOr[str] = None, +1377 avatar_image_index: typedefs.NoneOr[int] = None, +1378 membership_option: typedefs.NoneOr[ +1379 typedefs.IntAnd[enums.MembershipOption] +1380 ] = None, +1381 allow_chat: typedefs.NoneOr[bool] = None, +1382 chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None, +1383 call_sign: typedefs.NoneOr[str] = None, +1384 homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, +1385 enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None, +1386 default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, +1387 is_public_topic_admin: typedefs.NoneOr[bool] = None, +1388 ) -> None: +1389 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1390 payload = { +1391 "name": name, +1392 "about": about, +1393 "motto": motto, +1394 "theme": theme, +1395 "tags": tags, +1396 "isPublic": is_public, +1397 "avatarImageIndex": avatar_image_index, +1398 "isPublicTopicAdminOnly": is_public_topic_admin, +1399 "allowChat": allow_chat, +1400 "chatSecurity": chat_security, +1401 "callsign": call_sign, +1402 "homepage": homepage, +1403 "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins, +1404 "defaultPublicity": default_publicity, +1405 "locale": locale, +1406 } +1407 if membership_option is not None: +1408 payload["membershipOption"] = int(membership_option) +1409 +1410 await self._request( +1411 RequestMethod.POST, +1412 f"GroupV2/{group_id}/Edit", +1413 json=payload, +1414 auth=access_token, +1415 ) +1416 +1417 async def edit_clan_options( +1418 self, +1419 access_token: str, +1420 /, +1421 group_id: int, +1422 *, +1423 invite_permissions_override: typedefs.NoneOr[bool] = None, +1424 update_culture_permissionOverride: typedefs.NoneOr[bool] = None, +1425 host_guided_game_permission_override: typedefs.NoneOr[ +1426 typing.Literal[0, 1, 2] +1427 ] = None, +1428 update_banner_permission_override: typedefs.NoneOr[bool] = None, +1429 join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None, +1430 ) -> None: +1431 +1432 payload = { +1433 "InvitePermissionOverride": invite_permissions_override, +1434 "UpdateCulturePermissionOverride": update_culture_permissionOverride, +1435 "HostGuidedGamePermissionOverride": host_guided_game_permission_override, +1436 "UpdateBannerPermissionOverride": update_banner_permission_override, +1437 "JoinLevel": int(join_level) if join_level else None, +1438 } +1439 +1440 await self._request( +1441 RequestMethod.POST, +1442 f"GroupV2/{group_id}/EditFounderOptions", +1443 json=payload, +1444 auth=access_token, +1445 ) +1446 +1447 async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject: +1448 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1449 resp = await self._request( +1450 RequestMethod.GET, +1451 "Social/Friends/", +1452 auth=access_token, +1453 ) +1454 assert isinstance(resp, dict) +1455 return resp +1456 +1457 async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject: +1458 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1459 resp = await self._request( +1460 RequestMethod.GET, +1461 "Social/Friends/Requests", +1462 auth=access_token, +1463 ) +1464 assert isinstance(resp, dict) +1465 return resp +1466 +1467 async def accept_friend_request(self, access_token: str, /, member_id: int) -> None: +1468 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1469 await self._request( +1470 RequestMethod.POST, +1471 f"Social/Friends/Requests/Accept/{member_id}", +1472 auth=access_token, +1473 ) +1474 +1475 async def send_friend_request(self, access_token: str, /, member_id: int) -> None: +1476 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1477 await self._request( +1478 RequestMethod.POST, +1479 f"Social/Friends/Add/{member_id}", +1480 auth=access_token, +1481 ) +1482 +1483 async def decline_friend_request( +1484 self, access_token: str, /, member_id: int +1485 ) -> None: +1486 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1487 await self._request( +1488 RequestMethod.POST, +1489 f"Social/Friends/Requests/Decline/{member_id}", +1490 auth=access_token, +1491 ) +1492 +1493 async def remove_friend(self, access_token: str, /, member_id: int) -> None: +1494 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1495 await self._request( +1496 RequestMethod.POST, +1497 f"Social/Friends/Remove/{member_id}", +1498 auth=access_token, +1499 ) +1500 +1501 async def remove_friend_request(self, access_token: str, /, member_id: int) -> None: +1502 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> +1503 await self._request( +1504 RequestMethod.POST, +1505 f"Social/Friends/Requests/Remove/{member_id}", +1506 auth=access_token, +1507 ) +1508 +1509 async def approve_all_pending_group_users( +1510 self, +1511 access_token: str, +1512 /, +1513 group_id: int, +1514 message: undefined.UndefinedOr[str] = undefined.Undefined, +1515 ) -> None: +1516 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> +1517 await self._request( +1518 RequestMethod.POST, +1519 f"GroupV2/{group_id}/Members/ApproveAll", +1520 auth=access_token, +1521 json={"message": str(message)}, +1522 ) +1523 +1524 async def deny_all_pending_group_users( +1525 self, +1526 access_token: str, +1527 /, +1528 group_id: int, +1529 *, +1530 message: undefined.UndefinedOr[str] = undefined.Undefined, +1531 ) -> None: +1532 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> +1533 await self._request( +1534 RequestMethod.POST, +1535 f"GroupV2/{group_id}/Members/DenyAll", +1536 auth=access_token, +1537 json={"message": str(message)}, +1538 ) +1539 +1540 async def add_optional_conversation( +1541 self, +1542 access_token: str, +1543 /, +1544 group_id: int, +1545 *, +1546 name: undefined.UndefinedOr[str] = undefined.Undefined, +1547 security: typing.Literal[0, 1] = 0, +1548 ) -> None: +1549 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> +1550 payload = {"chatName": str(name), "chatSecurity": security} +1551 await self._request( +1552 RequestMethod.POST, +1553 f"GroupV2/{group_id}/OptionalConversations/Add", +1554 json=payload, +1555 auth=access_token, +1556 ) +1557 +1558 async def edit_optional_conversation( +1559 self, +1560 access_token: str, +1561 /, +1562 group_id: int, +1563 conversation_id: int, +1564 *, +1565 name: undefined.UndefinedOr[str] = undefined.Undefined, +1566 security: typing.Literal[0, 1] = 0, +1567 enable_chat: bool = False, +1568 ) -> None: +1569 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> +1570 payload = { +1571 "chatEnabled": enable_chat, +1572 "chatName": str(name), +1573 "chatSecurity": security, +1574 } +1575 await self._request( +1576 RequestMethod.POST, +1577 f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}", +1578 json=payload, +1579 auth=access_token, +1580 ) +1581 +1582 async def transfer_item( +1583 self, +1584 access_token: str, +1585 /, +1586 item_id: int, +1587 item_hash: int, +1588 character_id: int, +1589 member_type: typedefs.IntAnd[enums.MembershipType], +1590 *, +1591 stack_size: int = 1, +1592 vault: bool = False, +1593 ) -> None: +1594 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> +1595 payload = { +1596 "characterId": character_id, +1597 "membershipType": int(member_type), +1598 "itemId": item_id, +1599 "itemReferenceHash": item_hash, +1600 "stackSize": stack_size, +1601 "transferToVault": vault, +1602 } +1603 await self._request( +1604 RequestMethod.POST, +1605 "Destiny2/Actions/Items/TransferItem", +1606 json=payload, +1607 auth=access_token, +1608 ) +1609 +1610 async def pull_item( +1611 self, +1612 access_token: str, +1613 /, +1614 item_id: int, +1615 item_hash: int, +1616 character_id: int, +1617 member_type: typedefs.IntAnd[enums.MembershipType], +1618 *, +1619 stack_size: int = 1, +1620 vault: bool = False, +1621 ) -> None: +1622 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> +1623 payload = { +1624 "characterId": character_id, +1625 "membershipType": int(member_type), +1626 "itemId": item_id, +1627 "itemReferenceHash": item_hash, +1628 "stackSize": stack_size, +1629 "transferToVault": vault, +1630 } +1631 await self._request( +1632 RequestMethod.POST, +1633 "Destiny2/Actions/Items/PullFromPostmaster", +1634 json=payload, +1635 auth=access_token, +1636 ) +1637 +1638 async def fetch_fireteams( +1639 self, +1640 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], +1641 *, +1642 platform: typedefs.IntAnd[ +1643 fireteams.FireteamPlatform +1644 ] = fireteams.FireteamPlatform.ANY, +1645 language: typing.Union[ +1646 fireteams.FireteamLanguage, str +1647 ] = fireteams.FireteamLanguage.ALL, +1648 date_range: typedefs.IntAnd[ +1649 fireteams.FireteamDate +1650 ] = fireteams.FireteamDate.ALL, +1651 page: int = 0, +1652 slots_filter: int = 0, +1653 ) -> typedefs.JSONObject: +1654 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1655 resp = await self._request( +1656 RequestMethod.GET, +1657 f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}", # noqa: E501 Line too long +1658 ) +1659 assert isinstance(resp, dict) +1660 return resp +1661 +1662 async def fetch_avaliable_clan_fireteams( +1663 self, +1664 access_token: str, +1665 group_id: int, +1666 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], +1667 *, +1668 platform: typedefs.IntAnd[fireteams.FireteamPlatform], +1669 language: typing.Union[fireteams.FireteamLanguage, str], +1670 date_range: typedefs.IntAnd[ +1671 fireteams.FireteamDate +1672 ] = fireteams.FireteamDate.ALL, +1673 page: int = 0, +1674 public_only: bool = False, +1675 slots_filter: int = 0, +1676 ) -> typedefs.JSONObject: +1677 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1678 resp = await self._request( +1679 RequestMethod.GET, +1680 f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}", # noqa: E501 +1681 json={"langFilter": str(language)}, +1682 auth=access_token, +1683 ) +1684 assert isinstance(resp, dict) +1685 return resp +1686 +1687 async def fetch_clan_fireteam( +1688 self, access_token: str, fireteam_id: int, group_id: int +1689 ) -> typedefs.JSONObject: +1690 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1691 resp = await self._request( +1692 RequestMethod.GET, +1693 f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}", 1694 auth=access_token, 1695 ) 1696 assert isinstance(resp, dict) 1697 return resp 1698 -1699 async def fetch_clan_fireteam( -1700 self, access_token: str, fireteam_id: int, group_id: int -1701 ) -> typedefs.JSONObject: -1702 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1703 resp = await self._request( -1704 RequestMethod.GET, -1705 f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}", -1706 auth=access_token, -1707 ) -1708 assert isinstance(resp, dict) -1709 return resp -1710 -1711 async def fetch_my_clan_fireteams( -1712 self, -1713 access_token: str, -1714 group_id: int, -1715 *, -1716 include_closed: bool = True, -1717 platform: typedefs.IntAnd[fireteams.FireteamPlatform], -1718 language: typing.Union[fireteams.FireteamLanguage, str], -1719 filtered: bool = True, -1720 page: int = 0, -1721 ) -> typedefs.JSONObject: -1722 payload = {"groupFilter": filtered, "langFilter": str(language)} -1723 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1724 resp = await self._request( -1725 RequestMethod.GET, -1726 f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}", -1727 json=payload, +1699 async def fetch_my_clan_fireteams( +1700 self, +1701 access_token: str, +1702 group_id: int, +1703 *, +1704 include_closed: bool = True, +1705 platform: typedefs.IntAnd[fireteams.FireteamPlatform], +1706 language: typing.Union[fireteams.FireteamLanguage, str], +1707 filtered: bool = True, +1708 page: int = 0, +1709 ) -> typedefs.JSONObject: +1710 payload = {"groupFilter": filtered, "langFilter": str(language)} +1711 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1712 resp = await self._request( +1713 RequestMethod.GET, +1714 f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}", +1715 json=payload, +1716 auth=access_token, +1717 ) +1718 assert isinstance(resp, dict) +1719 return resp +1720 +1721 async def fetch_private_clan_fireteams( +1722 self, access_token: str, group_id: int, / +1723 ) -> int: +1724 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1725 resp = await self._request( +1726 RequestMethod.GET, +1727 f"Fireteam/Clan/{group_id}/ActiveCount", 1728 auth=access_token, 1729 ) -1730 assert isinstance(resp, dict) +1730 assert isinstance(resp, int) 1731 return resp 1732 -1733 async def fetch_private_clan_fireteams( -1734 self, access_token: str, group_id: int, / -1735 ) -> int: -1736 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1737 resp = await self._request( -1738 RequestMethod.GET, -1739 f"Fireteam/Clan/{group_id}/ActiveCount", -1740 auth=access_token, -1741 ) -1742 assert isinstance(resp, int) -1743 return resp -1744 -1745 async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject: -1746 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1747 resp = await self._request( -1748 RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}" +1733 async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject: +1734 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1735 resp = await self._request( +1736 RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}" +1737 ) +1738 assert isinstance(resp, dict) +1739 return resp +1740 +1741 async def search_entities( +1742 self, name: str, entity_type: str, *, page: int = 0 +1743 ) -> typedefs.JSONObject: +1744 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1745 resp = await self._request( +1746 RequestMethod.GET, +1747 f"Destiny2/Armory/Search/{entity_type}/{name}/", +1748 json={"page": page}, 1749 ) 1750 assert isinstance(resp, dict) 1751 return resp 1752 -1753 async def search_entities( -1754 self, name: str, entity_type: str, *, page: int = 0 -1755 ) -> typedefs.JSONObject: -1756 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1757 resp = await self._request( -1758 RequestMethod.GET, -1759 f"Destiny2/Armory/Search/{entity_type}/{name}/", -1760 json={"page": page}, -1761 ) -1762 assert isinstance(resp, dict) -1763 return resp -1764 -1765 async def fetch_unique_weapon_history( -1766 self, -1767 membership_id: int, -1768 character_id: int, -1769 membership_type: typedefs.IntAnd[enums.MembershipType], -1770 ) -> typedefs.JSONObject: -1771 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1772 resp = await self._request( -1773 RequestMethod.GET, -1774 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/", -1775 ) -1776 assert isinstance(resp, dict) -1777 return resp -1778 -1779 async def fetch_item( -1780 self, -1781 member_id: int, -1782 item_id: int, -1783 membership_type: typedefs.IntAnd[enums.MembershipType], -1784 components: list[enums.ComponentType], -1785 ) -> typedefs.JSONObject: -1786 collector = _collect_components(components) -1787 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1788 resp = await self._request( -1789 RequestMethod.GET, -1790 f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}", -1791 ) -1792 assert isinstance(resp, dict) -1793 return resp -1794 -1795 async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject: -1796 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1797 resp = await self._request( -1798 RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/" -1799 ) -1800 assert isinstance(resp, dict) -1801 return resp -1802 -1803 async def fetch_available_locales(self) -> typedefs.JSONObject: -1804 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1805 resp = await self._request( -1806 RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/" -1807 ) +1753 async def fetch_unique_weapon_history( +1754 self, +1755 membership_id: int, +1756 character_id: int, +1757 membership_type: typedefs.IntAnd[enums.MembershipType], +1758 ) -> typedefs.JSONObject: +1759 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1760 resp = await self._request( +1761 RequestMethod.GET, +1762 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/", +1763 ) +1764 assert isinstance(resp, dict) +1765 return resp +1766 +1767 async def fetch_item( +1768 self, +1769 member_id: int, +1770 item_id: int, +1771 membership_type: typedefs.IntAnd[enums.MembershipType], +1772 components: list[enums.ComponentType], +1773 ) -> typedefs.JSONObject: +1774 collector = _collect_components(components) +1775 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1776 resp = await self._request( +1777 RequestMethod.GET, +1778 f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}", +1779 ) +1780 assert isinstance(resp, dict) +1781 return resp +1782 +1783 async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject: +1784 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1785 resp = await self._request( +1786 RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/" +1787 ) +1788 assert isinstance(resp, dict) +1789 return resp +1790 +1791 async def fetch_available_locales(self) -> typedefs.JSONObject: +1792 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1793 resp = await self._request( +1794 RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/" +1795 ) +1796 assert isinstance(resp, dict) +1797 return resp +1798 +1799 async def fetch_common_settings(self) -> typedefs.JSONObject: +1800 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1801 resp = await self._request(RequestMethod.GET, "Settings") +1802 assert isinstance(resp, dict) +1803 return resp +1804 +1805 async def fetch_user_systems_overrides(self) -> typedefs.JSONObject: +1806 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1807 resp = await self._request(RequestMethod.GET, "UserSystemOverrides") 1808 assert isinstance(resp, dict) 1809 return resp 1810 -1811 async def fetch_common_settings(self) -> typedefs.JSONObject: -1812 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1813 resp = await self._request(RequestMethod.GET, "Settings") -1814 assert isinstance(resp, dict) -1815 return resp -1816 -1817 async def fetch_user_systems_overrides(self) -> typedefs.JSONObject: -1818 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1819 resp = await self._request(RequestMethod.GET, "UserSystemOverrides") -1820 assert isinstance(resp, dict) -1821 return resp -1822 -1823 async def fetch_global_alerts( -1824 self, *, include_streaming: bool = False -1825 ) -> typedefs.JSONArray: -1826 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1827 resp = await self._request( -1828 RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}" -1829 ) -1830 assert isinstance(resp, list) -1831 return resp +1811 async def fetch_global_alerts( +1812 self, *, include_streaming: bool = False +1813 ) -> typedefs.JSONArray: +1814 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1815 resp = await self._request( +1816 RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}" +1817 ) +1818 assert isinstance(resp, list) +1819 return resp +1820 +1821 async def awainitialize_request( +1822 self, +1823 access_token: str, +1824 type: typing.Literal[0, 1], +1825 membership_type: typedefs.IntAnd[enums.MembershipType], +1826 /, +1827 *, +1828 affected_item_id: typing.Optional[int] = None, +1829 character_id: typing.Optional[int] = None, +1830 ) -> typedefs.JSONObject: +1831 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1832 -1833 async def awainitialize_request( -1834 self, -1835 access_token: str, -1836 type: typing.Literal[0, 1], -1837 membership_type: typedefs.IntAnd[enums.MembershipType], -1838 /, -1839 *, -1840 affected_item_id: typing.Optional[int] = None, -1841 character_id: typing.Optional[int] = None, -1842 ) -> typedefs.JSONObject: -1843 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1844 -1845 body = {"type": type, "membershipType": int(membership_type)} +1833 body = {"type": type, "membershipType": int(membership_type)} +1834 +1835 if affected_item_id is not None: +1836 body["affectedItemId"] = affected_item_id +1837 +1838 if character_id is not None: +1839 body["characterId"] = character_id +1840 +1841 resp = await self._request( +1842 RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token +1843 ) +1844 assert isinstance(resp, dict) +1845 return resp 1846 -1847 if affected_item_id is not None: -1848 body["affectedItemId"] = affected_item_id -1849 -1850 if character_id is not None: -1851 body["characterId"] = character_id -1852 -1853 resp = await self._request( -1854 RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token +1847 async def awaget_action_token( +1848 self, access_token: str, correlation_id: str, / +1849 ) -> typedefs.JSONObject: +1850 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1851 resp = await self._request( +1852 RequestMethod.POST, +1853 f"Destiny2/Awa/GetActionToken/{correlation_id}", +1854 auth=access_token, 1855 ) 1856 assert isinstance(resp, dict) 1857 return resp 1858 -1859 async def awaget_action_token( -1860 self, access_token: str, correlation_id: str, / -1861 ) -> typedefs.JSONObject: -1862 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1863 resp = await self._request( -1864 RequestMethod.POST, -1865 f"Destiny2/Awa/GetActionToken/{correlation_id}", -1866 auth=access_token, -1867 ) -1868 assert isinstance(resp, dict) -1869 return resp -1870 -1871 async def awa_provide_authorization_result( -1872 self, -1873 access_token: str, -1874 selection: int, -1875 correlation_id: str, -1876 nonce: collections.MutableSequence[typing.Union[str, bytes]], -1877 ) -> int: -1878 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1879 -1880 body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce} -1881 -1882 resp = await self._request( -1883 RequestMethod.POST, -1884 "Destiny2/Awa/AwaProvideAuthorizationResult", -1885 json=body, -1886 auth=access_token, -1887 ) -1888 assert isinstance(resp, int) -1889 return resp -1890 -1891 async def fetch_vendors( -1892 self, -1893 access_token: str, -1894 character_id: int, -1895 membership_id: int, -1896 membership_type: typedefs.IntAnd[enums.MembershipType], -1897 /, -1898 components: list[enums.ComponentType], -1899 filter: typing.Optional[int] = None, -1900 ) -> typedefs.JSONObject: -1901 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1902 components_ = _collect_components(components) -1903 route = ( -1904 f"Destiny2/{int(membership_type)}/Profile/{membership_id}" -1905 f"/Character/{character_id}/Vendors/?components={components_}" -1906 ) -1907 -1908 if filter is not None: -1909 route = route + f"&filter={filter}" -1910 -1911 resp = await self._request( -1912 RequestMethod.GET, -1913 route, -1914 auth=access_token, -1915 ) -1916 assert isinstance(resp, dict) -1917 return resp -1918 -1919 async def fetch_vendor( -1920 self, -1921 access_token: str, -1922 character_id: int, -1923 membership_id: int, -1924 membership_type: typedefs.IntAnd[enums.MembershipType], -1925 vendor_hash: int, -1926 /, -1927 components: list[enums.ComponentType], -1928 ) -> typedefs.JSONObject: -1929 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. -1930 components_ = _collect_components(components) -1931 resp = await self._request( -1932 RequestMethod.GET, -1933 ( -1934 f"Platform/Destiny2/{int(membership_type)}/Profile/{membership_id}" -1935 f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}" -1936 ), -1937 auth=access_token, -1938 ) -1939 assert isinstance(resp, dict) -1940 return resp -1941 -1942 async def fetch_application_api_usage( -1943 self, -1944 access_token: str, -1945 application_id: int, -1946 /, -1947 *, -1948 start: typing.Optional[datetime.datetime] = None, -1949 end: typing.Optional[datetime.datetime] = None, -1950 ) -> typedefs.JSONObject: -1951 -1952 end_date, start_date = time.parse_date_range(end, start) -1953 resp = await self._request( -1954 RequestMethod.GET, -1955 f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}", -1956 auth=access_token, -1957 ) -1958 assert isinstance(resp, dict) -1959 return resp -1960 -1961 async def fetch_bungie_applications(self) -> typedefs.JSONArray: -1962 resp = await self._request(RequestMethod.GET, "App/FirstParty") -1963 assert isinstance(resp, list) -1964 return resp -1965 -1966 async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject: -1967 resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/") -1968 assert isinstance(resp, dict) -1969 return resp -1970 -1971 async def fetch_content_by_id( -1972 self, id: int, locale: str, /, *, head: bool = False -1973 ) -> typedefs.JSONObject: -1974 resp = await self._request( -1975 RequestMethod.GET, -1976 f"Content/GetContentById/{id}/{locale}/", -1977 json={"head": head}, -1978 ) -1979 assert isinstance(resp, dict) -1980 return resp -1981 -1982 async def fetch_content_by_tag_and_type( -1983 self, locale: str, tag: str, type: str, *, head: bool = False -1984 ) -> typedefs.JSONObject: -1985 resp = await self._request( -1986 RequestMethod.GET, -1987 f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/", -1988 json={"head": head}, -1989 ) -1990 assert isinstance(resp, dict) -1991 return resp +1859 async def awa_provide_authorization_result( +1860 self, +1861 access_token: str, +1862 selection: int, +1863 correlation_id: str, +1864 nonce: collections.MutableSequence[typing.Union[str, bytes]], +1865 ) -> int: +1866 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1867 +1868 body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce} +1869 +1870 resp = await self._request( +1871 RequestMethod.POST, +1872 "Destiny2/Awa/AwaProvideAuthorizationResult", +1873 json=body, +1874 auth=access_token, +1875 ) +1876 assert isinstance(resp, int) +1877 return resp +1878 +1879 async def fetch_vendors( +1880 self, +1881 access_token: str, +1882 character_id: int, +1883 membership_id: int, +1884 membership_type: typedefs.IntAnd[enums.MembershipType], +1885 /, +1886 components: list[enums.ComponentType], +1887 filter: typing.Optional[int] = None, +1888 ) -> typedefs.JSONObject: +1889 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1890 components_ = _collect_components(components) +1891 route = ( +1892 f"Destiny2/{int(membership_type)}/Profile/{membership_id}" +1893 f"/Character/{character_id}/Vendors/?components={components_}" +1894 ) +1895 +1896 if filter is not None: +1897 route = route + f"&filter={filter}" +1898 +1899 resp = await self._request( +1900 RequestMethod.GET, +1901 route, +1902 auth=access_token, +1903 ) +1904 assert isinstance(resp, dict) +1905 return resp +1906 +1907 async def fetch_vendor( +1908 self, +1909 access_token: str, +1910 character_id: int, +1911 membership_id: int, +1912 membership_type: typedefs.IntAnd[enums.MembershipType], +1913 vendor_hash: int, +1914 /, +1915 components: list[enums.ComponentType], +1916 ) -> typedefs.JSONObject: +1917 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. +1918 components_ = _collect_components(components) +1919 resp = await self._request( +1920 RequestMethod.GET, +1921 ( +1922 f"Platform/Destiny2/{int(membership_type)}/Profile/{membership_id}" +1923 f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}" +1924 ), +1925 auth=access_token, +1926 ) +1927 assert isinstance(resp, dict) +1928 return resp +1929 +1930 async def fetch_application_api_usage( +1931 self, +1932 access_token: str, +1933 application_id: int, +1934 /, +1935 *, +1936 start: typing.Optional[datetime.datetime] = None, +1937 end: typing.Optional[datetime.datetime] = None, +1938 ) -> typedefs.JSONObject: +1939 +1940 end_date, start_date = time.parse_date_range(end, start) +1941 resp = await self._request( +1942 RequestMethod.GET, +1943 f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}", +1944 auth=access_token, +1945 ) +1946 assert isinstance(resp, dict) +1947 return resp +1948 +1949 async def fetch_bungie_applications(self) -> typedefs.JSONArray: +1950 resp = await self._request(RequestMethod.GET, "App/FirstParty") +1951 assert isinstance(resp, list) +1952 return resp +1953 +1954 async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject: +1955 resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/") +1956 assert isinstance(resp, dict) +1957 return resp +1958 +1959 async def fetch_content_by_id( +1960 self, id: int, locale: str, /, *, head: bool = False +1961 ) -> typedefs.JSONObject: +1962 resp = await self._request( +1963 RequestMethod.GET, +1964 f"Content/GetContentById/{id}/{locale}/", +1965 json={"head": head}, +1966 ) +1967 assert isinstance(resp, dict) +1968 return resp +1969 +1970 async def fetch_content_by_tag_and_type( +1971 self, locale: str, tag: str, type: str, *, head: bool = False +1972 ) -> typedefs.JSONObject: +1973 resp = await self._request( +1974 RequestMethod.GET, +1975 f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/", +1976 json={"head": head}, +1977 ) +1978 assert isinstance(resp, dict) +1979 return resp +1980 +1981 async def search_content_with_text( +1982 self, +1983 locale: str, +1984 /, +1985 content_type: str, +1986 search_text: str, +1987 tag: str, +1988 *, +1989 page: undefined.UndefinedOr[int] = undefined.Undefined, +1990 source: undefined.UndefinedOr[str] = undefined.Undefined, +1991 ) -> typedefs.JSONObject: 1992 -1993 async def search_content_with_text( -1994 self, -1995 locale: str, -1996 /, -1997 content_type: str, -1998 search_text: str, -1999 tag: str, -2000 *, -2001 page: undefined.UndefinedOr[int] = undefined.Undefined, -2002 source: undefined.UndefinedOr[str] = undefined.Undefined, -2003 ) -> typedefs.JSONObject: -2004 -2005 body: typedefs.JSONObject = {} -2006 -2007 body["ctype"] = content_type -2008 body["searchtext"] = search_text -2009 body["tag"] = tag -2010 -2011 if page is not undefined.Undefined: -2012 body["currentpage"] = page -2013 else: -2014 body["currentpage"] = 1 -2015 -2016 if source is not undefined.Undefined: -2017 body["source"] = source -2018 else: -2019 source = "" -2020 resp = await self._request( -2021 RequestMethod.GET, f"Content/Search/{locale}/", json=body -2022 ) -2023 assert isinstance(resp, dict) -2024 return resp -2025 -2026 async def search_content_by_tag_and_type( -2027 self, -2028 locale: str, -2029 tag: str, -2030 type: str, -2031 *, -2032 page: undefined.UndefinedOr[int] = undefined.Undefined, -2033 ) -> typedefs.JSONObject: -2034 body: typedefs.JSONObject = {} -2035 body["currentpage"] = 1 if page is undefined.Undefined else page -2036 resp = await self._request( -2037 RequestMethod.GET, -2038 f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/", -2039 json=body, -2040 ) -2041 assert isinstance(resp, dict) -2042 return resp -2043 -2044 async def search_help_articles( -2045 self, text: str, size: str, / -2046 ) -> typedefs.JSONObject: -2047 resp = await self._request( -2048 RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/" -2049 ) -2050 assert isinstance(resp, dict) -2051 return resp +1993 body: typedefs.JSONObject = {} +1994 +1995 body["ctype"] = content_type +1996 body["searchtext"] = search_text +1997 body["tag"] = tag +1998 +1999 if page is not undefined.Undefined: +2000 body["currentpage"] = page +2001 else: +2002 body["currentpage"] = 1 +2003 +2004 if source is not undefined.Undefined: +2005 body["source"] = source +2006 else: +2007 source = "" +2008 resp = await self._request( +2009 RequestMethod.GET, f"Content/Search/{locale}/", json=body +2010 ) +2011 assert isinstance(resp, dict) +2012 return resp +2013 +2014 async def search_content_by_tag_and_type( +2015 self, +2016 locale: str, +2017 tag: str, +2018 type: str, +2019 *, +2020 page: undefined.UndefinedOr[int] = undefined.Undefined, +2021 ) -> typedefs.JSONObject: +2022 body: typedefs.JSONObject = {} +2023 body["currentpage"] = 1 if page is undefined.Undefined else page +2024 resp = await self._request( +2025 RequestMethod.GET, +2026 f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/", +2027 json=body, +2028 ) +2029 assert isinstance(resp, dict) +2030 return resp +2031 +2032 async def search_help_articles( +2033 self, text: str, size: str, / +2034 ) -> typedefs.JSONObject: +2035 resp = await self._request( +2036 RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/" +2037 ) +2038 assert isinstance(resp, dict) +2039 return resp +2040 +2041 async def fetch_topics_page( +2042 self, +2043 category_filter: int, +2044 group: int, +2045 date_filter: int, +2046 sort: typing.Union[str, bytes], +2047 *, +2048 page: undefined.UndefinedOr[int] = undefined.Undefined, +2049 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined, +2050 tag_filter: undefined.UndefinedOr[str] = undefined.Undefined, +2051 ) -> typedefs.JSONObject: 2052 -2053 async def fetch_topics_page( -2054 self, -2055 category_filter: int, -2056 group: int, -2057 date_filter: int, -2058 sort: typing.Union[str, bytes], -2059 *, -2060 page: undefined.UndefinedOr[int] = undefined.Undefined, -2061 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined, -2062 tag_filter: undefined.UndefinedOr[str] = undefined.Undefined, -2063 ) -> typedefs.JSONObject: -2064 -2065 body: typedefs.JSONObject = {} -2066 if locales is not undefined.Undefined: -2067 body["locales"] = ",".join(str(locales)) -2068 else: -2069 body["locales"] = ",".join([]) -2070 -2071 if tag_filter is not undefined.Undefined: -2072 body["tagstring"] = tag_filter -2073 else: -2074 body["tagstring"] = "" -2075 -2076 page = 0 if page is not undefined.Undefined else page -2077 -2078 resp = await self._request( -2079 RequestMethod.GET, -2080 f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/", -2081 json=body, -2082 ) -2083 assert isinstance(resp, dict) -2084 return resp -2085 -2086 async def fetch_core_topics_page( -2087 self, -2088 category_filter: int, -2089 date_filter: int, -2090 sort: typing.Union[str, bytes], -2091 *, -2092 page: undefined.UndefinedOr[int] = undefined.Undefined, -2093 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined, -2094 ) -> typedefs.JSONObject: -2095 body: typedefs.JSONObject = {} -2096 -2097 if locales is not undefined.Undefined: -2098 body["locales"] = ",".join(str(locales)) -2099 else: -2100 body["locales"] = ",".join([]) -2101 -2102 resp = await self._request( -2103 RequestMethod.GET, -2104 f"Forum/GetCoreTopicsPaged/{0 if page is undefined.Undefined else page}" -2105 f"/{sort!s}/{date_filter}/{category_filter}/", -2106 json=body, -2107 ) -2108 assert isinstance(resp, dict) -2109 return resp -2110 -2111 async def fetch_posts_threaded_page( -2112 self, -2113 parent_post: bool, -2114 page: int, -2115 page_size: int, -2116 parent_post_id: int, -2117 reply_size: int, -2118 root_thread_mode: bool, -2119 sort_mode: int, -2120 show_banned: typing.Optional[str] = None, -2121 ) -> typedefs.JSONObject: -2122 resp = await self._request( -2123 RequestMethod.GET, -2124 f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/" -2125 f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/", -2126 json={"showbanned": show_banned}, -2127 ) -2128 assert isinstance(resp, dict) -2129 return resp -2130 -2131 async def fetch_posts_threaded_page_from_child( -2132 self, -2133 child_id: bool, -2134 page: int, -2135 page_size: int, -2136 reply_size: int, -2137 root_thread_mode: bool, -2138 sort_mode: int, -2139 show_banned: typing.Optional[str] = None, +2053 body: typedefs.JSONObject = {} +2054 if locales is not undefined.Undefined: +2055 body["locales"] = ",".join(str(locales)) +2056 else: +2057 body["locales"] = ",".join([]) +2058 +2059 if tag_filter is not undefined.Undefined: +2060 body["tagstring"] = tag_filter +2061 else: +2062 body["tagstring"] = "" +2063 +2064 page = 0 if page is not undefined.Undefined else page +2065 +2066 resp = await self._request( +2067 RequestMethod.GET, +2068 f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/", +2069 json=body, +2070 ) +2071 assert isinstance(resp, dict) +2072 return resp +2073 +2074 async def fetch_core_topics_page( +2075 self, +2076 category_filter: int, +2077 date_filter: int, +2078 sort: typing.Union[str, bytes], +2079 *, +2080 page: undefined.UndefinedOr[int] = undefined.Undefined, +2081 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined, +2082 ) -> typedefs.JSONObject: +2083 body: typedefs.JSONObject = {} +2084 +2085 if locales is not undefined.Undefined: +2086 body["locales"] = ",".join(str(locales)) +2087 else: +2088 body["locales"] = ",".join([]) +2089 +2090 resp = await self._request( +2091 RequestMethod.GET, +2092 f"Forum/GetCoreTopicsPaged/{0 if page is undefined.Undefined else page}" +2093 f"/{sort!s}/{date_filter}/{category_filter}/", +2094 json=body, +2095 ) +2096 assert isinstance(resp, dict) +2097 return resp +2098 +2099 async def fetch_posts_threaded_page( +2100 self, +2101 parent_post: bool, +2102 page: int, +2103 page_size: int, +2104 parent_post_id: int, +2105 reply_size: int, +2106 root_thread_mode: bool, +2107 sort_mode: int, +2108 show_banned: typing.Optional[str] = None, +2109 ) -> typedefs.JSONObject: +2110 resp = await self._request( +2111 RequestMethod.GET, +2112 f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/" +2113 f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/", +2114 json={"showbanned": show_banned}, +2115 ) +2116 assert isinstance(resp, dict) +2117 return resp +2118 +2119 async def fetch_posts_threaded_page_from_child( +2120 self, +2121 child_id: bool, +2122 page: int, +2123 page_size: int, +2124 reply_size: int, +2125 root_thread_mode: bool, +2126 sort_mode: int, +2127 show_banned: typing.Optional[str] = None, +2128 ) -> typedefs.JSONObject: +2129 resp = await self._request( +2130 RequestMethod.GET, +2131 f"Forum/GetPostsThreadedPagedFromChild/{child_id}/" +2132 f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/", +2133 json={"showbanned": show_banned}, +2134 ) +2135 assert isinstance(resp, dict) +2136 return resp +2137 +2138 async def fetch_post_and_parent( +2139 self, child_id: int, /, *, show_banned: typing.Optional[str] = None 2140 ) -> typedefs.JSONObject: 2141 resp = await self._request( 2142 RequestMethod.GET, -2143 f"Forum/GetPostsThreadedPagedFromChild/{child_id}/" -2144 f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/", -2145 json={"showbanned": show_banned}, -2146 ) -2147 assert isinstance(resp, dict) -2148 return resp -2149 -2150 async def fetch_post_and_parent( -2151 self, child_id: int, /, *, show_banned: typing.Optional[str] = None -2152 ) -> typedefs.JSONObject: -2153 resp = await self._request( -2154 RequestMethod.GET, -2155 f"Forum/GetPostAndParent/{child_id}/", -2156 json={"showbanned": show_banned}, -2157 ) -2158 assert isinstance(resp, dict) -2159 return resp -2160 -2161 async def fetch_posts_and_parent_awaiting( -2162 self, child_id: int, /, *, show_banned: typing.Optional[str] = None -2163 ) -> typedefs.JSONObject: -2164 resp = await self._request( -2165 RequestMethod.GET, -2166 f"Forum/GetPostAndParentAwaitingApproval/{child_id}/", -2167 json={"showbanned": show_banned}, -2168 ) -2169 assert isinstance(resp, dict) -2170 return resp -2171 -2172 async def fetch_topic_for_content(self, content_id: int, /) -> int: -2173 resp = await self._request( -2174 RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/" -2175 ) -2176 assert isinstance(resp, int) -2177 return resp -2178 -2179 async def fetch_forum_tag_suggestions( -2180 self, partial_tag: str, / -2181 ) -> typedefs.JSONObject: -2182 resp = await self._request( -2183 RequestMethod.GET, -2184 "Forum/GetForumTagSuggestions/", -2185 json={"partialtag": partial_tag}, -2186 ) -2187 assert isinstance(resp, dict) -2188 return resp -2189 -2190 async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject: -2191 resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/") -2192 assert isinstance(resp, dict) -2193 return resp -2194 -2195 async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray: -2196 resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/") -2197 assert isinstance(resp, list) -2198 return resp -2199 -2200 async def fetch_recommended_groups( -2201 self, -2202 accecss_token: str, -2203 /, -2204 *, -2205 date_range: int = 0, -2206 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, -2207 ) -> typedefs.JSONArray: -2208 resp = await self._request( -2209 RequestMethod.POST, -2210 f"GroupV2/Recommended/{int(group_type)}/{date_range}/", -2211 auth=accecss_token, -2212 ) -2213 assert isinstance(resp, list) -2214 return resp -2215 -2216 async def fetch_available_avatars(self) -> collections.Mapping[str, int]: -2217 resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/") -2218 assert isinstance(resp, dict) -2219 return resp -2220 -2221 async def fetch_user_clan_invite_setting( -2222 self, -2223 access_token: str, -2224 /, -2225 membership_type: typedefs.IntAnd[enums.MembershipType], -2226 ) -> bool: -2227 resp = await self._request( -2228 RequestMethod.GET, -2229 f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/", -2230 auth=access_token, -2231 ) -2232 assert isinstance(resp, bool) -2233 return resp -2234 -2235 async def fetch_banned_group_members( -2236 self, access_token: str, group_id: int, /, *, page: int = 1 -2237 ) -> typedefs.JSONObject: -2238 resp = await self._request( -2239 RequestMethod.GET, -2240 f"GroupV2/{group_id}/Banned/?currentpage={page}", -2241 auth=access_token, -2242 ) -2243 assert isinstance(resp, dict) -2244 return resp -2245 -2246 async def fetch_pending_group_memberships( -2247 self, access_token: str, group_id: int, /, *, current_page: int = 1 -2248 ) -> typedefs.JSONObject: -2249 resp = await self._request( -2250 RequestMethod.GET, -2251 f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}", -2252 auth=access_token, -2253 ) -2254 assert isinstance(resp, dict) -2255 return resp -2256 -2257 async def fetch_invited_group_memberships( -2258 self, access_token: str, group_id: int, /, *, current_page: int = 1 -2259 ) -> typedefs.JSONObject: -2260 resp = await self._request( -2261 RequestMethod.GET, -2262 f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}", -2263 auth=access_token, -2264 ) -2265 assert isinstance(resp, dict) -2266 return resp -2267 -2268 async def invite_member_to_group( -2269 self, -2270 access_token: str, -2271 /, -2272 group_id: int, -2273 membership_id: int, -2274 membership_type: typedefs.IntAnd[enums.MembershipType], -2275 *, -2276 message: undefined.UndefinedOr[str] = undefined.Undefined, -2277 ) -> typedefs.JSONObject: -2278 resp = await self._request( -2279 RequestMethod.POST, -2280 f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/", -2281 auth=access_token, -2282 json={"message": str(message)}, -2283 ) -2284 assert isinstance(resp, dict) -2285 return resp -2286 -2287 async def cancel_group_member_invite( -2288 self, -2289 access_token: str, -2290 /, -2291 group_id: int, -2292 membership_id: int, -2293 membership_type: typedefs.IntAnd[enums.MembershipType], -2294 ) -> typedefs.JSONObject: -2295 resp = await self._request( -2296 RequestMethod.POST, -2297 f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/", -2298 auth=access_token, -2299 ) -2300 assert isinstance(resp, dict) -2301 return resp -2302 -2303 async def fetch_historical_definition(self) -> typedefs.JSONObject: -2304 resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/") -2305 assert isinstance(resp, dict) -2306 return resp -2307 -2308 async def fetch_historical_stats( -2309 self, -2310 character_id: int, -2311 membership_id: int, -2312 membership_type: typedefs.IntAnd[enums.MembershipType], -2313 day_start: datetime.datetime, -2314 day_end: datetime.datetime, -2315 groups: list[typedefs.IntAnd[enums.StatsGroupType]], -2316 modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]], -2317 *, -2318 period_type: enums.PeriodType = enums.PeriodType.ALL_TIME, -2319 ) -> typedefs.JSONObject: -2320 -2321 end, start = time.parse_date_range(day_end, day_start) -2322 resp = await self._request( -2323 RequestMethod.GET, -2324 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/", -2325 json={ -2326 "dayend": end, -2327 "daystart": start, -2328 "groups": [str(int(group)) for group in groups], -2329 "modes": [str(int(mode)) for mode in modes], -2330 "periodType": int(period_type), -2331 }, -2332 ) -2333 assert isinstance(resp, dict) -2334 return resp -2335 -2336 async def fetch_historical_stats_for_account( -2337 self, -2338 membership_id: int, -2339 membership_type: typedefs.IntAnd[enums.MembershipType], -2340 groups: list[typedefs.IntAnd[enums.StatsGroupType]], -2341 ) -> typedefs.JSONObject: -2342 resp = await self._request( -2343 RequestMethod.GET, -2344 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/", -2345 json={"groups": [str(int(group)) for group in groups]}, -2346 ) -2347 assert isinstance(resp, dict) -2348 return resp -2349 -2350 async def fetch_aggregated_activity_stats( -2351 self, -2352 character_id: int, -2353 membership_id: int, -2354 membership_type: typedefs.IntAnd[enums.MembershipType], -2355 /, -2356 ) -> typedefs.JSONObject: -2357 resp = await self._request( -2358 RequestMethod.GET, -2359 f"Destiny2/{int(membership_type)}/Account/{membership_id}/" -2360 f"Character/{character_id}/Stats/AggregateActivityStats/", -2361 ) -2362 assert isinstance(resp, dict) -2363 return resp +2143 f"Forum/GetPostAndParent/{child_id}/", +2144 json={"showbanned": show_banned}, +2145 ) +2146 assert isinstance(resp, dict) +2147 return resp +2148 +2149 async def fetch_posts_and_parent_awaiting( +2150 self, child_id: int, /, *, show_banned: typing.Optional[str] = None +2151 ) -> typedefs.JSONObject: +2152 resp = await self._request( +2153 RequestMethod.GET, +2154 f"Forum/GetPostAndParentAwaitingApproval/{child_id}/", +2155 json={"showbanned": show_banned}, +2156 ) +2157 assert isinstance(resp, dict) +2158 return resp +2159 +2160 async def fetch_topic_for_content(self, content_id: int, /) -> int: +2161 resp = await self._request( +2162 RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/" +2163 ) +2164 assert isinstance(resp, int) +2165 return resp +2166 +2167 async def fetch_forum_tag_suggestions( +2168 self, partial_tag: str, / +2169 ) -> typedefs.JSONObject: +2170 resp = await self._request( +2171 RequestMethod.GET, +2172 "Forum/GetForumTagSuggestions/", +2173 json={"partialtag": partial_tag}, +2174 ) +2175 assert isinstance(resp, dict) +2176 return resp +2177 +2178 async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject: +2179 resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/") +2180 assert isinstance(resp, dict) +2181 return resp +2182 +2183 async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray: +2184 resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/") +2185 assert isinstance(resp, list) +2186 return resp +2187 +2188 async def fetch_recommended_groups( +2189 self, +2190 accecss_token: str, +2191 /, +2192 *, +2193 date_range: int = 0, +2194 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, +2195 ) -> typedefs.JSONArray: +2196 resp = await self._request( +2197 RequestMethod.POST, +2198 f"GroupV2/Recommended/{int(group_type)}/{date_range}/", +2199 auth=accecss_token, +2200 ) +2201 assert isinstance(resp, list) +2202 return resp +2203 +2204 async def fetch_available_avatars(self) -> collections.Mapping[str, int]: +2205 resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/") +2206 assert isinstance(resp, dict) +2207 return resp +2208 +2209 async def fetch_user_clan_invite_setting( +2210 self, +2211 access_token: str, +2212 /, +2213 membership_type: typedefs.IntAnd[enums.MembershipType], +2214 ) -> bool: +2215 resp = await self._request( +2216 RequestMethod.GET, +2217 f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/", +2218 auth=access_token, +2219 ) +2220 assert isinstance(resp, bool) +2221 return resp +2222 +2223 async def fetch_banned_group_members( +2224 self, access_token: str, group_id: int, /, *, page: int = 1 +2225 ) -> typedefs.JSONObject: +2226 resp = await self._request( +2227 RequestMethod.GET, +2228 f"GroupV2/{group_id}/Banned/?currentpage={page}", +2229 auth=access_token, +2230 ) +2231 assert isinstance(resp, dict) +2232 return resp +2233 +2234 async def fetch_pending_group_memberships( +2235 self, access_token: str, group_id: int, /, *, current_page: int = 1 +2236 ) -> typedefs.JSONObject: +2237 resp = await self._request( +2238 RequestMethod.GET, +2239 f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}", +2240 auth=access_token, +2241 ) +2242 assert isinstance(resp, dict) +2243 return resp +2244 +2245 async def fetch_invited_group_memberships( +2246 self, access_token: str, group_id: int, /, *, current_page: int = 1 +2247 ) -> typedefs.JSONObject: +2248 resp = await self._request( +2249 RequestMethod.GET, +2250 f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}", +2251 auth=access_token, +2252 ) +2253 assert isinstance(resp, dict) +2254 return resp +2255 +2256 async def invite_member_to_group( +2257 self, +2258 access_token: str, +2259 /, +2260 group_id: int, +2261 membership_id: int, +2262 membership_type: typedefs.IntAnd[enums.MembershipType], +2263 *, +2264 message: undefined.UndefinedOr[str] = undefined.Undefined, +2265 ) -> typedefs.JSONObject: +2266 resp = await self._request( +2267 RequestMethod.POST, +2268 f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/", +2269 auth=access_token, +2270 json={"message": str(message)}, +2271 ) +2272 assert isinstance(resp, dict) +2273 return resp +2274 +2275 async def cancel_group_member_invite( +2276 self, +2277 access_token: str, +2278 /, +2279 group_id: int, +2280 membership_id: int, +2281 membership_type: typedefs.IntAnd[enums.MembershipType], +2282 ) -> typedefs.JSONObject: +2283 resp = await self._request( +2284 RequestMethod.POST, +2285 f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/", +2286 auth=access_token, +2287 ) +2288 assert isinstance(resp, dict) +2289 return resp +2290 +2291 async def fetch_historical_definition(self) -> typedefs.JSONObject: +2292 resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/") +2293 assert isinstance(resp, dict) +2294 return resp +2295 +2296 async def fetch_historical_stats( +2297 self, +2298 character_id: int, +2299 membership_id: int, +2300 membership_type: typedefs.IntAnd[enums.MembershipType], +2301 day_start: datetime.datetime, +2302 day_end: datetime.datetime, +2303 groups: list[typedefs.IntAnd[enums.StatsGroupType]], +2304 modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]], +2305 *, +2306 period_type: enums.PeriodType = enums.PeriodType.ALL_TIME, +2307 ) -> typedefs.JSONObject: +2308 +2309 end, start = time.parse_date_range(day_end, day_start) +2310 resp = await self._request( +2311 RequestMethod.GET, +2312 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/", +2313 json={ +2314 "dayend": end, +2315 "daystart": start, +2316 "groups": [str(int(group)) for group in groups], +2317 "modes": [str(int(mode)) for mode in modes], +2318 "periodType": int(period_type), +2319 }, +2320 ) +2321 assert isinstance(resp, dict) +2322 return resp +2323 +2324 async def fetch_historical_stats_for_account( +2325 self, +2326 membership_id: int, +2327 membership_type: typedefs.IntAnd[enums.MembershipType], +2328 groups: list[typedefs.IntAnd[enums.StatsGroupType]], +2329 ) -> typedefs.JSONObject: +2330 resp = await self._request( +2331 RequestMethod.GET, +2332 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/", +2333 json={"groups": [str(int(group)) for group in groups]}, +2334 ) +2335 assert isinstance(resp, dict) +2336 return resp +2337 +2338 async def fetch_aggregated_activity_stats( +2339 self, +2340 character_id: int, +2341 membership_id: int, +2342 membership_type: typedefs.IntAnd[enums.MembershipType], +2343 /, +2344 ) -> typedefs.JSONObject: +2345 resp = await self._request( +2346 RequestMethod.GET, +2347 f"Destiny2/{int(membership_type)}/Account/{membership_id}/" +2348 f"Character/{character_id}/Stats/AggregateActivityStats/", +2349 ) +2350 assert isinstance(resp, dict) +2351 return resp

            @@ -2829,2007 +2814,1997 @@

            -
             364class RESTClient(interfaces.RESTInterface):
            - 365    """A RESTful client implementation for Bungie's API.
            - 366
            - 367    This client is designed to only make HTTP requests and return JSON objects
            - 368    to provide RESTful functionality.
            - 369
            - 370    This client is also used within `aiobungie.Client` which deserialize those returned JSON objects
            - 371    using the factory into Pythonic data classes objects which provide Python functionality.
            - 372
            - 373    Example
            - 374    -------
            - 375    ```py
            - 376    import aiobungie
            - 377
            - 378    async def main():
            - 379        async with aiobungie.RESTClient("TOKEN") as rest_client:
            - 380            req = await rest_client.fetch_clan_members(4389205)
            - 381            clan_members = req['results']
            - 382            for member in clan_members:
            - 383                for k, v in member['destinyUserInfo'].items():
            - 384                    print(k, v)
            - 385    ```
            - 386
            - 387    Parameters
            - 388    ----------
            - 389    token : `str`
            - 390        A valid application token from Bungie's developer portal.
            - 391
            - 392    Other Parameters
            - 393    ----------------
            - 394    max_retries : `int`
            - 395        The max retries number to retry if the request hit a `5xx` status code.
            - 396    max_ratelimit_retries : `int`
            - 397        The max retries number to retry if the request hit a `429` status code. Defaults to `3`.
            - 398    client_secret : `typing.Optional[str]`
            - 399        An optional application client secret,
            - 400        This is only needed if you're fetching OAuth2 tokens with this client.
            - 401    client_id : `typing.Optional[int]`
            - 402        An optional application client id,
            - 403        This is only needed if you're fetching OAuth2 tokens with this client.
            - 404    enable_debugging : `bool | str`
            - 405        Whether to enable logging responses or not.
            - 406
            - 407    Logging Levels
            - 408    --------------
            - 409    * `False`: This will disable logging.
            - 410    * `True`: This will set the level to `DEBUG` and enable logging minimal information.
            - 411    * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information.
            - 412    """
            - 413
            - 414    __slots__ = (
            - 415        "_token",
            - 416        "_session",
            - 417        "_lock",
            - 418        "_max_retries",
            - 419        "_client_secret",
            - 420        "_client_id",
            - 421        "_metadata",
            - 422        "_max_rate_limit_retries",
            - 423    )
            - 424
            - 425    def __init__(
            - 426        self,
            - 427        token: str,
            - 428        /,
            - 429        client_secret: typing.Optional[str] = None,
            - 430        client_id: typing.Optional[int] = None,
            - 431        *,
            - 432        max_retries: int = 4,
            - 433        max_ratelimit_retries: int = 3,
            - 434        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
            - 435    ) -> None:
            - 436        self._session: typing.Optional[_Session] = None
            - 437        self._lock: typing.Optional[asyncio.Lock] = None
            - 438        self._client_secret = client_secret
            - 439        self._client_id = client_id
            - 440        self._token: str = token
            - 441        self._max_retries = max_retries
            - 442        self._max_rate_limit_retries = max_ratelimit_retries
            - 443        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
            +            
             362class RESTClient(interfaces.RESTInterface):
            + 363    """A RESTful client implementation for Bungie's API.
            + 364
            + 365    This client is designed to only make HTTP requests and return JSON objects
            + 366    to provide RESTful functionality.
            + 367
            + 368    This client is also used within `aiobungie.Client` which deserialize those returned JSON objects
            + 369    using the factory into Pythonic data classes objects which provide Python functionality.
            + 370
            + 371    Example
            + 372    -------
            + 373    ```py
            + 374    import aiobungie
            + 375
            + 376    async def main():
            + 377        async with aiobungie.RESTClient("TOKEN") as rest_client:
            + 378            req = await rest_client.fetch_clan_members(4389205)
            + 379            clan_members = req['results']
            + 380            for member in clan_members:
            + 381                for k, v in member['destinyUserInfo'].items():
            + 382                    print(k, v)
            + 383    ```
            + 384
            + 385    Parameters
            + 386    ----------
            + 387    token : `str`
            + 388        A valid application token from Bungie's developer portal.
            + 389
            + 390    Other Parameters
            + 391    ----------------
            + 392    max_retries : `int`
            + 393        The max retries number to retry if the request hit a `5xx` status code.
            + 394    max_ratelimit_retries : `int`
            + 395        The max retries number to retry if the request hit a `429` status code. Defaults to `3`.
            + 396    client_secret : `typing.Optional[str]`
            + 397        An optional application client secret,
            + 398        This is only needed if you're fetching OAuth2 tokens with this client.
            + 399    client_id : `typing.Optional[int]`
            + 400        An optional application client id,
            + 401        This is only needed if you're fetching OAuth2 tokens with this client.
            + 402    enable_debugging : `bool | str`
            + 403        Whether to enable logging responses or not.
            + 404
            + 405    Logging Levels
            + 406    --------------
            + 407    * `False`: This will disable logging.
            + 408    * `True`: This will set the level to `DEBUG` and enable logging minimal information.
            + 409    * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information.
            + 410    """
            + 411
            + 412    __slots__ = (
            + 413        "_token",
            + 414        "_session",
            + 415        "_lock",
            + 416        "_max_retries",
            + 417        "_client_secret",
            + 418        "_client_id",
            + 419        "_metadata",
            + 420        "_max_rate_limit_retries",
            + 421    )
            + 422
            + 423    def __init__(
            + 424        self,
            + 425        token: str,
            + 426        /,
            + 427        client_secret: typing.Optional[str] = None,
            + 428        client_id: typing.Optional[int] = None,
            + 429        *,
            + 430        max_retries: int = 4,
            + 431        max_ratelimit_retries: int = 3,
            + 432        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
            + 433    ) -> None:
            + 434        self._session: typing.Optional[_Session] = None
            + 435        self._lock: typing.Optional[asyncio.Lock] = None
            + 436        self._client_secret = client_secret
            + 437        self._client_id = client_id
            + 438        self._token: str = token
            + 439        self._max_retries = max_retries
            + 440        self._max_rate_limit_retries = max_ratelimit_retries
            + 441        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
            + 442
            + 443        self._set_debug_level(enable_debugging)
              444
            - 445        self._set_debug_level(enable_debugging)
            - 446
            - 447    @property
            - 448    def client_id(self) -> typing.Optional[int]:
            - 449        return self._client_id
            - 450
            - 451    @property
            - 452    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
            - 453        return self._metadata
            - 454
            - 455    @property
            - 456    def is_alive(self) -> bool:
            - 457        return self._session is not None
            - 458
            - 459    @typing.final
            - 460    async def close(self) -> None:
            - 461        session = self._get_session()
            - 462        await session.close()
            - 463        self._session = None
            - 464
            - 465    @typing.final
            - 466    def open(self) -> None:
            - 467        """Open a new client session. This is called internally with contextmanager usage."""
            - 468        if self.is_alive:
            - 469            raise RuntimeError("Cannot open a new session while it's already open.")
            + 445    @property
            + 446    def client_id(self) -> typing.Optional[int]:
            + 447        return self._client_id
            + 448
            + 449    @property
            + 450    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
            + 451        return self._metadata
            + 452
            + 453    @property
            + 454    def is_alive(self) -> bool:
            + 455        return self._session is not None
            + 456
            + 457    @typing.final
            + 458    async def close(self) -> None:
            + 459        session = self._get_session()
            + 460        await session.close()
            + 461        self._session = None
            + 462
            + 463    @typing.final
            + 464    def open(self) -> None:
            + 465        """Open a new client session. This is called internally with contextmanager usage."""
            + 466        if self.is_alive:
            + 467            raise RuntimeError("Cannot open a new session while it's already open.")
            + 468
            + 469        self._session = _Session.create(owner=False, raise_status=False)
              470
            - 471        self._session = _Session.create(
            - 472            owner=False,
            - 473            raise_status=False,
            - 474            connect=None,
            - 475            socket_read=None,
            - 476            socket_connect=None,
            - 477        )
            - 478
            - 479    @typing.final
            - 480    def enable_debugging(
            - 481        self,
            - 482        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
            - 483        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
            - 484        /,
            - 485    ) -> None:
            - 486        self._set_debug_level(level, file)
            - 487
            - 488    @typing.final
            - 489    async def static_request(
            - 490        self,
            - 491        method: typing.Union[RequestMethod, str],
            - 492        path: str,
            - 493        *,
            - 494        auth: typing.Optional[str] = None,
            - 495        json: typing.Optional[dict[str, typing.Any]] = None,
            - 496    ) -> ResponseSig:
            - 497        return await self._request(method, path, auth=auth, json=json)
            + 471    @typing.final
            + 472    def enable_debugging(
            + 473        self,
            + 474        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
            + 475        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
            + 476        /,
            + 477    ) -> None:
            + 478        self._set_debug_level(level, file)
            + 479
            + 480    @typing.final
            + 481    async def static_request(
            + 482        self,
            + 483        method: typing.Union[RequestMethod, str],
            + 484        path: str,
            + 485        *,
            + 486        auth: typing.Optional[str] = None,
            + 487        json: typing.Optional[dict[str, typing.Any]] = None,
            + 488    ) -> ResponseSig:
            + 489        return await self._request(method, path, auth=auth, json=json)
            + 490
            + 491    @typing.final
            + 492    def build_oauth2_url(
            + 493        self, client_id: typing.Optional[int] = None
            + 494    ) -> typing.Optional[builders.OAuthURL]:
            + 495        client_id = client_id or self._client_id
            + 496        if client_id is None:
            + 497            return None
              498
            - 499    @typing.final
            - 500    def build_oauth2_url(
            - 501        self, client_id: typing.Optional[int] = None
            - 502    ) -> typing.Optional[str]:
            - 503        client_id = client_id or self._client_id
            - 504        if client_id is None:
            - 505            return None
            + 499        return builders.OAuthURL(client_id=client_id)
            + 500
            + 501    @staticmethod
            + 502    def _set_debug_level(
            + 503        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
            + 504        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
            + 505    ) -> None:
              506
            - 507        return url.OAUTH2_EP_BUILDER.format(
            - 508            oauth_endpoint=url.OAUTH_EP,
            - 509            client_id=client_id,
            - 510            uuid=_uuid(),
            - 511        )
            + 507        file_handler = logging.FileHandler(file, mode="w") if file else None
            + 508        if level == "TRACE" or level == TRACE:
            + 509            logging.basicConfig(
            + 510                level=TRACE, handlers=[file_handler] if file_handler else None
            + 511            )
              512
            - 513    @staticmethod
            - 514    def _set_debug_level(
            - 515        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
            - 516        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
            - 517    ) -> None:
            - 518
            - 519        file_handler = logging.FileHandler(file, mode="w") if file else None
            - 520        if level == "TRACE" or level == TRACE:
            - 521            logging.basicConfig(
            - 522                level=TRACE, handlers=[file_handler] if file_handler else None
            - 523            )
            - 524
            - 525        elif level:
            - 526            logging.basicConfig(
            - 527                level=logging.DEBUG, handlers=[file_handler] if file_handler else None
            - 528            )
            - 529
            - 530    def _get_session(self) -> _Session:
            - 531        if self._session:
            - 532            return self._session
            - 533
            - 534        raise RuntimeError(
            - 535            "Cannot return a session while its close. Make sure you use `async with` before making requests."
            - 536        )
            - 537
            - 538    async def _request(
            - 539        self,
            - 540        method: typing.Union[RequestMethod, str],
            - 541        route: str,
            - 542        *,
            - 543        base: bool = False,
            - 544        oauth2: bool = False,
            - 545        auth: typing.Optional[str] = None,
            - 546        unwrapping: typing.Literal["json", "read"] = "json",
            - 547        json: typing.Optional[dict[str, typing.Any]] = None,
            - 548        headers: typing.Optional[dict[str, typing.Any]] = None,
            - 549        data: typing.Optional[typing.Union[str, dict[str, typing.Any]]] = None,
            - 550    ) -> ResponseSig:
            - 551
            - 552        retries: int = 0
            - 553        session = self._get_session()
            - 554        headers = headers or {}
            + 513        elif level:
            + 514            logging.basicConfig(
            + 515                level=logging.DEBUG, handlers=[file_handler] if file_handler else None
            + 516            )
            + 517
            + 518    def _get_session(self) -> _Session:
            + 519        if self._session:
            + 520            return self._session
            + 521
            + 522        raise RuntimeError(
            + 523            "Cannot return a session while its close. Make sure you use `async with` before making requests."
            + 524        )
            + 525
            + 526    async def _request(
            + 527        self,
            + 528        method: typing.Union[RequestMethod, str],
            + 529        route: str,
            + 530        *,
            + 531        base: bool = False,
            + 532        oauth2: bool = False,
            + 533        auth: typing.Optional[str] = None,
            + 534        unwrapping: typing.Literal["json", "read"] = "json",
            + 535        json: typing.Optional[dict[str, typing.Any]] = None,
            + 536        headers: typing.Optional[dict[str, typing.Any]] = None,
            + 537        data: typing.Optional[typing.Union[str, dict[str, typing.Any]]] = None,
            + 538    ) -> ResponseSig:
            + 539
            + 540        retries: int = 0
            + 541        session = self._get_session()
            + 542        headers = headers or {}
            + 543
            + 544        headers.setdefault(_USER_AGENT_HEADERS, _USER_AGENT)
            + 545        headers["X-API-KEY"] = self._token
            + 546
            + 547        if auth is not None:
            + 548            headers[_AUTH_HEADER] = f"Bearer {auth}"
            + 549
            + 550        # Handling endpoints
            + 551        endpoint = url.BASE
            + 552
            + 553        if not base:
            + 554            endpoint = endpoint + url.REST_EP
              555
            - 556        headers.setdefault(_USER_AGENT_HEADERS, _USER_AGENT)
            - 557        headers["X-API-KEY"] = self._token
            - 558
            - 559        if auth is not None:
            - 560            headers[_AUTH_HEADER] = f"Bearer {auth}"
            - 561
            - 562        # Handling endpoints
            - 563        endpoint = url.BASE
            - 564
            - 565        if not base:
            - 566            endpoint = endpoint + url.REST_EP
            + 556        if oauth2:
            + 557            headers["Content-Type"] = "application/x-www-form-urlencoded"
            + 558            endpoint = endpoint + url.TOKEN_EP
            + 559
            + 560        if self._lock is None:
            + 561            self._lock = asyncio.Lock()
            + 562
            + 563        while True:
            + 564            try:
            + 565                async with (stack := contextlib.AsyncExitStack()):
            + 566                    await stack.enter_async_context(self._lock)
              567
            - 568        if oauth2:
            - 569            headers["Content-Type"] = "application/x-www-form-urlencoded"
            - 570            endpoint = endpoint + url.TOKEN_EP
            - 571
            - 572        if self._lock is None:
            - 573            self._lock = asyncio.Lock()
            - 574
            - 575        while True:
            - 576            try:
            - 577                async with (stack := contextlib.AsyncExitStack()):
            - 578                    await stack.enter_async_context(self._lock)
            - 579
            - 580                    # We make the request here.
            - 581                    taken_time = time.monotonic()
            - 582                    response = await stack.enter_async_context(
            - 583                        session.client_session.request(
            - 584                            method=method,
            - 585                            url=f"{endpoint}/{route}",
            - 586                            json=json,
            - 587                            headers=headers,
            - 588                            data=data,
            - 589                        )
            - 590                    )
            - 591                    response_time = (time.monotonic() - taken_time) * 1_000
            + 568                    # We make the request here.
            + 569                    taken_time = time.monotonic()
            + 570                    response = await stack.enter_async_context(
            + 571                        session.client_session.request(
            + 572                            method=method,
            + 573                            url=f"{endpoint}/{route}",
            + 574                            json=json,
            + 575                            headers=headers,
            + 576                            data=data,
            + 577                        )
            + 578                    )
            + 579                    response_time = (time.monotonic() - taken_time) * 1_000
            + 580
            + 581                    _LOG.debug(
            + 582                        "%s %s %s Time %.4fms",
            + 583                        method,
            + 584                        f"{endpoint}/{route}",
            + 585                        f"{response.status} {response.reason}",
            + 586                        response_time,
            + 587                    )
            + 588
            + 589                    await self._handle_ratelimit(
            + 590                        response, method, route, self._max_rate_limit_retries
            + 591                    )
              592
            - 593                    _LOG.debug(
            - 594                        "%s %s %s Time %.4fms",
            - 595                        method,
            - 596                        f"{endpoint}/{route}",
            - 597                        f"{response.status} {response.reason}",
            - 598                        response_time,
            - 599                    )
            + 593                    if response.status == http.HTTPStatus.NO_CONTENT:
            + 594                        return None
            + 595
            + 596                    if 300 > response.status >= 200:
            + 597                        if unwrapping == "read":
            + 598                            # We need to read the bytes for the manifest response.
            + 599                            return await response.read()
              600
            - 601                    await self._handle_ratelimit(
            - 602                        response, method, route, self._max_rate_limit_retries
            - 603                    )
            - 604
            - 605                    if response.status == http.HTTPStatus.NO_CONTENT:
            - 606                        return None
            - 607
            - 608                    if 300 > response.status >= 200:
            - 609                        if unwrapping == "read":
            - 610                            # We need to read the bytes for the manifest response.
            - 611                            return await response.read()
            - 612
            - 613                        if response.content_type == _APP_JSON:
            - 614                            json_data = await response.json()
            - 615
            - 616                            _LOG.debug(
            - 617                                "%s %s %s Time %.4fms",
            - 618                                method,
            - 619                                f"{endpoint}/{route}",
            - 620                                f"{response.status} {response.reason}",
            - 621                                response_time,
            - 622                            )
            - 623
            - 624                            if _LOG.isEnabledFor(TRACE):
            - 625                                headers.update(response.headers)  # type: ignore
            - 626
            - 627                                _LOG.log(
            - 628                                    TRACE,
            - 629                                    "%s",
            - 630                                    error.stringify_http_message(headers),
            - 631                                )
            - 632
            - 633                            # Return the response.
            - 634                            # oauth2 responses are not packed inside a Response object.
            - 635                            if oauth2:
            - 636                                return json_data  # type: ignore[no-any-return]
            - 637
            - 638                            return json_data["Response"]  # type: ignore[no-any-return]
            - 639
            - 640                    if (
            - 641                        response.status in _RETRY_5XX
            - 642                        and retries < self._max_retries  # noqa: W503
            - 643                    ):
            - 644                        backoff_ = backoff.ExponentialBackOff(maximum=6)
            - 645                        sleep_time = next(backoff_)
            - 646                        _LOG.warning(
            - 647                            "Got %i - %s. Sleeping for %.2f seconds. Remaining retries: %i",
            - 648                            response.status,
            - 649                            response.reason,
            - 650                            sleep_time,
            - 651                            self._max_retries - retries,
            - 652                        )
            - 653
            - 654                        retries += 1
            - 655                        await asyncio.sleep(sleep_time)
            - 656                        continue
            - 657
            - 658                    raise await error.raise_error(response)
            - 659            # eol
            - 660            except _Dyn:
            - 661                continue
            - 662
            - 663    if not typing.TYPE_CHECKING:
            - 664
            - 665        def __enter__(self) -> typing.NoReturn:
            - 666            cls = type(self)
            - 667            raise TypeError(
            - 668                f"{cls.__qualname__} is async only, use 'async with' instead."
            - 669            )
            + 601                        if response.content_type == _APP_JSON:
            + 602                            json_data = await response.json()
            + 603
            + 604                            _LOG.debug(
            + 605                                "%s %s %s Time %.4fms",
            + 606                                method,
            + 607                                f"{endpoint}/{route}",
            + 608                                f"{response.status} {response.reason}",
            + 609                                response_time,
            + 610                            )
            + 611
            + 612                            if _LOG.isEnabledFor(TRACE):
            + 613                                headers.update(response.headers)  # type: ignore
            + 614
            + 615                                _LOG.log(
            + 616                                    TRACE,
            + 617                                    "%s",
            + 618                                    error.stringify_http_message(headers),
            + 619                                )
            + 620
            + 621                            # Return the response.
            + 622                            # oauth2 responses are not packed inside a Response object.
            + 623                            if oauth2:
            + 624                                return json_data  # type: ignore[no-any-return]
            + 625
            + 626                            return json_data["Response"]  # type: ignore[no-any-return]
            + 627
            + 628                    if (
            + 629                        response.status in _RETRY_5XX
            + 630                        and retries < self._max_retries  # noqa: W503
            + 631                    ):
            + 632                        backoff_ = backoff.ExponentialBackOff(maximum=6)
            + 633                        sleep_time = next(backoff_)
            + 634                        _LOG.warning(
            + 635                            "Got %i - %s. Sleeping for %.2f seconds. Remaining retries: %i",
            + 636                            response.status,
            + 637                            response.reason,
            + 638                            sleep_time,
            + 639                            self._max_retries - retries,
            + 640                        )
            + 641
            + 642                        retries += 1
            + 643                        await asyncio.sleep(sleep_time)
            + 644                        continue
            + 645
            + 646                    raise await error.raise_error(response)
            + 647            # eol
            + 648            except _Dyn:
            + 649                continue
            + 650
            + 651    if not typing.TYPE_CHECKING:
            + 652
            + 653        def __enter__(self) -> typing.NoReturn:
            + 654            cls = type(self)
            + 655            raise TypeError(
            + 656                f"{cls.__qualname__} is async only, use 'async with' instead."
            + 657            )
            + 658
            + 659        def __exit__(
            + 660            self,
            + 661            exception_type: typing.Optional[type[BaseException]],
            + 662            exception: typing.Optional[BaseException],
            + 663            exception_traceback: typing.Optional[types.TracebackType],
            + 664        ) -> None:
            + 665            ...
            + 666
            + 667    async def __aenter__(self) -> RESTClient:
            + 668        self.open()
            + 669        return self
              670
            - 671        def __exit__(
            - 672            self,
            - 673            exception_type: typing.Optional[type[BaseException]],
            - 674            exception: typing.Optional[BaseException],
            - 675            exception_traceback: typing.Optional[types.TracebackType],
            - 676        ) -> None:
            - 677            ...
            + 671    async def __aexit__(
            + 672        self,
            + 673        exception_type: typing.Optional[type[BaseException]],
            + 674        exception: typing.Optional[BaseException],
            + 675        exception_traceback: typing.Optional[types.TracebackType],
            + 676    ) -> None:
            + 677        await self.close()
              678
            - 679    async def __aenter__(self) -> RESTClient:
            - 680        self.open()
            - 681        return self
            - 682
            - 683    async def __aexit__(
            - 684        self,
            - 685        exception_type: typing.Optional[type[BaseException]],
            - 686        exception: typing.Optional[BaseException],
            - 687        exception_traceback: typing.Optional[types.TracebackType],
            - 688    ) -> None:
            - 689        await self.close()
            - 690
            - 691    # We don't want this to be super complicated.
            - 692    @staticmethod
            - 693    @typing.final
            - 694    async def _handle_ratelimit(
            - 695        response: aiohttp.ClientResponse,
            - 696        method: str,
            - 697        route: str,
            - 698        max_ratelimit_retries: int = 3,
            - 699    ) -> None:
            - 700
            - 701        if response.status != http.HTTPStatus.TOO_MANY_REQUESTS:
            - 702            return
            - 703
            - 704        if response.content_type != _APP_JSON:
            - 705            raise error.HTTPError(
            - 706                f"Being ratelimited on non JSON request, {response.content_type}.",
            - 707                http.HTTPStatus.TOO_MANY_REQUESTS,
            - 708            )
            + 679    # We don't want this to be super complicated.
            + 680    @staticmethod
            + 681    @typing.final
            + 682    async def _handle_ratelimit(
            + 683        response: aiohttp.ClientResponse,
            + 684        method: str,
            + 685        route: str,
            + 686        max_ratelimit_retries: int = 3,
            + 687    ) -> None:
            + 688
            + 689        if response.status != http.HTTPStatus.TOO_MANY_REQUESTS:
            + 690            return
            + 691
            + 692        if response.content_type != _APP_JSON:
            + 693            raise error.HTTPError(
            + 694                f"Being ratelimited on non JSON request, {response.content_type}.",
            + 695                http.HTTPStatus.TOO_MANY_REQUESTS,
            + 696            )
            + 697
            + 698        count: int = 0
            + 699        json: typedefs.JSONObject = await response.json()
            + 700        retry_after = float(json["ThrottleSeconds"])
            + 701
            + 702        while True:
            + 703            if count == max_ratelimit_retries:
            + 704                raise _Dyn
            + 705
            + 706            if retry_after <= 0:
            + 707                # We sleep for a little bit to avoid funky behavior.
            + 708                sleep_time = float(random.random() + 0.93) / 2
              709
            - 710        count: int = 0
            - 711        json: typedefs.JSONObject = await response.json()
            - 712        retry_after = float(json["ThrottleSeconds"])
            - 713
            - 714        while True:
            - 715            if count == max_ratelimit_retries:
            - 716                raise _Dyn
            - 717
            - 718            if retry_after <= 0:
            - 719                # We sleep for a little bit to avoid funky behavior.
            - 720                sleep_time = float(random.random() + 0.93) / 2
            - 721
            - 722                _LOG.warning(
            - 723                    "We're being ratelimited with method %s route %s. Sleeping for %.2fs.",
            - 724                    method,
            - 725                    route,
            - 726                    sleep_time,
            - 727                )
            - 728                count += 1
            - 729                await asyncio.sleep(sleep_time)
            - 730                continue
            - 731
            - 732            raise error.RateLimitedError(
            - 733                body=json,
            - 734                url=str(response.real_url),
            - 735                retry_after=retry_after,
            + 710                _LOG.warning(
            + 711                    "We're being ratelimited with method %s route %s. Sleeping for %.2fs.",
            + 712                    method,
            + 713                    route,
            + 714                    sleep_time,
            + 715                )
            + 716                count += 1
            + 717                await asyncio.sleep(sleep_time)
            + 718                continue
            + 719
            + 720            raise error.RateLimitedError(
            + 721                body=json,
            + 722                url=str(response.real_url),
            + 723                retry_after=retry_after,
            + 724            )
            + 725
            + 726    async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response:
            + 727
            + 728        if not isinstance(self._client_id, int):
            + 729            raise TypeError(
            + 730                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
            + 731            )
            + 732
            + 733        if not isinstance(self._client_secret, str):
            + 734            raise TypeError(
            + 735                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
              736            )
              737
            - 738    async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response:
            - 739
            - 740        if not isinstance(self._client_id, int):
            - 741            raise TypeError(
            - 742                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
            - 743            )
            - 744
            - 745        if not isinstance(self._client_secret, str):
            - 746            raise TypeError(
            - 747                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
            - 748            )
            - 749
            - 750        headers = {
            - 751            "client_secret": self._client_secret,
            - 752        }
            - 753
            - 754        data = (
            - 755            f"grant_type=authorization_code&code={code}"
            - 756            f"&client_id={self._client_id}&client_secret={self._client_secret}"
            - 757        )
            - 758
            - 759        response = await self._request(
            - 760            RequestMethod.POST, "", headers=headers, data=data, oauth2=True
            - 761        )
            - 762        assert isinstance(response, dict)
            - 763        return builders.OAuth2Response.build_response(response)
            - 764
            - 765    async def refresh_access_token(
            - 766        self, refresh_token: str, /
            - 767    ) -> builders.OAuth2Response:
            - 768        if not isinstance(self._client_id, int):
            - 769            raise TypeError(
            - 770                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
            - 771            )
            - 772
            - 773        if not isinstance(self._client_secret, str):
            - 774            raise TypeError(
            - 775                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
            - 776            )
            + 738        headers = {
            + 739            "client_secret": self._client_secret,
            + 740        }
            + 741
            + 742        data = (
            + 743            f"grant_type=authorization_code&code={code}"
            + 744            f"&client_id={self._client_id}&client_secret={self._client_secret}"
            + 745        )
            + 746
            + 747        response = await self._request(
            + 748            RequestMethod.POST, "", headers=headers, data=data, oauth2=True
            + 749        )
            + 750        assert isinstance(response, dict)
            + 751        return builders.OAuth2Response.build_response(response)
            + 752
            + 753    async def refresh_access_token(
            + 754        self, refresh_token: str, /
            + 755    ) -> builders.OAuth2Response:
            + 756        if not isinstance(self._client_id, int):
            + 757            raise TypeError(
            + 758                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
            + 759            )
            + 760
            + 761        if not isinstance(self._client_secret, str):
            + 762            raise TypeError(
            + 763                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
            + 764            )
            + 765
            + 766        data = {
            + 767            "grant_type": "refresh_token",
            + 768            "refresh_token": refresh_token,
            + 769            "client_id": self._client_id,
            + 770            "client_secret": self._client_secret,
            + 771            "Content-Type": "application/x-www-form-urlencoded",
            + 772        }
            + 773
            + 774        response = await self._request(RequestMethod.POST, "", data=data, oauth2=True)
            + 775        assert isinstance(response, dict)
            + 776        return builders.OAuth2Response.build_response(response)
              777
            - 778        data = {
            - 779            "grant_type": "refresh_token",
            - 780            "refresh_token": refresh_token,
            - 781            "client_id": self._client_id,
            - 782            "client_secret": self._client_secret,
            - 783            "Content-Type": "application/x-www-form-urlencoded",
            - 784        }
            + 778    async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject:
            + 779        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 780        resp = await self._request(
            + 781            RequestMethod.GET, f"User/GetBungieNetUserById/{id}/"
            + 782        )
            + 783        assert isinstance(resp, dict)
            + 784        return resp
              785
            - 786        response = await self._request(RequestMethod.POST, "", data=data, oauth2=True)
            - 787        assert isinstance(response, dict)
            - 788        return builders.OAuth2Response.build_response(response)
            - 789
            - 790    async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject:
            - 791        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 792        resp = await self._request(
            - 793            RequestMethod.GET, f"User/GetBungieNetUserById/{id}/"
            - 794        )
            - 795        assert isinstance(resp, dict)
            - 796        return resp
            - 797
            - 798    async def fetch_user_themes(self) -> typedefs.JSONArray:
            - 799        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 800        resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/")
            - 801        assert isinstance(resp, list)
            - 802        return resp
            - 803
            - 804    async def fetch_membership_from_id(
            - 805        self,
            - 806        id: int,
            - 807        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
            - 808        /,
            - 809    ) -> typedefs.JSONObject:
            - 810        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 811        resp = await self._request(
            - 812            RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}"
            - 813        )
            - 814        assert isinstance(resp, dict)
            - 815        return resp
            - 816
            - 817    async def fetch_player(
            - 818        self,
            - 819        name: str,
            - 820        code: int,
            - 821        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
            - 822        /,
            - 823    ) -> typedefs.JSONArray:
            - 824        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 825        resp = await self._request(
            - 826            RequestMethod.POST,
            - 827            f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}",
            - 828            json={"displayName": name, "displayNameCode": code},
            - 829        )
            - 830        assert isinstance(resp, list)
            - 831        return resp
            - 832
            - 833    async def search_users(self, name: str, /) -> typedefs.JSONObject:
            + 786    async def fetch_user_themes(self) -> typedefs.JSONArray:
            + 787        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 788        resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/")
            + 789        assert isinstance(resp, list)
            + 790        return resp
            + 791
            + 792    async def fetch_membership_from_id(
            + 793        self,
            + 794        id: int,
            + 795        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
            + 796        /,
            + 797    ) -> typedefs.JSONObject:
            + 798        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 799        resp = await self._request(
            + 800            RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}"
            + 801        )
            + 802        assert isinstance(resp, dict)
            + 803        return resp
            + 804
            + 805    async def fetch_player(
            + 806        self,
            + 807        name: str,
            + 808        code: int,
            + 809        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
            + 810        /,
            + 811    ) -> typedefs.JSONArray:
            + 812        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 813        resp = await self._request(
            + 814            RequestMethod.POST,
            + 815            f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}",
            + 816            json={"displayName": name, "displayNameCode": code},
            + 817        )
            + 818        assert isinstance(resp, list)
            + 819        return resp
            + 820
            + 821    async def search_users(self, name: str, /) -> typedefs.JSONObject:
            + 822        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 823        resp = await self._request(
            + 824            RequestMethod.POST,
            + 825            "User/Search/GlobalName/0",
            + 826            json={"displayNamePrefix": name},
            + 827        )
            + 828        assert isinstance(resp, dict)
            + 829        return resp
            + 830
            + 831    async def fetch_clan_from_id(
            + 832        self, id: int, /, access_token: typing.Optional[str] = None
            + 833    ) -> typedefs.JSONObject:
              834        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
              835        resp = await self._request(
            - 836            RequestMethod.POST,
            - 837            "User/Search/GlobalName/0",
            - 838            json={"displayNamePrefix": name},
            - 839        )
            - 840        assert isinstance(resp, dict)
            - 841        return resp
            - 842
            - 843    async def fetch_clan_from_id(
            - 844        self, id: int, /, access_token: typing.Optional[str] = None
            - 845    ) -> typedefs.JSONObject:
            - 846        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 847        resp = await self._request(
            - 848            RequestMethod.GET, f"GroupV2/{id}", auth=access_token
            - 849        )
            - 850        assert isinstance(resp, dict)
            - 851        return resp
            - 852
            - 853    async def fetch_clan(
            - 854        self,
            - 855        name: str,
            - 856        /,
            - 857        access_token: typing.Optional[str] = None,
            - 858        *,
            - 859        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            - 860    ) -> typedefs.JSONObject:
            - 861        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 862        resp = await self._request(
            - 863            RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token
            - 864        )
            - 865        assert isinstance(resp, dict)
            - 866        return resp
            - 867
            - 868    async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject:
            - 869        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 870        resp = await self._request(
            - 871            RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/"
            - 872        )
            - 873        assert isinstance(resp, dict)
            - 874        return resp
            - 875
            - 876    async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray:
            - 877        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 878        resp = await self._request(
            - 879            RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/"
            - 880        )
            - 881        assert isinstance(resp, list)
            - 882        return resp
            - 883
            - 884    async def fetch_application(self, appid: int, /) -> typedefs.JSONObject:
            - 885        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 886        resp = await self._request(RequestMethod.GET, f"App/Application/{appid}")
            - 887        assert isinstance(resp, dict)
            - 888        return resp
            - 889
            - 890    async def fetch_character(
            - 891        self,
            - 892        member_id: int,
            - 893        membership_type: typedefs.IntAnd[enums.MembershipType],
            - 894        character_id: int,
            - 895        components: list[enums.ComponentType],
            - 896        auth: typing.Optional[str] = None,
            - 897    ) -> typedefs.JSONObject:
            - 898        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 899        collector = _collect_components(components)
            - 900        response = await self._request(
            - 901            RequestMethod.GET,
            - 902            f"Destiny2/{int(membership_type)}/Profile/{member_id}/"
            - 903            f"Character/{character_id}/?components={collector}",
            - 904            auth=auth,
            - 905        )
            - 906        assert isinstance(response, dict)
            - 907        return response
            - 908
            - 909    async def fetch_activities(
            - 910        self,
            - 911        member_id: int,
            - 912        character_id: int,
            - 913        mode: typedefs.IntAnd[enums.GameMode],
            - 914        membership_type: typedefs.IntAnd[
            - 915            enums.MembershipType
            - 916        ] = enums.MembershipType.ALL,
            - 917        *,
            - 918        page: int = 0,
            - 919        limit: int = 1,
            - 920    ) -> typedefs.JSONObject:
            - 921        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 922        resp = await self._request(
            - 923            RequestMethod.GET,
            - 924            f"Destiny2/{int(membership_type)}/Account/"
            - 925            f"{member_id}/Character/{character_id}/Stats/Activities"
            - 926            f"/?mode={int(mode)}&count={limit}&page={page}",
            - 927        )
            - 928        assert isinstance(resp, dict)
            - 929        return resp
            - 930
            - 931    async def fetch_vendor_sales(self) -> typedefs.JSONObject:
            - 932        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 933        resp = await self._request(
            - 934            RequestMethod.GET,
            - 935            f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}",
            - 936        )
            - 937        assert isinstance(resp, dict)
            - 938        return resp
            - 939
            - 940    async def fetch_profile(
            - 941        self,
            - 942        membership_id: int,
            - 943        type: typedefs.IntAnd[enums.MembershipType],
            - 944        components: list[enums.ComponentType],
            - 945        auth: typing.Optional[str] = None,
            - 946    ) -> typedefs.JSONObject:
            - 947        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 948        collector = _collect_components(components)
            - 949        response = await self._request(
            - 950            RequestMethod.GET,
            - 951            f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}",
            - 952            auth=auth,
            - 953        )
            - 954        assert isinstance(response, dict)
            - 955        return response
            - 956
            - 957    async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject:
            - 958        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 959        response = await self._request(
            - 960            RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}"
            - 961        )
            - 962        assert isinstance(response, dict)
            - 963        return response
            + 836            RequestMethod.GET, f"GroupV2/{id}", auth=access_token
            + 837        )
            + 838        assert isinstance(resp, dict)
            + 839        return resp
            + 840
            + 841    async def fetch_clan(
            + 842        self,
            + 843        name: str,
            + 844        /,
            + 845        access_token: typing.Optional[str] = None,
            + 846        *,
            + 847        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            + 848    ) -> typedefs.JSONObject:
            + 849        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 850        resp = await self._request(
            + 851            RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token
            + 852        )
            + 853        assert isinstance(resp, dict)
            + 854        return resp
            + 855
            + 856    async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject:
            + 857        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 858        resp = await self._request(
            + 859            RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/"
            + 860        )
            + 861        assert isinstance(resp, dict)
            + 862        return resp
            + 863
            + 864    async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray:
            + 865        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 866        resp = await self._request(
            + 867            RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/"
            + 868        )
            + 869        assert isinstance(resp, list)
            + 870        return resp
            + 871
            + 872    async def fetch_application(self, appid: int, /) -> typedefs.JSONObject:
            + 873        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 874        resp = await self._request(RequestMethod.GET, f"App/Application/{appid}")
            + 875        assert isinstance(resp, dict)
            + 876        return resp
            + 877
            + 878    async def fetch_character(
            + 879        self,
            + 880        member_id: int,
            + 881        membership_type: typedefs.IntAnd[enums.MembershipType],
            + 882        character_id: int,
            + 883        components: list[enums.ComponentType],
            + 884        auth: typing.Optional[str] = None,
            + 885    ) -> typedefs.JSONObject:
            + 886        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 887        collector = _collect_components(components)
            + 888        response = await self._request(
            + 889            RequestMethod.GET,
            + 890            f"Destiny2/{int(membership_type)}/Profile/{member_id}/"
            + 891            f"Character/{character_id}/?components={collector}",
            + 892            auth=auth,
            + 893        )
            + 894        assert isinstance(response, dict)
            + 895        return response
            + 896
            + 897    async def fetch_activities(
            + 898        self,
            + 899        member_id: int,
            + 900        character_id: int,
            + 901        mode: typedefs.IntAnd[enums.GameMode],
            + 902        membership_type: typedefs.IntAnd[
            + 903            enums.MembershipType
            + 904        ] = enums.MembershipType.ALL,
            + 905        *,
            + 906        page: int = 0,
            + 907        limit: int = 1,
            + 908    ) -> typedefs.JSONObject:
            + 909        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 910        resp = await self._request(
            + 911            RequestMethod.GET,
            + 912            f"Destiny2/{int(membership_type)}/Account/"
            + 913            f"{member_id}/Character/{character_id}/Stats/Activities"
            + 914            f"/?mode={int(mode)}&count={limit}&page={page}",
            + 915        )
            + 916        assert isinstance(resp, dict)
            + 917        return resp
            + 918
            + 919    async def fetch_vendor_sales(self) -> typedefs.JSONObject:
            + 920        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 921        resp = await self._request(
            + 922            RequestMethod.GET,
            + 923            f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}",
            + 924        )
            + 925        assert isinstance(resp, dict)
            + 926        return resp
            + 927
            + 928    async def fetch_profile(
            + 929        self,
            + 930        membership_id: int,
            + 931        type: typedefs.IntAnd[enums.MembershipType],
            + 932        components: list[enums.ComponentType],
            + 933        auth: typing.Optional[str] = None,
            + 934    ) -> typedefs.JSONObject:
            + 935        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 936        collector = _collect_components(components)
            + 937        response = await self._request(
            + 938            RequestMethod.GET,
            + 939            f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}",
            + 940            auth=auth,
            + 941        )
            + 942        assert isinstance(response, dict)
            + 943        return response
            + 944
            + 945    async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject:
            + 946        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 947        response = await self._request(
            + 948            RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}"
            + 949        )
            + 950        assert isinstance(response, dict)
            + 951        return response
            + 952
            + 953    async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject:
            + 954        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 955        resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash)
            + 956        assert isinstance(resp, dict)
            + 957        return resp
            + 958
            + 959    async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject:
            + 960        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            + 961        resp = await self.fetch_entity("DestinyObjectiveDefinition", hash)
            + 962        assert isinstance(resp, dict)
            + 963        return resp
              964
            - 965    async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject:
            - 966        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 967        resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash)
            - 968        assert isinstance(resp, dict)
            - 969        return resp
            - 970
            - 971    async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject:
            - 972        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            - 973        resp = await self.fetch_entity("DestinyObjectiveDefinition", hash)
            - 974        assert isinstance(resp, dict)
            - 975        return resp
            - 976
            - 977    async def fetch_groups_for_member(
            - 978        self,
            - 979        member_id: int,
            - 980        member_type: typedefs.IntAnd[enums.MembershipType],
            - 981        /,
            - 982        *,
            - 983        filter: int = 0,
            - 984        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            - 985    ) -> typedefs.JSONObject:
            - 986        resp = await self._request(
            - 987            RequestMethod.GET,
            - 988            f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
            - 989        )
            - 990        assert isinstance(resp, dict)
            - 991        return resp
            - 992
            - 993    async def fetch_potential_groups_for_member(
            - 994        self,
            - 995        member_id: int,
            - 996        member_type: typedefs.IntAnd[enums.MembershipType],
            - 997        /,
            - 998        *,
            - 999        filter: int = 0,
            -1000        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            -1001    ) -> typedefs.JSONObject:
            -1002        resp = await self._request(
            -1003            RequestMethod.GET,
            -1004            f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
            -1005        )
            -1006        assert isinstance(resp, dict)
            -1007        return resp
            -1008
            -1009    async def fetch_clan_members(
            -1010        self,
            -1011        clan_id: int,
            -1012        /,
            -1013        *,
            -1014        name: typing.Optional[str] = None,
            -1015        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
            -1016    ) -> typedefs.JSONObject:
            -1017        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1018        resp = await self._request(
            -1019            RequestMethod.GET,
            -1020            f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}&currentpage=1",
            -1021        )
            -1022        assert isinstance(resp, dict)
            -1023        return resp
            -1024
            -1025    async def fetch_hardlinked_credentials(
            -1026        self,
            -1027        credential: int,
            -1028        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
            -1029        /,
            -1030    ) -> typedefs.JSONObject:
            -1031        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1032        resp = await self._request(
            -1033            RequestMethod.GET,
            -1034            f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/",
            -1035        )
            -1036        assert isinstance(resp, dict)
            -1037        return resp
            -1038
            -1039    async def fetch_user_credentials(
            -1040        self, access_token: str, membership_id: int, /
            -1041    ) -> typedefs.JSONArray:
            -1042        resp = await self._request(
            -1043            RequestMethod.GET,
            -1044            f"User/GetCredentialTypesForTargetAccount/{membership_id}",
            -1045            auth=access_token,
            -1046        )
            -1047        assert isinstance(resp, list)
            -1048        return resp
            -1049
            -1050    async def insert_socket_plug(
            -1051        self,
            -1052        action_token: str,
            -1053        /,
            -1054        instance_id: int,
            -1055        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
            -1056        character_id: int,
            -1057        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1058    ) -> typedefs.JSONObject:
            -1059
            -1060        if isinstance(plug, builders.PlugSocketBuilder):
            -1061            plug = plug.collect()
            -1062
            -1063        body = {
            -1064            "actionToken": action_token,
            -1065            "itemInstanceId": instance_id,
            -1066            "plug": plug,
            -1067            "characterId": character_id,
            -1068            "membershipType": int(membership_type),
            -1069        }
            -1070        resp = await self._request(
            -1071            RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body
            -1072        )
            -1073        assert isinstance(resp, dict)
            -1074        return resp
            -1075
            -1076    async def insert_socket_plug_free(
            -1077        self,
            -1078        access_token: str,
            -1079        /,
            -1080        instance_id: int,
            -1081        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
            -1082        character_id: int,
            -1083        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1084    ) -> typedefs.JSONObject:
            -1085
            -1086        if isinstance(plug, builders.PlugSocketBuilder):
            -1087            plug = plug.collect()
            -1088
            -1089        body = {
            -1090            "itemInstanceId": instance_id,
            -1091            "plug": plug,
            -1092            "characterId": character_id,
            -1093            "membershipType": int(membership_type),
            -1094        }
            -1095        resp = await self._request(
            -1096            RequestMethod.POST,
            -1097            "Destiny2/Actions/Items/InsertSocketPlugFree",
            -1098            json=body,
            -1099            auth=access_token,
            -1100        )
            -1101        assert isinstance(resp, dict)
            -1102        return resp
            -1103
            -1104    async def set_item_lock_state(
            -1105        self,
            -1106        access_token: str,
            -1107        state: bool,
            -1108        /,
            -1109        item_id: int,
            -1110        character_id: int,
            -1111        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1112    ) -> int:
            -1113        body = {
            -1114            "state": state,
            -1115            "itemId": item_id,
            -1116            "characterId": character_id,
            -1117            "membership_type": int(membership_type),
            -1118        }
            -1119        response = await self._request(
            -1120            RequestMethod.POST,
            -1121            "Destiny2/Actions/Items/SetLockState",
            -1122            json=body,
            -1123            auth=access_token,
            -1124        )
            -1125        assert isinstance(response, int)
            -1126        return response
            -1127
            -1128    async def set_quest_track_state(
            -1129        self,
            -1130        access_token: str,
            -1131        state: bool,
            -1132        /,
            -1133        item_id: int,
            -1134        character_id: int,
            -1135        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1136    ) -> int:
            -1137        body = {
            -1138            "state": state,
            -1139            "itemId": item_id,
            -1140            "characterId": character_id,
            -1141            "membership_type": int(membership_type),
            -1142        }
            -1143        response = await self._request(
            -1144            RequestMethod.POST,
            -1145            "Destiny2/Actions/Items/SetTrackedState",
            -1146            json=body,
            -1147            auth=access_token,
            -1148        )
            -1149        assert isinstance(response, int)
            -1150        return response
            -1151
            -1152    async def fetch_manifest_path(self) -> typedefs.JSONObject:
            -1153        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1154        path = await self._request(RequestMethod.GET, "Destiny2/Manifest")
            -1155        assert isinstance(path, dict)
            -1156        return path
            -1157
            -1158    async def read_manifest_bytes(self, language: str = "en", /) -> bytes:
            -1159        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1160        _ensure_manifest_language(language)
            -1161
            -1162        content = await self.fetch_manifest_path()
            -1163        resp = await self._request(
            -1164            RequestMethod.GET,
            -1165            content["mobileWorldContentPaths"][language],
            -1166            unwrapping="read",
            -1167            base=True,
            -1168        )
            -1169        assert isinstance(resp, bytes)
            -1170        return resp
            -1171
            -1172    async def download_manifest(
            -1173        self,
            -1174        language: str = "en",
            -1175        name: str = "manifest",
            -1176        path: typing.Union[pathlib.Path, str] = ".",
            -1177        *,
            -1178        force: bool = False,
            -1179    ) -> None:
            -1180        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1181        complete_path = _get_path(name, path, sql=True)
            -1182
            -1183        if complete_path.exists() and force:
            -1184            if force:
            -1185                _LOG.info(
            -1186                    f"Found manifest in {complete_path!s}. Forcing to Re-Download."
            -1187                )
            -1188                complete_path.unlink(missing_ok=True)
            -1189
            -1190                return await self.download_manifest(language, name, path, force=force)
            + 965    async def fetch_groups_for_member(
            + 966        self,
            + 967        member_id: int,
            + 968        member_type: typedefs.IntAnd[enums.MembershipType],
            + 969        /,
            + 970        *,
            + 971        filter: int = 0,
            + 972        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            + 973    ) -> typedefs.JSONObject:
            + 974        resp = await self._request(
            + 975            RequestMethod.GET,
            + 976            f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
            + 977        )
            + 978        assert isinstance(resp, dict)
            + 979        return resp
            + 980
            + 981    async def fetch_potential_groups_for_member(
            + 982        self,
            + 983        member_id: int,
            + 984        member_type: typedefs.IntAnd[enums.MembershipType],
            + 985        /,
            + 986        *,
            + 987        filter: int = 0,
            + 988        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            + 989    ) -> typedefs.JSONObject:
            + 990        resp = await self._request(
            + 991            RequestMethod.GET,
            + 992            f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
            + 993        )
            + 994        assert isinstance(resp, dict)
            + 995        return resp
            + 996
            + 997    async def fetch_clan_members(
            + 998        self,
            + 999        clan_id: int,
            +1000        /,
            +1001        *,
            +1002        name: typing.Optional[str] = None,
            +1003        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
            +1004    ) -> typedefs.JSONObject:
            +1005        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1006        resp = await self._request(
            +1007            RequestMethod.GET,
            +1008            f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}&currentpage=1",
            +1009        )
            +1010        assert isinstance(resp, dict)
            +1011        return resp
            +1012
            +1013    async def fetch_hardlinked_credentials(
            +1014        self,
            +1015        credential: int,
            +1016        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
            +1017        /,
            +1018    ) -> typedefs.JSONObject:
            +1019        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1020        resp = await self._request(
            +1021            RequestMethod.GET,
            +1022            f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/",
            +1023        )
            +1024        assert isinstance(resp, dict)
            +1025        return resp
            +1026
            +1027    async def fetch_user_credentials(
            +1028        self, access_token: str, membership_id: int, /
            +1029    ) -> typedefs.JSONArray:
            +1030        resp = await self._request(
            +1031            RequestMethod.GET,
            +1032            f"User/GetCredentialTypesForTargetAccount/{membership_id}",
            +1033            auth=access_token,
            +1034        )
            +1035        assert isinstance(resp, list)
            +1036        return resp
            +1037
            +1038    async def insert_socket_plug(
            +1039        self,
            +1040        action_token: str,
            +1041        /,
            +1042        instance_id: int,
            +1043        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
            +1044        character_id: int,
            +1045        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1046    ) -> typedefs.JSONObject:
            +1047
            +1048        if isinstance(plug, builders.PlugSocketBuilder):
            +1049            plug = plug.collect()
            +1050
            +1051        body = {
            +1052            "actionToken": action_token,
            +1053            "itemInstanceId": instance_id,
            +1054            "plug": plug,
            +1055            "characterId": character_id,
            +1056            "membershipType": int(membership_type),
            +1057        }
            +1058        resp = await self._request(
            +1059            RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body
            +1060        )
            +1061        assert isinstance(resp, dict)
            +1062        return resp
            +1063
            +1064    async def insert_socket_plug_free(
            +1065        self,
            +1066        access_token: str,
            +1067        /,
            +1068        instance_id: int,
            +1069        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
            +1070        character_id: int,
            +1071        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1072    ) -> typedefs.JSONObject:
            +1073
            +1074        if isinstance(plug, builders.PlugSocketBuilder):
            +1075            plug = plug.collect()
            +1076
            +1077        body = {
            +1078            "itemInstanceId": instance_id,
            +1079            "plug": plug,
            +1080            "characterId": character_id,
            +1081            "membershipType": int(membership_type),
            +1082        }
            +1083        resp = await self._request(
            +1084            RequestMethod.POST,
            +1085            "Destiny2/Actions/Items/InsertSocketPlugFree",
            +1086            json=body,
            +1087            auth=access_token,
            +1088        )
            +1089        assert isinstance(resp, dict)
            +1090        return resp
            +1091
            +1092    async def set_item_lock_state(
            +1093        self,
            +1094        access_token: str,
            +1095        state: bool,
            +1096        /,
            +1097        item_id: int,
            +1098        character_id: int,
            +1099        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1100    ) -> int:
            +1101        body = {
            +1102            "state": state,
            +1103            "itemId": item_id,
            +1104            "characterId": character_id,
            +1105            "membership_type": int(membership_type),
            +1106        }
            +1107        response = await self._request(
            +1108            RequestMethod.POST,
            +1109            "Destiny2/Actions/Items/SetLockState",
            +1110            json=body,
            +1111            auth=access_token,
            +1112        )
            +1113        assert isinstance(response, int)
            +1114        return response
            +1115
            +1116    async def set_quest_track_state(
            +1117        self,
            +1118        access_token: str,
            +1119        state: bool,
            +1120        /,
            +1121        item_id: int,
            +1122        character_id: int,
            +1123        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1124    ) -> int:
            +1125        body = {
            +1126            "state": state,
            +1127            "itemId": item_id,
            +1128            "characterId": character_id,
            +1129            "membership_type": int(membership_type),
            +1130        }
            +1131        response = await self._request(
            +1132            RequestMethod.POST,
            +1133            "Destiny2/Actions/Items/SetTrackedState",
            +1134            json=body,
            +1135            auth=access_token,
            +1136        )
            +1137        assert isinstance(response, int)
            +1138        return response
            +1139
            +1140    async def fetch_manifest_path(self) -> typedefs.JSONObject:
            +1141        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1142        path = await self._request(RequestMethod.GET, "Destiny2/Manifest")
            +1143        assert isinstance(path, dict)
            +1144        return path
            +1145
            +1146    async def read_manifest_bytes(self, language: str = "en", /) -> bytes:
            +1147        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1148        _ensure_manifest_language(language)
            +1149
            +1150        content = await self.fetch_manifest_path()
            +1151        resp = await self._request(
            +1152            RequestMethod.GET,
            +1153            content["mobileWorldContentPaths"][language],
            +1154            unwrapping="read",
            +1155            base=True,
            +1156        )
            +1157        assert isinstance(resp, bytes)
            +1158        return resp
            +1159
            +1160    async def download_manifest(
            +1161        self,
            +1162        language: str = "en",
            +1163        name: str = "manifest",
            +1164        path: typing.Union[pathlib.Path, str] = ".",
            +1165        *,
            +1166        force: bool = False,
            +1167    ) -> None:
            +1168        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1169        complete_path = _get_path(name, path, sql=True)
            +1170
            +1171        if complete_path.exists() and force:
            +1172            if force:
            +1173                _LOG.info(
            +1174                    f"Found manifest in {complete_path!s}. Forcing to Re-Download."
            +1175                )
            +1176                complete_path.unlink(missing_ok=True)
            +1177
            +1178                return await self.download_manifest(language, name, path, force=force)
            +1179
            +1180            else:
            +1181                raise FileExistsError(
            +1182                    "Manifest file already exists, "
            +1183                    "To force download, set the `force` parameter to `True`."
            +1184                )
            +1185
            +1186        _LOG.info(f"Downloading manifest. Location: {complete_path!s}")
            +1187        data_bytes = await self.read_manifest_bytes(language)
            +1188        await asyncio.get_running_loop().run_in_executor(
            +1189            None, _write_sqlite_bytes, data_bytes, path, name
            +1190        )
             1191
            -1192            else:
            -1193                raise FileExistsError(
            -1194                    "Manifest file already exists, "
            -1195                    "To force download, set the `force` parameter to `True`."
            -1196                )
            -1197
            -1198        _LOG.info(f"Downloading manifest. Location: {complete_path!s}")
            -1199        data_bytes = await self.read_manifest_bytes(language)
            -1200        await asyncio.get_running_loop().run_in_executor(
            -1201            None, _write_sqlite_bytes, data_bytes, path, name
            -1202        )
            -1203
            -1204    async def download_json_manifest(
            -1205        self,
            -1206        file_name: str = "manifest",
            -1207        path: typing.Union[str, pathlib.Path] = ".",
            -1208        language: str = "en",
            -1209    ) -> None:
            -1210        _ensure_manifest_language(language)
            -1211
            -1212        _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...")
            -1213
            -1214        content = await self.fetch_manifest_path()
            -1215        json_bytes = await self._request(
            -1216            RequestMethod.GET,
            -1217            content["jsonWorldContentPaths"][language],
            -1218            unwrapping="read",
            -1219            base=True,
            -1220        )
            -1221
            -1222        await asyncio.get_running_loop().run_in_executor(
            -1223            None, _write_json_bytes, json_bytes, file_name, path
            -1224        )
            -1225        _LOG.info("Finished downloading manifest JSON.")
            -1226
            -1227    async def fetch_manifest_version(self) -> str:
            -1228        return typing.cast(str, (await self.fetch_manifest_path())["version"])
            -1229
            -1230    async def fetch_linked_profiles(
            -1231        self,
            -1232        member_id: int,
            -1233        member_type: typedefs.IntAnd[enums.MembershipType],
            -1234        /,
            -1235        *,
            -1236        all: bool = False,
            -1237    ) -> typedefs.JSONObject:
            -1238        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1239        resp = await self._request(
            -1240            RequestMethod.GET,
            -1241            f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}",
            -1242        )
            -1243        assert isinstance(resp, dict)
            -1244        return resp
            -1245
            -1246    async def fetch_clan_banners(self) -> typedefs.JSONObject:
            -1247        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1248        resp = await self._request(
            -1249            RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/"
            -1250        )
            -1251        assert isinstance(resp, dict)
            -1252        return resp
            -1253
            -1254    async def fetch_public_milestones(self) -> typedefs.JSONObject:
            -1255        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1256        resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/")
            -1257        assert isinstance(resp, dict)
            -1258        return resp
            -1259
            -1260    async def fetch_public_milestone_content(
            -1261        self, milestone_hash: int, /
            -1262    ) -> typedefs.JSONObject:
            -1263        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1264        resp = await self._request(
            -1265            RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/"
            +1192    async def download_json_manifest(
            +1193        self,
            +1194        file_name: str = "manifest",
            +1195        path: typing.Union[str, pathlib.Path] = ".",
            +1196        language: str = "en",
            +1197    ) -> None:
            +1198        _ensure_manifest_language(language)
            +1199
            +1200        _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...")
            +1201
            +1202        content = await self.fetch_manifest_path()
            +1203        json_bytes = await self._request(
            +1204            RequestMethod.GET,
            +1205            content["jsonWorldContentPaths"][language],
            +1206            unwrapping="read",
            +1207            base=True,
            +1208        )
            +1209
            +1210        await asyncio.get_running_loop().run_in_executor(
            +1211            None, _write_json_bytes, json_bytes, file_name, path
            +1212        )
            +1213        _LOG.info("Finished downloading manifest JSON.")
            +1214
            +1215    async def fetch_manifest_version(self) -> str:
            +1216        return typing.cast(str, (await self.fetch_manifest_path())["version"])
            +1217
            +1218    async def fetch_linked_profiles(
            +1219        self,
            +1220        member_id: int,
            +1221        member_type: typedefs.IntAnd[enums.MembershipType],
            +1222        /,
            +1223        *,
            +1224        all: bool = False,
            +1225    ) -> typedefs.JSONObject:
            +1226        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1227        resp = await self._request(
            +1228            RequestMethod.GET,
            +1229            f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}",
            +1230        )
            +1231        assert isinstance(resp, dict)
            +1232        return resp
            +1233
            +1234    async def fetch_clan_banners(self) -> typedefs.JSONObject:
            +1235        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1236        resp = await self._request(
            +1237            RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/"
            +1238        )
            +1239        assert isinstance(resp, dict)
            +1240        return resp
            +1241
            +1242    async def fetch_public_milestones(self) -> typedefs.JSONObject:
            +1243        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1244        resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/")
            +1245        assert isinstance(resp, dict)
            +1246        return resp
            +1247
            +1248    async def fetch_public_milestone_content(
            +1249        self, milestone_hash: int, /
            +1250    ) -> typedefs.JSONObject:
            +1251        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1252        resp = await self._request(
            +1253            RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/"
            +1254        )
            +1255        assert isinstance(resp, dict)
            +1256        return resp
            +1257
            +1258    async def fetch_current_user_memberships(
            +1259        self, access_token: str, /
            +1260    ) -> typedefs.JSONObject:
            +1261        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1262        resp = await self._request(
            +1263            RequestMethod.GET,
            +1264            "User/GetMembershipsForCurrentUser/",
            +1265            auth=access_token,
             1266        )
             1267        assert isinstance(resp, dict)
             1268        return resp
             1269
            -1270    async def fetch_current_user_memberships(
            -1271        self, access_token: str, /
            -1272    ) -> typedefs.JSONObject:
            -1273        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1274        resp = await self._request(
            -1275            RequestMethod.GET,
            -1276            "User/GetMembershipsForCurrentUser/",
            -1277            auth=access_token,
            -1278        )
            -1279        assert isinstance(resp, dict)
            -1280        return resp
            -1281
            -1282    async def equip_item(
            -1283        self,
            -1284        access_token: str,
            -1285        /,
            -1286        item_id: int,
            -1287        character_id: int,
            -1288        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1289    ) -> None:
            -1290        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1291        payload = {
            -1292            "itemId": item_id,
            -1293            "characterId": character_id,
            -1294            "membershipType": int(membership_type),
            -1295        }
            -1296
            -1297        await self._request(
            -1298            RequestMethod.POST,
            -1299            "Destiny2/Actions/Items/EquipItem/",
            -1300            json=payload,
            -1301            auth=access_token,
            -1302        )
            -1303
            -1304    async def equip_items(
            -1305        self,
            -1306        access_token: str,
            -1307        /,
            -1308        item_ids: list[int],
            -1309        character_id: int,
            -1310        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1311    ) -> None:
            -1312        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1313        payload = {
            -1314            "itemIds": item_ids,
            -1315            "characterId": character_id,
            -1316            "membershipType": int(membership_type),
            -1317        }
            -1318        await self._request(
            -1319            RequestMethod.POST,
            -1320            "Destiny2/Actions/Items/EquipItems/",
            -1321            json=payload,
            -1322            auth=access_token,
            -1323        )
            -1324
            -1325    async def ban_clan_member(
            -1326        self,
            -1327        access_token: str,
            -1328        /,
            -1329        group_id: int,
            -1330        membership_id: int,
            -1331        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1332        *,
            -1333        length: int = 0,
            -1334        comment: undefined.UndefinedOr[str] = undefined.Undefined,
            -1335    ) -> None:
            -1336        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1337        payload = {"comment": str(comment), "length": length}
            -1338        await self._request(
            -1339            RequestMethod.POST,
            -1340            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/",
            -1341            json=payload,
            -1342            auth=access_token,
            -1343        )
            -1344
            -1345    async def unban_clan_member(
            -1346        self,
            -1347        access_token: str,
            -1348        /,
            -1349        group_id: int,
            -1350        membership_id: int,
            -1351        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1352    ) -> None:
            -1353        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1354        await self._request(
            -1355            RequestMethod.POST,
            -1356            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/",
            -1357            auth=access_token,
            -1358        )
            -1359
            -1360    async def kick_clan_member(
            -1361        self,
            -1362        access_token: str,
            -1363        /,
            -1364        group_id: int,
            -1365        membership_id: int,
            -1366        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1367    ) -> typedefs.JSONObject:
            -1368        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1369        resp = await self._request(
            -1370            RequestMethod.POST,
            -1371            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/",
            -1372            auth=access_token,
            -1373        )
            -1374        assert isinstance(resp, dict)
            -1375        return resp
            -1376
            -1377    async def edit_clan(
            -1378        self,
            -1379        access_token: str,
            -1380        /,
            -1381        group_id: int,
            -1382        *,
            -1383        name: typedefs.NoneOr[str] = None,
            -1384        about: typedefs.NoneOr[str] = None,
            -1385        motto: typedefs.NoneOr[str] = None,
            -1386        theme: typedefs.NoneOr[str] = None,
            -1387        tags: typedefs.NoneOr[collections.Sequence[str]] = None,
            -1388        is_public: typedefs.NoneOr[bool] = None,
            -1389        locale: typedefs.NoneOr[str] = None,
            -1390        avatar_image_index: typedefs.NoneOr[int] = None,
            -1391        membership_option: typedefs.NoneOr[
            -1392            typedefs.IntAnd[enums.MembershipOption]
            -1393        ] = None,
            -1394        allow_chat: typedefs.NoneOr[bool] = None,
            -1395        chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None,
            -1396        call_sign: typedefs.NoneOr[str] = None,
            -1397        homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
            -1398        enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None,
            -1399        default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
            -1400        is_public_topic_admin: typedefs.NoneOr[bool] = None,
            -1401    ) -> None:
            -1402        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1403        payload = {
            -1404            "name": name,
            -1405            "about": about,
            -1406            "motto": motto,
            -1407            "theme": theme,
            -1408            "tags": tags,
            -1409            "isPublic": is_public,
            -1410            "avatarImageIndex": avatar_image_index,
            -1411            "isPublicTopicAdminOnly": is_public_topic_admin,
            -1412            "allowChat": allow_chat,
            -1413            "chatSecurity": chat_security,
            -1414            "callsign": call_sign,
            -1415            "homepage": homepage,
            -1416            "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins,
            -1417            "defaultPublicity": default_publicity,
            -1418            "locale": locale,
            -1419        }
            -1420        if membership_option is not None:
            -1421            payload["membershipOption"] = int(membership_option)
            -1422
            -1423        await self._request(
            -1424            RequestMethod.POST,
            -1425            f"GroupV2/{group_id}/Edit",
            -1426            json=payload,
            -1427            auth=access_token,
            -1428        )
            -1429
            -1430    async def edit_clan_options(
            -1431        self,
            -1432        access_token: str,
            -1433        /,
            -1434        group_id: int,
            -1435        *,
            -1436        invite_permissions_override: typedefs.NoneOr[bool] = None,
            -1437        update_culture_permissionOverride: typedefs.NoneOr[bool] = None,
            -1438        host_guided_game_permission_override: typedefs.NoneOr[
            -1439            typing.Literal[0, 1, 2]
            -1440        ] = None,
            -1441        update_banner_permission_override: typedefs.NoneOr[bool] = None,
            -1442        join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None,
            -1443    ) -> None:
            -1444
            -1445        payload = {
            -1446            "InvitePermissionOverride": invite_permissions_override,
            -1447            "UpdateCulturePermissionOverride": update_culture_permissionOverride,
            -1448            "HostGuidedGamePermissionOverride": host_guided_game_permission_override,
            -1449            "UpdateBannerPermissionOverride": update_banner_permission_override,
            -1450            "JoinLevel": int(join_level) if join_level else None,
            -1451        }
            -1452
            -1453        await self._request(
            -1454            RequestMethod.POST,
            -1455            f"GroupV2/{group_id}/EditFounderOptions",
            -1456            json=payload,
            -1457            auth=access_token,
            -1458        )
            -1459
            -1460    async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject:
            -1461        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1462        resp = await self._request(
            -1463            RequestMethod.GET,
            -1464            "Social/Friends/",
            -1465            auth=access_token,
            -1466        )
            -1467        assert isinstance(resp, dict)
            -1468        return resp
            -1469
            -1470    async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject:
            -1471        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1472        resp = await self._request(
            -1473            RequestMethod.GET,
            -1474            "Social/Friends/Requests",
            -1475            auth=access_token,
            -1476        )
            -1477        assert isinstance(resp, dict)
            -1478        return resp
            -1479
            -1480    async def accept_friend_request(self, access_token: str, /, member_id: int) -> None:
            -1481        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1482        await self._request(
            -1483            RequestMethod.POST,
            -1484            f"Social/Friends/Requests/Accept/{member_id}",
            -1485            auth=access_token,
            -1486        )
            -1487
            -1488    async def send_friend_request(self, access_token: str, /, member_id: int) -> None:
            -1489        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1490        await self._request(
            -1491            RequestMethod.POST,
            -1492            f"Social/Friends/Add/{member_id}",
            -1493            auth=access_token,
            -1494        )
            -1495
            -1496    async def decline_friend_request(
            -1497        self, access_token: str, /, member_id: int
            -1498    ) -> None:
            -1499        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1500        await self._request(
            -1501            RequestMethod.POST,
            -1502            f"Social/Friends/Requests/Decline/{member_id}",
            -1503            auth=access_token,
            -1504        )
            -1505
            -1506    async def remove_friend(self, access_token: str, /, member_id: int) -> None:
            -1507        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1508        await self._request(
            -1509            RequestMethod.POST,
            -1510            f"Social/Friends/Remove/{member_id}",
            -1511            auth=access_token,
            -1512        )
            -1513
            -1514    async def remove_friend_request(self, access_token: str, /, member_id: int) -> None:
            -1515        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            -1516        await self._request(
            -1517            RequestMethod.POST,
            -1518            f"Social/Friends/Requests/Remove/{member_id}",
            -1519            auth=access_token,
            -1520        )
            -1521
            -1522    async def approve_all_pending_group_users(
            -1523        self,
            -1524        access_token: str,
            -1525        /,
            -1526        group_id: int,
            -1527        message: undefined.UndefinedOr[str] = undefined.Undefined,
            -1528    ) -> None:
            -1529        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            -1530        await self._request(
            -1531            RequestMethod.POST,
            -1532            f"GroupV2/{group_id}/Members/ApproveAll",
            -1533            auth=access_token,
            -1534            json={"message": str(message)},
            -1535        )
            -1536
            -1537    async def deny_all_pending_group_users(
            -1538        self,
            -1539        access_token: str,
            -1540        /,
            -1541        group_id: int,
            -1542        *,
            -1543        message: undefined.UndefinedOr[str] = undefined.Undefined,
            -1544    ) -> None:
            -1545        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            -1546        await self._request(
            -1547            RequestMethod.POST,
            -1548            f"GroupV2/{group_id}/Members/DenyAll",
            -1549            auth=access_token,
            -1550            json={"message": str(message)},
            -1551        )
            -1552
            -1553    async def add_optional_conversation(
            -1554        self,
            -1555        access_token: str,
            -1556        /,
            -1557        group_id: int,
            -1558        *,
            -1559        name: undefined.UndefinedOr[str] = undefined.Undefined,
            -1560        security: typing.Literal[0, 1] = 0,
            -1561    ) -> None:
            -1562        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            -1563        payload = {"chatName": str(name), "chatSecurity": security}
            -1564        await self._request(
            -1565            RequestMethod.POST,
            -1566            f"GroupV2/{group_id}/OptionalConversations/Add",
            -1567            json=payload,
            -1568            auth=access_token,
            -1569        )
            -1570
            -1571    async def edit_optional_conversation(
            -1572        self,
            -1573        access_token: str,
            -1574        /,
            -1575        group_id: int,
            -1576        conversation_id: int,
            -1577        *,
            -1578        name: undefined.UndefinedOr[str] = undefined.Undefined,
            -1579        security: typing.Literal[0, 1] = 0,
            -1580        enable_chat: bool = False,
            -1581    ) -> None:
            -1582        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            -1583        payload = {
            -1584            "chatEnabled": enable_chat,
            -1585            "chatName": str(name),
            -1586            "chatSecurity": security,
            -1587        }
            -1588        await self._request(
            -1589            RequestMethod.POST,
            -1590            f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}",
            -1591            json=payload,
            -1592            auth=access_token,
            -1593        )
            -1594
            -1595    async def transfer_item(
            -1596        self,
            -1597        access_token: str,
            -1598        /,
            -1599        item_id: int,
            -1600        item_hash: int,
            -1601        character_id: int,
            -1602        member_type: typedefs.IntAnd[enums.MembershipType],
            -1603        *,
            -1604        stack_size: int = 1,
            -1605        vault: bool = False,
            -1606    ) -> None:
            -1607        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            -1608        payload = {
            -1609            "characterId": character_id,
            -1610            "membershipType": int(member_type),
            -1611            "itemId": item_id,
            -1612            "itemReferenceHash": item_hash,
            -1613            "stackSize": stack_size,
            -1614            "transferToVault": vault,
            -1615        }
            -1616        await self._request(
            -1617            RequestMethod.POST,
            -1618            "Destiny2/Actions/Items/TransferItem",
            -1619            json=payload,
            -1620            auth=access_token,
            -1621        )
            -1622
            -1623    async def pull_item(
            -1624        self,
            -1625        access_token: str,
            -1626        /,
            -1627        item_id: int,
            -1628        item_hash: int,
            -1629        character_id: int,
            -1630        member_type: typedefs.IntAnd[enums.MembershipType],
            -1631        *,
            -1632        stack_size: int = 1,
            -1633        vault: bool = False,
            -1634    ) -> None:
            -1635        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            -1636        payload = {
            -1637            "characterId": character_id,
            -1638            "membershipType": int(member_type),
            -1639            "itemId": item_id,
            -1640            "itemReferenceHash": item_hash,
            -1641            "stackSize": stack_size,
            -1642            "transferToVault": vault,
            -1643        }
            -1644        await self._request(
            -1645            RequestMethod.POST,
            -1646            "Destiny2/Actions/Items/PullFromPostmaster",
            -1647            json=payload,
            -1648            auth=access_token,
            -1649        )
            -1650
            -1651    async def fetch_fireteams(
            -1652        self,
            -1653        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
            -1654        *,
            -1655        platform: typedefs.IntAnd[
            -1656            fireteams.FireteamPlatform
            -1657        ] = fireteams.FireteamPlatform.ANY,
            -1658        language: typing.Union[
            -1659            fireteams.FireteamLanguage, str
            -1660        ] = fireteams.FireteamLanguage.ALL,
            -1661        date_range: typedefs.IntAnd[
            -1662            fireteams.FireteamDate
            -1663        ] = fireteams.FireteamDate.ALL,
            -1664        page: int = 0,
            -1665        slots_filter: int = 0,
            -1666    ) -> typedefs.JSONObject:
            -1667        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1668        resp = await self._request(
            -1669            RequestMethod.GET,
            -1670            f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}",  # noqa: E501 Line too long
            -1671        )
            -1672        assert isinstance(resp, dict)
            -1673        return resp
            -1674
            -1675    async def fetch_avaliable_clan_fireteams(
            -1676        self,
            -1677        access_token: str,
            -1678        group_id: int,
            -1679        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
            -1680        *,
            -1681        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
            -1682        language: typing.Union[fireteams.FireteamLanguage, str],
            -1683        date_range: typedefs.IntAnd[
            -1684            fireteams.FireteamDate
            -1685        ] = fireteams.FireteamDate.ALL,
            -1686        page: int = 0,
            -1687        public_only: bool = False,
            -1688        slots_filter: int = 0,
            -1689    ) -> typedefs.JSONObject:
            -1690        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1691        resp = await self._request(
            -1692            RequestMethod.GET,
            -1693            f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}",  # noqa: E501
            -1694            json={"langFilter": str(language)},
            +1270    async def equip_item(
            +1271        self,
            +1272        access_token: str,
            +1273        /,
            +1274        item_id: int,
            +1275        character_id: int,
            +1276        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1277    ) -> None:
            +1278        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1279        payload = {
            +1280            "itemId": item_id,
            +1281            "characterId": character_id,
            +1282            "membershipType": int(membership_type),
            +1283        }
            +1284
            +1285        await self._request(
            +1286            RequestMethod.POST,
            +1287            "Destiny2/Actions/Items/EquipItem/",
            +1288            json=payload,
            +1289            auth=access_token,
            +1290        )
            +1291
            +1292    async def equip_items(
            +1293        self,
            +1294        access_token: str,
            +1295        /,
            +1296        item_ids: list[int],
            +1297        character_id: int,
            +1298        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1299    ) -> None:
            +1300        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1301        payload = {
            +1302            "itemIds": item_ids,
            +1303            "characterId": character_id,
            +1304            "membershipType": int(membership_type),
            +1305        }
            +1306        await self._request(
            +1307            RequestMethod.POST,
            +1308            "Destiny2/Actions/Items/EquipItems/",
            +1309            json=payload,
            +1310            auth=access_token,
            +1311        )
            +1312
            +1313    async def ban_clan_member(
            +1314        self,
            +1315        access_token: str,
            +1316        /,
            +1317        group_id: int,
            +1318        membership_id: int,
            +1319        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1320        *,
            +1321        length: int = 0,
            +1322        comment: undefined.UndefinedOr[str] = undefined.Undefined,
            +1323    ) -> None:
            +1324        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1325        payload = {"comment": str(comment), "length": length}
            +1326        await self._request(
            +1327            RequestMethod.POST,
            +1328            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/",
            +1329            json=payload,
            +1330            auth=access_token,
            +1331        )
            +1332
            +1333    async def unban_clan_member(
            +1334        self,
            +1335        access_token: str,
            +1336        /,
            +1337        group_id: int,
            +1338        membership_id: int,
            +1339        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1340    ) -> None:
            +1341        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1342        await self._request(
            +1343            RequestMethod.POST,
            +1344            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/",
            +1345            auth=access_token,
            +1346        )
            +1347
            +1348    async def kick_clan_member(
            +1349        self,
            +1350        access_token: str,
            +1351        /,
            +1352        group_id: int,
            +1353        membership_id: int,
            +1354        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1355    ) -> typedefs.JSONObject:
            +1356        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1357        resp = await self._request(
            +1358            RequestMethod.POST,
            +1359            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/",
            +1360            auth=access_token,
            +1361        )
            +1362        assert isinstance(resp, dict)
            +1363        return resp
            +1364
            +1365    async def edit_clan(
            +1366        self,
            +1367        access_token: str,
            +1368        /,
            +1369        group_id: int,
            +1370        *,
            +1371        name: typedefs.NoneOr[str] = None,
            +1372        about: typedefs.NoneOr[str] = None,
            +1373        motto: typedefs.NoneOr[str] = None,
            +1374        theme: typedefs.NoneOr[str] = None,
            +1375        tags: typedefs.NoneOr[collections.Sequence[str]] = None,
            +1376        is_public: typedefs.NoneOr[bool] = None,
            +1377        locale: typedefs.NoneOr[str] = None,
            +1378        avatar_image_index: typedefs.NoneOr[int] = None,
            +1379        membership_option: typedefs.NoneOr[
            +1380            typedefs.IntAnd[enums.MembershipOption]
            +1381        ] = None,
            +1382        allow_chat: typedefs.NoneOr[bool] = None,
            +1383        chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None,
            +1384        call_sign: typedefs.NoneOr[str] = None,
            +1385        homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
            +1386        enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None,
            +1387        default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
            +1388        is_public_topic_admin: typedefs.NoneOr[bool] = None,
            +1389    ) -> None:
            +1390        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1391        payload = {
            +1392            "name": name,
            +1393            "about": about,
            +1394            "motto": motto,
            +1395            "theme": theme,
            +1396            "tags": tags,
            +1397            "isPublic": is_public,
            +1398            "avatarImageIndex": avatar_image_index,
            +1399            "isPublicTopicAdminOnly": is_public_topic_admin,
            +1400            "allowChat": allow_chat,
            +1401            "chatSecurity": chat_security,
            +1402            "callsign": call_sign,
            +1403            "homepage": homepage,
            +1404            "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins,
            +1405            "defaultPublicity": default_publicity,
            +1406            "locale": locale,
            +1407        }
            +1408        if membership_option is not None:
            +1409            payload["membershipOption"] = int(membership_option)
            +1410
            +1411        await self._request(
            +1412            RequestMethod.POST,
            +1413            f"GroupV2/{group_id}/Edit",
            +1414            json=payload,
            +1415            auth=access_token,
            +1416        )
            +1417
            +1418    async def edit_clan_options(
            +1419        self,
            +1420        access_token: str,
            +1421        /,
            +1422        group_id: int,
            +1423        *,
            +1424        invite_permissions_override: typedefs.NoneOr[bool] = None,
            +1425        update_culture_permissionOverride: typedefs.NoneOr[bool] = None,
            +1426        host_guided_game_permission_override: typedefs.NoneOr[
            +1427            typing.Literal[0, 1, 2]
            +1428        ] = None,
            +1429        update_banner_permission_override: typedefs.NoneOr[bool] = None,
            +1430        join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None,
            +1431    ) -> None:
            +1432
            +1433        payload = {
            +1434            "InvitePermissionOverride": invite_permissions_override,
            +1435            "UpdateCulturePermissionOverride": update_culture_permissionOverride,
            +1436            "HostGuidedGamePermissionOverride": host_guided_game_permission_override,
            +1437            "UpdateBannerPermissionOverride": update_banner_permission_override,
            +1438            "JoinLevel": int(join_level) if join_level else None,
            +1439        }
            +1440
            +1441        await self._request(
            +1442            RequestMethod.POST,
            +1443            f"GroupV2/{group_id}/EditFounderOptions",
            +1444            json=payload,
            +1445            auth=access_token,
            +1446        )
            +1447
            +1448    async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject:
            +1449        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1450        resp = await self._request(
            +1451            RequestMethod.GET,
            +1452            "Social/Friends/",
            +1453            auth=access_token,
            +1454        )
            +1455        assert isinstance(resp, dict)
            +1456        return resp
            +1457
            +1458    async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject:
            +1459        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1460        resp = await self._request(
            +1461            RequestMethod.GET,
            +1462            "Social/Friends/Requests",
            +1463            auth=access_token,
            +1464        )
            +1465        assert isinstance(resp, dict)
            +1466        return resp
            +1467
            +1468    async def accept_friend_request(self, access_token: str, /, member_id: int) -> None:
            +1469        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1470        await self._request(
            +1471            RequestMethod.POST,
            +1472            f"Social/Friends/Requests/Accept/{member_id}",
            +1473            auth=access_token,
            +1474        )
            +1475
            +1476    async def send_friend_request(self, access_token: str, /, member_id: int) -> None:
            +1477        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1478        await self._request(
            +1479            RequestMethod.POST,
            +1480            f"Social/Friends/Add/{member_id}",
            +1481            auth=access_token,
            +1482        )
            +1483
            +1484    async def decline_friend_request(
            +1485        self, access_token: str, /, member_id: int
            +1486    ) -> None:
            +1487        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1488        await self._request(
            +1489            RequestMethod.POST,
            +1490            f"Social/Friends/Requests/Decline/{member_id}",
            +1491            auth=access_token,
            +1492        )
            +1493
            +1494    async def remove_friend(self, access_token: str, /, member_id: int) -> None:
            +1495        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1496        await self._request(
            +1497            RequestMethod.POST,
            +1498            f"Social/Friends/Remove/{member_id}",
            +1499            auth=access_token,
            +1500        )
            +1501
            +1502    async def remove_friend_request(self, access_token: str, /, member_id: int) -> None:
            +1503        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            +1504        await self._request(
            +1505            RequestMethod.POST,
            +1506            f"Social/Friends/Requests/Remove/{member_id}",
            +1507            auth=access_token,
            +1508        )
            +1509
            +1510    async def approve_all_pending_group_users(
            +1511        self,
            +1512        access_token: str,
            +1513        /,
            +1514        group_id: int,
            +1515        message: undefined.UndefinedOr[str] = undefined.Undefined,
            +1516    ) -> None:
            +1517        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            +1518        await self._request(
            +1519            RequestMethod.POST,
            +1520            f"GroupV2/{group_id}/Members/ApproveAll",
            +1521            auth=access_token,
            +1522            json={"message": str(message)},
            +1523        )
            +1524
            +1525    async def deny_all_pending_group_users(
            +1526        self,
            +1527        access_token: str,
            +1528        /,
            +1529        group_id: int,
            +1530        *,
            +1531        message: undefined.UndefinedOr[str] = undefined.Undefined,
            +1532    ) -> None:
            +1533        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            +1534        await self._request(
            +1535            RequestMethod.POST,
            +1536            f"GroupV2/{group_id}/Members/DenyAll",
            +1537            auth=access_token,
            +1538            json={"message": str(message)},
            +1539        )
            +1540
            +1541    async def add_optional_conversation(
            +1542        self,
            +1543        access_token: str,
            +1544        /,
            +1545        group_id: int,
            +1546        *,
            +1547        name: undefined.UndefinedOr[str] = undefined.Undefined,
            +1548        security: typing.Literal[0, 1] = 0,
            +1549    ) -> None:
            +1550        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            +1551        payload = {"chatName": str(name), "chatSecurity": security}
            +1552        await self._request(
            +1553            RequestMethod.POST,
            +1554            f"GroupV2/{group_id}/OptionalConversations/Add",
            +1555            json=payload,
            +1556            auth=access_token,
            +1557        )
            +1558
            +1559    async def edit_optional_conversation(
            +1560        self,
            +1561        access_token: str,
            +1562        /,
            +1563        group_id: int,
            +1564        conversation_id: int,
            +1565        *,
            +1566        name: undefined.UndefinedOr[str] = undefined.Undefined,
            +1567        security: typing.Literal[0, 1] = 0,
            +1568        enable_chat: bool = False,
            +1569    ) -> None:
            +1570        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            +1571        payload = {
            +1572            "chatEnabled": enable_chat,
            +1573            "chatName": str(name),
            +1574            "chatSecurity": security,
            +1575        }
            +1576        await self._request(
            +1577            RequestMethod.POST,
            +1578            f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}",
            +1579            json=payload,
            +1580            auth=access_token,
            +1581        )
            +1582
            +1583    async def transfer_item(
            +1584        self,
            +1585        access_token: str,
            +1586        /,
            +1587        item_id: int,
            +1588        item_hash: int,
            +1589        character_id: int,
            +1590        member_type: typedefs.IntAnd[enums.MembershipType],
            +1591        *,
            +1592        stack_size: int = 1,
            +1593        vault: bool = False,
            +1594    ) -> None:
            +1595        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            +1596        payload = {
            +1597            "characterId": character_id,
            +1598            "membershipType": int(member_type),
            +1599            "itemId": item_id,
            +1600            "itemReferenceHash": item_hash,
            +1601            "stackSize": stack_size,
            +1602            "transferToVault": vault,
            +1603        }
            +1604        await self._request(
            +1605            RequestMethod.POST,
            +1606            "Destiny2/Actions/Items/TransferItem",
            +1607            json=payload,
            +1608            auth=access_token,
            +1609        )
            +1610
            +1611    async def pull_item(
            +1612        self,
            +1613        access_token: str,
            +1614        /,
            +1615        item_id: int,
            +1616        item_hash: int,
            +1617        character_id: int,
            +1618        member_type: typedefs.IntAnd[enums.MembershipType],
            +1619        *,
            +1620        stack_size: int = 1,
            +1621        vault: bool = False,
            +1622    ) -> None:
            +1623        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
            +1624        payload = {
            +1625            "characterId": character_id,
            +1626            "membershipType": int(member_type),
            +1627            "itemId": item_id,
            +1628            "itemReferenceHash": item_hash,
            +1629            "stackSize": stack_size,
            +1630            "transferToVault": vault,
            +1631        }
            +1632        await self._request(
            +1633            RequestMethod.POST,
            +1634            "Destiny2/Actions/Items/PullFromPostmaster",
            +1635            json=payload,
            +1636            auth=access_token,
            +1637        )
            +1638
            +1639    async def fetch_fireteams(
            +1640        self,
            +1641        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
            +1642        *,
            +1643        platform: typedefs.IntAnd[
            +1644            fireteams.FireteamPlatform
            +1645        ] = fireteams.FireteamPlatform.ANY,
            +1646        language: typing.Union[
            +1647            fireteams.FireteamLanguage, str
            +1648        ] = fireteams.FireteamLanguage.ALL,
            +1649        date_range: typedefs.IntAnd[
            +1650            fireteams.FireteamDate
            +1651        ] = fireteams.FireteamDate.ALL,
            +1652        page: int = 0,
            +1653        slots_filter: int = 0,
            +1654    ) -> typedefs.JSONObject:
            +1655        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1656        resp = await self._request(
            +1657            RequestMethod.GET,
            +1658            f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}",  # noqa: E501 Line too long
            +1659        )
            +1660        assert isinstance(resp, dict)
            +1661        return resp
            +1662
            +1663    async def fetch_avaliable_clan_fireteams(
            +1664        self,
            +1665        access_token: str,
            +1666        group_id: int,
            +1667        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
            +1668        *,
            +1669        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
            +1670        language: typing.Union[fireteams.FireteamLanguage, str],
            +1671        date_range: typedefs.IntAnd[
            +1672            fireteams.FireteamDate
            +1673        ] = fireteams.FireteamDate.ALL,
            +1674        page: int = 0,
            +1675        public_only: bool = False,
            +1676        slots_filter: int = 0,
            +1677    ) -> typedefs.JSONObject:
            +1678        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1679        resp = await self._request(
            +1680            RequestMethod.GET,
            +1681            f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}",  # noqa: E501
            +1682            json={"langFilter": str(language)},
            +1683            auth=access_token,
            +1684        )
            +1685        assert isinstance(resp, dict)
            +1686        return resp
            +1687
            +1688    async def fetch_clan_fireteam(
            +1689        self, access_token: str, fireteam_id: int, group_id: int
            +1690    ) -> typedefs.JSONObject:
            +1691        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1692        resp = await self._request(
            +1693            RequestMethod.GET,
            +1694            f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}",
             1695            auth=access_token,
             1696        )
             1697        assert isinstance(resp, dict)
             1698        return resp
             1699
            -1700    async def fetch_clan_fireteam(
            -1701        self, access_token: str, fireteam_id: int, group_id: int
            -1702    ) -> typedefs.JSONObject:
            -1703        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1704        resp = await self._request(
            -1705            RequestMethod.GET,
            -1706            f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}",
            -1707            auth=access_token,
            -1708        )
            -1709        assert isinstance(resp, dict)
            -1710        return resp
            -1711
            -1712    async def fetch_my_clan_fireteams(
            -1713        self,
            -1714        access_token: str,
            -1715        group_id: int,
            -1716        *,
            -1717        include_closed: bool = True,
            -1718        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
            -1719        language: typing.Union[fireteams.FireteamLanguage, str],
            -1720        filtered: bool = True,
            -1721        page: int = 0,
            -1722    ) -> typedefs.JSONObject:
            -1723        payload = {"groupFilter": filtered, "langFilter": str(language)}
            -1724        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1725        resp = await self._request(
            -1726            RequestMethod.GET,
            -1727            f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}",
            -1728            json=payload,
            +1700    async def fetch_my_clan_fireteams(
            +1701        self,
            +1702        access_token: str,
            +1703        group_id: int,
            +1704        *,
            +1705        include_closed: bool = True,
            +1706        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
            +1707        language: typing.Union[fireteams.FireteamLanguage, str],
            +1708        filtered: bool = True,
            +1709        page: int = 0,
            +1710    ) -> typedefs.JSONObject:
            +1711        payload = {"groupFilter": filtered, "langFilter": str(language)}
            +1712        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1713        resp = await self._request(
            +1714            RequestMethod.GET,
            +1715            f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}",
            +1716            json=payload,
            +1717            auth=access_token,
            +1718        )
            +1719        assert isinstance(resp, dict)
            +1720        return resp
            +1721
            +1722    async def fetch_private_clan_fireteams(
            +1723        self, access_token: str, group_id: int, /
            +1724    ) -> int:
            +1725        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1726        resp = await self._request(
            +1727            RequestMethod.GET,
            +1728            f"Fireteam/Clan/{group_id}/ActiveCount",
             1729            auth=access_token,
             1730        )
            -1731        assert isinstance(resp, dict)
            +1731        assert isinstance(resp, int)
             1732        return resp
             1733
            -1734    async def fetch_private_clan_fireteams(
            -1735        self, access_token: str, group_id: int, /
            -1736    ) -> int:
            -1737        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1738        resp = await self._request(
            -1739            RequestMethod.GET,
            -1740            f"Fireteam/Clan/{group_id}/ActiveCount",
            -1741            auth=access_token,
            -1742        )
            -1743        assert isinstance(resp, int)
            -1744        return resp
            -1745
            -1746    async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject:
            -1747        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1748        resp = await self._request(
            -1749            RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}"
            +1734    async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject:
            +1735        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1736        resp = await self._request(
            +1737            RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}"
            +1738        )
            +1739        assert isinstance(resp, dict)
            +1740        return resp
            +1741
            +1742    async def search_entities(
            +1743        self, name: str, entity_type: str, *, page: int = 0
            +1744    ) -> typedefs.JSONObject:
            +1745        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1746        resp = await self._request(
            +1747            RequestMethod.GET,
            +1748            f"Destiny2/Armory/Search/{entity_type}/{name}/",
            +1749            json={"page": page},
             1750        )
             1751        assert isinstance(resp, dict)
             1752        return resp
             1753
            -1754    async def search_entities(
            -1755        self, name: str, entity_type: str, *, page: int = 0
            -1756    ) -> typedefs.JSONObject:
            -1757        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1758        resp = await self._request(
            -1759            RequestMethod.GET,
            -1760            f"Destiny2/Armory/Search/{entity_type}/{name}/",
            -1761            json={"page": page},
            -1762        )
            -1763        assert isinstance(resp, dict)
            -1764        return resp
            -1765
            -1766    async def fetch_unique_weapon_history(
            -1767        self,
            -1768        membership_id: int,
            -1769        character_id: int,
            -1770        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1771    ) -> typedefs.JSONObject:
            -1772        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1773        resp = await self._request(
            -1774            RequestMethod.GET,
            -1775            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/",
            -1776        )
            -1777        assert isinstance(resp, dict)
            -1778        return resp
            -1779
            -1780    async def fetch_item(
            -1781        self,
            -1782        member_id: int,
            -1783        item_id: int,
            -1784        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1785        components: list[enums.ComponentType],
            -1786    ) -> typedefs.JSONObject:
            -1787        collector = _collect_components(components)
            -1788        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1789        resp = await self._request(
            -1790            RequestMethod.GET,
            -1791            f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}",
            -1792        )
            -1793        assert isinstance(resp, dict)
            -1794        return resp
            -1795
            -1796    async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject:
            -1797        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1798        resp = await self._request(
            -1799            RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/"
            -1800        )
            -1801        assert isinstance(resp, dict)
            -1802        return resp
            -1803
            -1804    async def fetch_available_locales(self) -> typedefs.JSONObject:
            -1805        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1806        resp = await self._request(
            -1807            RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/"
            -1808        )
            +1754    async def fetch_unique_weapon_history(
            +1755        self,
            +1756        membership_id: int,
            +1757        character_id: int,
            +1758        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1759    ) -> typedefs.JSONObject:
            +1760        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1761        resp = await self._request(
            +1762            RequestMethod.GET,
            +1763            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/",
            +1764        )
            +1765        assert isinstance(resp, dict)
            +1766        return resp
            +1767
            +1768    async def fetch_item(
            +1769        self,
            +1770        member_id: int,
            +1771        item_id: int,
            +1772        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1773        components: list[enums.ComponentType],
            +1774    ) -> typedefs.JSONObject:
            +1775        collector = _collect_components(components)
            +1776        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1777        resp = await self._request(
            +1778            RequestMethod.GET,
            +1779            f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}",
            +1780        )
            +1781        assert isinstance(resp, dict)
            +1782        return resp
            +1783
            +1784    async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject:
            +1785        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1786        resp = await self._request(
            +1787            RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/"
            +1788        )
            +1789        assert isinstance(resp, dict)
            +1790        return resp
            +1791
            +1792    async def fetch_available_locales(self) -> typedefs.JSONObject:
            +1793        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1794        resp = await self._request(
            +1795            RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/"
            +1796        )
            +1797        assert isinstance(resp, dict)
            +1798        return resp
            +1799
            +1800    async def fetch_common_settings(self) -> typedefs.JSONObject:
            +1801        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1802        resp = await self._request(RequestMethod.GET, "Settings")
            +1803        assert isinstance(resp, dict)
            +1804        return resp
            +1805
            +1806    async def fetch_user_systems_overrides(self) -> typedefs.JSONObject:
            +1807        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1808        resp = await self._request(RequestMethod.GET, "UserSystemOverrides")
             1809        assert isinstance(resp, dict)
             1810        return resp
             1811
            -1812    async def fetch_common_settings(self) -> typedefs.JSONObject:
            -1813        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1814        resp = await self._request(RequestMethod.GET, "Settings")
            -1815        assert isinstance(resp, dict)
            -1816        return resp
            -1817
            -1818    async def fetch_user_systems_overrides(self) -> typedefs.JSONObject:
            -1819        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1820        resp = await self._request(RequestMethod.GET, "UserSystemOverrides")
            -1821        assert isinstance(resp, dict)
            -1822        return resp
            -1823
            -1824    async def fetch_global_alerts(
            -1825        self, *, include_streaming: bool = False
            -1826    ) -> typedefs.JSONArray:
            -1827        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1828        resp = await self._request(
            -1829            RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}"
            -1830        )
            -1831        assert isinstance(resp, list)
            -1832        return resp
            +1812    async def fetch_global_alerts(
            +1813        self, *, include_streaming: bool = False
            +1814    ) -> typedefs.JSONArray:
            +1815        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1816        resp = await self._request(
            +1817            RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}"
            +1818        )
            +1819        assert isinstance(resp, list)
            +1820        return resp
            +1821
            +1822    async def awainitialize_request(
            +1823        self,
            +1824        access_token: str,
            +1825        type: typing.Literal[0, 1],
            +1826        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1827        /,
            +1828        *,
            +1829        affected_item_id: typing.Optional[int] = None,
            +1830        character_id: typing.Optional[int] = None,
            +1831    ) -> typedefs.JSONObject:
            +1832        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
             1833
            -1834    async def awainitialize_request(
            -1835        self,
            -1836        access_token: str,
            -1837        type: typing.Literal[0, 1],
            -1838        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1839        /,
            -1840        *,
            -1841        affected_item_id: typing.Optional[int] = None,
            -1842        character_id: typing.Optional[int] = None,
            -1843    ) -> typedefs.JSONObject:
            -1844        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1845
            -1846        body = {"type": type, "membershipType": int(membership_type)}
            +1834        body = {"type": type, "membershipType": int(membership_type)}
            +1835
            +1836        if affected_item_id is not None:
            +1837            body["affectedItemId"] = affected_item_id
            +1838
            +1839        if character_id is not None:
            +1840            body["characterId"] = character_id
            +1841
            +1842        resp = await self._request(
            +1843            RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token
            +1844        )
            +1845        assert isinstance(resp, dict)
            +1846        return resp
             1847
            -1848        if affected_item_id is not None:
            -1849            body["affectedItemId"] = affected_item_id
            -1850
            -1851        if character_id is not None:
            -1852            body["characterId"] = character_id
            -1853
            -1854        resp = await self._request(
            -1855            RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token
            +1848    async def awaget_action_token(
            +1849        self, access_token: str, correlation_id: str, /
            +1850    ) -> typedefs.JSONObject:
            +1851        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1852        resp = await self._request(
            +1853            RequestMethod.POST,
            +1854            f"Destiny2/Awa/GetActionToken/{correlation_id}",
            +1855            auth=access_token,
             1856        )
             1857        assert isinstance(resp, dict)
             1858        return resp
             1859
            -1860    async def awaget_action_token(
            -1861        self, access_token: str, correlation_id: str, /
            -1862    ) -> typedefs.JSONObject:
            -1863        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1864        resp = await self._request(
            -1865            RequestMethod.POST,
            -1866            f"Destiny2/Awa/GetActionToken/{correlation_id}",
            -1867            auth=access_token,
            -1868        )
            -1869        assert isinstance(resp, dict)
            -1870        return resp
            -1871
            -1872    async def awa_provide_authorization_result(
            -1873        self,
            -1874        access_token: str,
            -1875        selection: int,
            -1876        correlation_id: str,
            -1877        nonce: collections.MutableSequence[typing.Union[str, bytes]],
            -1878    ) -> int:
            -1879        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1880
            -1881        body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce}
            -1882
            -1883        resp = await self._request(
            -1884            RequestMethod.POST,
            -1885            "Destiny2/Awa/AwaProvideAuthorizationResult",
            -1886            json=body,
            -1887            auth=access_token,
            -1888        )
            -1889        assert isinstance(resp, int)
            -1890        return resp
            -1891
            -1892    async def fetch_vendors(
            -1893        self,
            -1894        access_token: str,
            -1895        character_id: int,
            -1896        membership_id: int,
            -1897        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1898        /,
            -1899        components: list[enums.ComponentType],
            -1900        filter: typing.Optional[int] = None,
            -1901    ) -> typedefs.JSONObject:
            -1902        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1903        components_ = _collect_components(components)
            -1904        route = (
            -1905            f"Destiny2/{int(membership_type)}/Profile/{membership_id}"
            -1906            f"/Character/{character_id}/Vendors/?components={components_}"
            -1907        )
            -1908
            -1909        if filter is not None:
            -1910            route = route + f"&filter={filter}"
            -1911
            -1912        resp = await self._request(
            -1913            RequestMethod.GET,
            -1914            route,
            -1915            auth=access_token,
            -1916        )
            -1917        assert isinstance(resp, dict)
            -1918        return resp
            -1919
            -1920    async def fetch_vendor(
            -1921        self,
            -1922        access_token: str,
            -1923        character_id: int,
            -1924        membership_id: int,
            -1925        membership_type: typedefs.IntAnd[enums.MembershipType],
            -1926        vendor_hash: int,
            -1927        /,
            -1928        components: list[enums.ComponentType],
            -1929    ) -> typedefs.JSONObject:
            -1930        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -1931        components_ = _collect_components(components)
            -1932        resp = await self._request(
            -1933            RequestMethod.GET,
            -1934            (
            -1935                f"Platform/Destiny2/{int(membership_type)}/Profile/{membership_id}"
            -1936                f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}"
            -1937            ),
            -1938            auth=access_token,
            -1939        )
            -1940        assert isinstance(resp, dict)
            -1941        return resp
            -1942
            -1943    async def fetch_application_api_usage(
            -1944        self,
            -1945        access_token: str,
            -1946        application_id: int,
            -1947        /,
            -1948        *,
            -1949        start: typing.Optional[datetime.datetime] = None,
            -1950        end: typing.Optional[datetime.datetime] = None,
            -1951    ) -> typedefs.JSONObject:
            -1952
            -1953        end_date, start_date = time.parse_date_range(end, start)
            -1954        resp = await self._request(
            -1955            RequestMethod.GET,
            -1956            f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}",
            -1957            auth=access_token,
            -1958        )
            -1959        assert isinstance(resp, dict)
            -1960        return resp
            -1961
            -1962    async def fetch_bungie_applications(self) -> typedefs.JSONArray:
            -1963        resp = await self._request(RequestMethod.GET, "App/FirstParty")
            -1964        assert isinstance(resp, list)
            -1965        return resp
            -1966
            -1967    async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject:
            -1968        resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/")
            -1969        assert isinstance(resp, dict)
            -1970        return resp
            -1971
            -1972    async def fetch_content_by_id(
            -1973        self, id: int, locale: str, /, *, head: bool = False
            -1974    ) -> typedefs.JSONObject:
            -1975        resp = await self._request(
            -1976            RequestMethod.GET,
            -1977            f"Content/GetContentById/{id}/{locale}/",
            -1978            json={"head": head},
            -1979        )
            -1980        assert isinstance(resp, dict)
            -1981        return resp
            -1982
            -1983    async def fetch_content_by_tag_and_type(
            -1984        self, locale: str, tag: str, type: str, *, head: bool = False
            -1985    ) -> typedefs.JSONObject:
            -1986        resp = await self._request(
            -1987            RequestMethod.GET,
            -1988            f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/",
            -1989            json={"head": head},
            -1990        )
            -1991        assert isinstance(resp, dict)
            -1992        return resp
            +1860    async def awa_provide_authorization_result(
            +1861        self,
            +1862        access_token: str,
            +1863        selection: int,
            +1864        correlation_id: str,
            +1865        nonce: collections.MutableSequence[typing.Union[str, bytes]],
            +1866    ) -> int:
            +1867        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1868
            +1869        body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce}
            +1870
            +1871        resp = await self._request(
            +1872            RequestMethod.POST,
            +1873            "Destiny2/Awa/AwaProvideAuthorizationResult",
            +1874            json=body,
            +1875            auth=access_token,
            +1876        )
            +1877        assert isinstance(resp, int)
            +1878        return resp
            +1879
            +1880    async def fetch_vendors(
            +1881        self,
            +1882        access_token: str,
            +1883        character_id: int,
            +1884        membership_id: int,
            +1885        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1886        /,
            +1887        components: list[enums.ComponentType],
            +1888        filter: typing.Optional[int] = None,
            +1889    ) -> typedefs.JSONObject:
            +1890        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1891        components_ = _collect_components(components)
            +1892        route = (
            +1893            f"Destiny2/{int(membership_type)}/Profile/{membership_id}"
            +1894            f"/Character/{character_id}/Vendors/?components={components_}"
            +1895        )
            +1896
            +1897        if filter is not None:
            +1898            route = route + f"&filter={filter}"
            +1899
            +1900        resp = await self._request(
            +1901            RequestMethod.GET,
            +1902            route,
            +1903            auth=access_token,
            +1904        )
            +1905        assert isinstance(resp, dict)
            +1906        return resp
            +1907
            +1908    async def fetch_vendor(
            +1909        self,
            +1910        access_token: str,
            +1911        character_id: int,
            +1912        membership_id: int,
            +1913        membership_type: typedefs.IntAnd[enums.MembershipType],
            +1914        vendor_hash: int,
            +1915        /,
            +1916        components: list[enums.ComponentType],
            +1917    ) -> typedefs.JSONObject:
            +1918        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +1919        components_ = _collect_components(components)
            +1920        resp = await self._request(
            +1921            RequestMethod.GET,
            +1922            (
            +1923                f"Platform/Destiny2/{int(membership_type)}/Profile/{membership_id}"
            +1924                f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}"
            +1925            ),
            +1926            auth=access_token,
            +1927        )
            +1928        assert isinstance(resp, dict)
            +1929        return resp
            +1930
            +1931    async def fetch_application_api_usage(
            +1932        self,
            +1933        access_token: str,
            +1934        application_id: int,
            +1935        /,
            +1936        *,
            +1937        start: typing.Optional[datetime.datetime] = None,
            +1938        end: typing.Optional[datetime.datetime] = None,
            +1939    ) -> typedefs.JSONObject:
            +1940
            +1941        end_date, start_date = time.parse_date_range(end, start)
            +1942        resp = await self._request(
            +1943            RequestMethod.GET,
            +1944            f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}",
            +1945            auth=access_token,
            +1946        )
            +1947        assert isinstance(resp, dict)
            +1948        return resp
            +1949
            +1950    async def fetch_bungie_applications(self) -> typedefs.JSONArray:
            +1951        resp = await self._request(RequestMethod.GET, "App/FirstParty")
            +1952        assert isinstance(resp, list)
            +1953        return resp
            +1954
            +1955    async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject:
            +1956        resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/")
            +1957        assert isinstance(resp, dict)
            +1958        return resp
            +1959
            +1960    async def fetch_content_by_id(
            +1961        self, id: int, locale: str, /, *, head: bool = False
            +1962    ) -> typedefs.JSONObject:
            +1963        resp = await self._request(
            +1964            RequestMethod.GET,
            +1965            f"Content/GetContentById/{id}/{locale}/",
            +1966            json={"head": head},
            +1967        )
            +1968        assert isinstance(resp, dict)
            +1969        return resp
            +1970
            +1971    async def fetch_content_by_tag_and_type(
            +1972        self, locale: str, tag: str, type: str, *, head: bool = False
            +1973    ) -> typedefs.JSONObject:
            +1974        resp = await self._request(
            +1975            RequestMethod.GET,
            +1976            f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/",
            +1977            json={"head": head},
            +1978        )
            +1979        assert isinstance(resp, dict)
            +1980        return resp
            +1981
            +1982    async def search_content_with_text(
            +1983        self,
            +1984        locale: str,
            +1985        /,
            +1986        content_type: str,
            +1987        search_text: str,
            +1988        tag: str,
            +1989        *,
            +1990        page: undefined.UndefinedOr[int] = undefined.Undefined,
            +1991        source: undefined.UndefinedOr[str] = undefined.Undefined,
            +1992    ) -> typedefs.JSONObject:
             1993
            -1994    async def search_content_with_text(
            -1995        self,
            -1996        locale: str,
            -1997        /,
            -1998        content_type: str,
            -1999        search_text: str,
            -2000        tag: str,
            -2001        *,
            -2002        page: undefined.UndefinedOr[int] = undefined.Undefined,
            -2003        source: undefined.UndefinedOr[str] = undefined.Undefined,
            -2004    ) -> typedefs.JSONObject:
            -2005
            -2006        body: typedefs.JSONObject = {}
            -2007
            -2008        body["ctype"] = content_type
            -2009        body["searchtext"] = search_text
            -2010        body["tag"] = tag
            -2011
            -2012        if page is not undefined.Undefined:
            -2013            body["currentpage"] = page
            -2014        else:
            -2015            body["currentpage"] = 1
            -2016
            -2017        if source is not undefined.Undefined:
            -2018            body["source"] = source
            -2019        else:
            -2020            source = ""
            -2021        resp = await self._request(
            -2022            RequestMethod.GET, f"Content/Search/{locale}/", json=body
            -2023        )
            -2024        assert isinstance(resp, dict)
            -2025        return resp
            -2026
            -2027    async def search_content_by_tag_and_type(
            -2028        self,
            -2029        locale: str,
            -2030        tag: str,
            -2031        type: str,
            -2032        *,
            -2033        page: undefined.UndefinedOr[int] = undefined.Undefined,
            -2034    ) -> typedefs.JSONObject:
            -2035        body: typedefs.JSONObject = {}
            -2036        body["currentpage"] = 1 if page is undefined.Undefined else page
            -2037        resp = await self._request(
            -2038            RequestMethod.GET,
            -2039            f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/",
            -2040            json=body,
            -2041        )
            -2042        assert isinstance(resp, dict)
            -2043        return resp
            -2044
            -2045    async def search_help_articles(
            -2046        self, text: str, size: str, /
            -2047    ) -> typedefs.JSONObject:
            -2048        resp = await self._request(
            -2049            RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/"
            -2050        )
            -2051        assert isinstance(resp, dict)
            -2052        return resp
            +1994        body: typedefs.JSONObject = {}
            +1995
            +1996        body["ctype"] = content_type
            +1997        body["searchtext"] = search_text
            +1998        body["tag"] = tag
            +1999
            +2000        if page is not undefined.Undefined:
            +2001            body["currentpage"] = page
            +2002        else:
            +2003            body["currentpage"] = 1
            +2004
            +2005        if source is not undefined.Undefined:
            +2006            body["source"] = source
            +2007        else:
            +2008            source = ""
            +2009        resp = await self._request(
            +2010            RequestMethod.GET, f"Content/Search/{locale}/", json=body
            +2011        )
            +2012        assert isinstance(resp, dict)
            +2013        return resp
            +2014
            +2015    async def search_content_by_tag_and_type(
            +2016        self,
            +2017        locale: str,
            +2018        tag: str,
            +2019        type: str,
            +2020        *,
            +2021        page: undefined.UndefinedOr[int] = undefined.Undefined,
            +2022    ) -> typedefs.JSONObject:
            +2023        body: typedefs.JSONObject = {}
            +2024        body["currentpage"] = 1 if page is undefined.Undefined else page
            +2025        resp = await self._request(
            +2026            RequestMethod.GET,
            +2027            f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/",
            +2028            json=body,
            +2029        )
            +2030        assert isinstance(resp, dict)
            +2031        return resp
            +2032
            +2033    async def search_help_articles(
            +2034        self, text: str, size: str, /
            +2035    ) -> typedefs.JSONObject:
            +2036        resp = await self._request(
            +2037            RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/"
            +2038        )
            +2039        assert isinstance(resp, dict)
            +2040        return resp
            +2041
            +2042    async def fetch_topics_page(
            +2043        self,
            +2044        category_filter: int,
            +2045        group: int,
            +2046        date_filter: int,
            +2047        sort: typing.Union[str, bytes],
            +2048        *,
            +2049        page: undefined.UndefinedOr[int] = undefined.Undefined,
            +2050        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
            +2051        tag_filter: undefined.UndefinedOr[str] = undefined.Undefined,
            +2052    ) -> typedefs.JSONObject:
             2053
            -2054    async def fetch_topics_page(
            -2055        self,
            -2056        category_filter: int,
            -2057        group: int,
            -2058        date_filter: int,
            -2059        sort: typing.Union[str, bytes],
            -2060        *,
            -2061        page: undefined.UndefinedOr[int] = undefined.Undefined,
            -2062        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
            -2063        tag_filter: undefined.UndefinedOr[str] = undefined.Undefined,
            -2064    ) -> typedefs.JSONObject:
            -2065
            -2066        body: typedefs.JSONObject = {}
            -2067        if locales is not undefined.Undefined:
            -2068            body["locales"] = ",".join(str(locales))
            -2069        else:
            -2070            body["locales"] = ",".join([])
            -2071
            -2072        if tag_filter is not undefined.Undefined:
            -2073            body["tagstring"] = tag_filter
            -2074        else:
            -2075            body["tagstring"] = ""
            -2076
            -2077        page = 0 if page is not undefined.Undefined else page
            -2078
            -2079        resp = await self._request(
            -2080            RequestMethod.GET,
            -2081            f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/",
            -2082            json=body,
            -2083        )
            -2084        assert isinstance(resp, dict)
            -2085        return resp
            -2086
            -2087    async def fetch_core_topics_page(
            -2088        self,
            -2089        category_filter: int,
            -2090        date_filter: int,
            -2091        sort: typing.Union[str, bytes],
            -2092        *,
            -2093        page: undefined.UndefinedOr[int] = undefined.Undefined,
            -2094        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
            -2095    ) -> typedefs.JSONObject:
            -2096        body: typedefs.JSONObject = {}
            -2097
            -2098        if locales is not undefined.Undefined:
            -2099            body["locales"] = ",".join(str(locales))
            -2100        else:
            -2101            body["locales"] = ",".join([])
            -2102
            -2103        resp = await self._request(
            -2104            RequestMethod.GET,
            -2105            f"Forum/GetCoreTopicsPaged/{0 if page is undefined.Undefined else page}"
            -2106            f"/{sort!s}/{date_filter}/{category_filter}/",
            -2107            json=body,
            -2108        )
            -2109        assert isinstance(resp, dict)
            -2110        return resp
            -2111
            -2112    async def fetch_posts_threaded_page(
            -2113        self,
            -2114        parent_post: bool,
            -2115        page: int,
            -2116        page_size: int,
            -2117        parent_post_id: int,
            -2118        reply_size: int,
            -2119        root_thread_mode: bool,
            -2120        sort_mode: int,
            -2121        show_banned: typing.Optional[str] = None,
            -2122    ) -> typedefs.JSONObject:
            -2123        resp = await self._request(
            -2124            RequestMethod.GET,
            -2125            f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/"
            -2126            f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/",
            -2127            json={"showbanned": show_banned},
            -2128        )
            -2129        assert isinstance(resp, dict)
            -2130        return resp
            -2131
            -2132    async def fetch_posts_threaded_page_from_child(
            -2133        self,
            -2134        child_id: bool,
            -2135        page: int,
            -2136        page_size: int,
            -2137        reply_size: int,
            -2138        root_thread_mode: bool,
            -2139        sort_mode: int,
            -2140        show_banned: typing.Optional[str] = None,
            +2054        body: typedefs.JSONObject = {}
            +2055        if locales is not undefined.Undefined:
            +2056            body["locales"] = ",".join(str(locales))
            +2057        else:
            +2058            body["locales"] = ",".join([])
            +2059
            +2060        if tag_filter is not undefined.Undefined:
            +2061            body["tagstring"] = tag_filter
            +2062        else:
            +2063            body["tagstring"] = ""
            +2064
            +2065        page = 0 if page is not undefined.Undefined else page
            +2066
            +2067        resp = await self._request(
            +2068            RequestMethod.GET,
            +2069            f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/",
            +2070            json=body,
            +2071        )
            +2072        assert isinstance(resp, dict)
            +2073        return resp
            +2074
            +2075    async def fetch_core_topics_page(
            +2076        self,
            +2077        category_filter: int,
            +2078        date_filter: int,
            +2079        sort: typing.Union[str, bytes],
            +2080        *,
            +2081        page: undefined.UndefinedOr[int] = undefined.Undefined,
            +2082        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
            +2083    ) -> typedefs.JSONObject:
            +2084        body: typedefs.JSONObject = {}
            +2085
            +2086        if locales is not undefined.Undefined:
            +2087            body["locales"] = ",".join(str(locales))
            +2088        else:
            +2089            body["locales"] = ",".join([])
            +2090
            +2091        resp = await self._request(
            +2092            RequestMethod.GET,
            +2093            f"Forum/GetCoreTopicsPaged/{0 if page is undefined.Undefined else page}"
            +2094            f"/{sort!s}/{date_filter}/{category_filter}/",
            +2095            json=body,
            +2096        )
            +2097        assert isinstance(resp, dict)
            +2098        return resp
            +2099
            +2100    async def fetch_posts_threaded_page(
            +2101        self,
            +2102        parent_post: bool,
            +2103        page: int,
            +2104        page_size: int,
            +2105        parent_post_id: int,
            +2106        reply_size: int,
            +2107        root_thread_mode: bool,
            +2108        sort_mode: int,
            +2109        show_banned: typing.Optional[str] = None,
            +2110    ) -> typedefs.JSONObject:
            +2111        resp = await self._request(
            +2112            RequestMethod.GET,
            +2113            f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/"
            +2114            f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/",
            +2115            json={"showbanned": show_banned},
            +2116        )
            +2117        assert isinstance(resp, dict)
            +2118        return resp
            +2119
            +2120    async def fetch_posts_threaded_page_from_child(
            +2121        self,
            +2122        child_id: bool,
            +2123        page: int,
            +2124        page_size: int,
            +2125        reply_size: int,
            +2126        root_thread_mode: bool,
            +2127        sort_mode: int,
            +2128        show_banned: typing.Optional[str] = None,
            +2129    ) -> typedefs.JSONObject:
            +2130        resp = await self._request(
            +2131            RequestMethod.GET,
            +2132            f"Forum/GetPostsThreadedPagedFromChild/{child_id}/"
            +2133            f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/",
            +2134            json={"showbanned": show_banned},
            +2135        )
            +2136        assert isinstance(resp, dict)
            +2137        return resp
            +2138
            +2139    async def fetch_post_and_parent(
            +2140        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
             2141    ) -> typedefs.JSONObject:
             2142        resp = await self._request(
             2143            RequestMethod.GET,
            -2144            f"Forum/GetPostsThreadedPagedFromChild/{child_id}/"
            -2145            f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/",
            -2146            json={"showbanned": show_banned},
            -2147        )
            -2148        assert isinstance(resp, dict)
            -2149        return resp
            -2150
            -2151    async def fetch_post_and_parent(
            -2152        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
            -2153    ) -> typedefs.JSONObject:
            -2154        resp = await self._request(
            -2155            RequestMethod.GET,
            -2156            f"Forum/GetPostAndParent/{child_id}/",
            -2157            json={"showbanned": show_banned},
            -2158        )
            -2159        assert isinstance(resp, dict)
            -2160        return resp
            -2161
            -2162    async def fetch_posts_and_parent_awaiting(
            -2163        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
            -2164    ) -> typedefs.JSONObject:
            -2165        resp = await self._request(
            -2166            RequestMethod.GET,
            -2167            f"Forum/GetPostAndParentAwaitingApproval/{child_id}/",
            -2168            json={"showbanned": show_banned},
            -2169        )
            -2170        assert isinstance(resp, dict)
            -2171        return resp
            -2172
            -2173    async def fetch_topic_for_content(self, content_id: int, /) -> int:
            -2174        resp = await self._request(
            -2175            RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/"
            -2176        )
            -2177        assert isinstance(resp, int)
            -2178        return resp
            -2179
            -2180    async def fetch_forum_tag_suggestions(
            -2181        self, partial_tag: str, /
            -2182    ) -> typedefs.JSONObject:
            -2183        resp = await self._request(
            -2184            RequestMethod.GET,
            -2185            "Forum/GetForumTagSuggestions/",
            -2186            json={"partialtag": partial_tag},
            -2187        )
            -2188        assert isinstance(resp, dict)
            -2189        return resp
            -2190
            -2191    async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject:
            -2192        resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/")
            -2193        assert isinstance(resp, dict)
            -2194        return resp
            -2195
            -2196    async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray:
            -2197        resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/")
            -2198        assert isinstance(resp, list)
            -2199        return resp
            -2200
            -2201    async def fetch_recommended_groups(
            -2202        self,
            -2203        accecss_token: str,
            -2204        /,
            -2205        *,
            -2206        date_range: int = 0,
            -2207        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            -2208    ) -> typedefs.JSONArray:
            -2209        resp = await self._request(
            -2210            RequestMethod.POST,
            -2211            f"GroupV2/Recommended/{int(group_type)}/{date_range}/",
            -2212            auth=accecss_token,
            -2213        )
            -2214        assert isinstance(resp, list)
            -2215        return resp
            -2216
            -2217    async def fetch_available_avatars(self) -> collections.Mapping[str, int]:
            -2218        resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/")
            -2219        assert isinstance(resp, dict)
            -2220        return resp
            -2221
            -2222    async def fetch_user_clan_invite_setting(
            -2223        self,
            -2224        access_token: str,
            -2225        /,
            -2226        membership_type: typedefs.IntAnd[enums.MembershipType],
            -2227    ) -> bool:
            -2228        resp = await self._request(
            -2229            RequestMethod.GET,
            -2230            f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/",
            -2231            auth=access_token,
            -2232        )
            -2233        assert isinstance(resp, bool)
            -2234        return resp
            -2235
            -2236    async def fetch_banned_group_members(
            -2237        self, access_token: str, group_id: int, /, *, page: int = 1
            -2238    ) -> typedefs.JSONObject:
            -2239        resp = await self._request(
            -2240            RequestMethod.GET,
            -2241            f"GroupV2/{group_id}/Banned/?currentpage={page}",
            -2242            auth=access_token,
            -2243        )
            -2244        assert isinstance(resp, dict)
            -2245        return resp
            -2246
            -2247    async def fetch_pending_group_memberships(
            -2248        self, access_token: str, group_id: int, /, *, current_page: int = 1
            -2249    ) -> typedefs.JSONObject:
            -2250        resp = await self._request(
            -2251            RequestMethod.GET,
            -2252            f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}",
            -2253            auth=access_token,
            -2254        )
            -2255        assert isinstance(resp, dict)
            -2256        return resp
            -2257
            -2258    async def fetch_invited_group_memberships(
            -2259        self, access_token: str, group_id: int, /, *, current_page: int = 1
            -2260    ) -> typedefs.JSONObject:
            -2261        resp = await self._request(
            -2262            RequestMethod.GET,
            -2263            f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}",
            -2264            auth=access_token,
            -2265        )
            -2266        assert isinstance(resp, dict)
            -2267        return resp
            -2268
            -2269    async def invite_member_to_group(
            -2270        self,
            -2271        access_token: str,
            -2272        /,
            -2273        group_id: int,
            -2274        membership_id: int,
            -2275        membership_type: typedefs.IntAnd[enums.MembershipType],
            -2276        *,
            -2277        message: undefined.UndefinedOr[str] = undefined.Undefined,
            -2278    ) -> typedefs.JSONObject:
            -2279        resp = await self._request(
            -2280            RequestMethod.POST,
            -2281            f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/",
            -2282            auth=access_token,
            -2283            json={"message": str(message)},
            -2284        )
            -2285        assert isinstance(resp, dict)
            -2286        return resp
            -2287
            -2288    async def cancel_group_member_invite(
            -2289        self,
            -2290        access_token: str,
            -2291        /,
            -2292        group_id: int,
            -2293        membership_id: int,
            -2294        membership_type: typedefs.IntAnd[enums.MembershipType],
            -2295    ) -> typedefs.JSONObject:
            -2296        resp = await self._request(
            -2297            RequestMethod.POST,
            -2298            f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/",
            -2299            auth=access_token,
            -2300        )
            -2301        assert isinstance(resp, dict)
            -2302        return resp
            -2303
            -2304    async def fetch_historical_definition(self) -> typedefs.JSONObject:
            -2305        resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/")
            -2306        assert isinstance(resp, dict)
            -2307        return resp
            -2308
            -2309    async def fetch_historical_stats(
            -2310        self,
            -2311        character_id: int,
            -2312        membership_id: int,
            -2313        membership_type: typedefs.IntAnd[enums.MembershipType],
            -2314        day_start: datetime.datetime,
            -2315        day_end: datetime.datetime,
            -2316        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
            -2317        modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]],
            -2318        *,
            -2319        period_type: enums.PeriodType = enums.PeriodType.ALL_TIME,
            -2320    ) -> typedefs.JSONObject:
            -2321
            -2322        end, start = time.parse_date_range(day_end, day_start)
            -2323        resp = await self._request(
            -2324            RequestMethod.GET,
            -2325            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/",
            -2326            json={
            -2327                "dayend": end,
            -2328                "daystart": start,
            -2329                "groups": [str(int(group)) for group in groups],
            -2330                "modes": [str(int(mode)) for mode in modes],
            -2331                "periodType": int(period_type),
            -2332            },
            -2333        )
            -2334        assert isinstance(resp, dict)
            -2335        return resp
            -2336
            -2337    async def fetch_historical_stats_for_account(
            -2338        self,
            -2339        membership_id: int,
            -2340        membership_type: typedefs.IntAnd[enums.MembershipType],
            -2341        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
            -2342    ) -> typedefs.JSONObject:
            -2343        resp = await self._request(
            -2344            RequestMethod.GET,
            -2345            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/",
            -2346            json={"groups": [str(int(group)) for group in groups]},
            -2347        )
            -2348        assert isinstance(resp, dict)
            -2349        return resp
            -2350
            -2351    async def fetch_aggregated_activity_stats(
            -2352        self,
            -2353        character_id: int,
            -2354        membership_id: int,
            -2355        membership_type: typedefs.IntAnd[enums.MembershipType],
            -2356        /,
            -2357    ) -> typedefs.JSONObject:
            -2358        resp = await self._request(
            -2359            RequestMethod.GET,
            -2360            f"Destiny2/{int(membership_type)}/Account/{membership_id}/"
            -2361            f"Character/{character_id}/Stats/AggregateActivityStats/",
            -2362        )
            -2363        assert isinstance(resp, dict)
            -2364        return resp
            +2144            f"Forum/GetPostAndParent/{child_id}/",
            +2145            json={"showbanned": show_banned},
            +2146        )
            +2147        assert isinstance(resp, dict)
            +2148        return resp
            +2149
            +2150    async def fetch_posts_and_parent_awaiting(
            +2151        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
            +2152    ) -> typedefs.JSONObject:
            +2153        resp = await self._request(
            +2154            RequestMethod.GET,
            +2155            f"Forum/GetPostAndParentAwaitingApproval/{child_id}/",
            +2156            json={"showbanned": show_banned},
            +2157        )
            +2158        assert isinstance(resp, dict)
            +2159        return resp
            +2160
            +2161    async def fetch_topic_for_content(self, content_id: int, /) -> int:
            +2162        resp = await self._request(
            +2163            RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/"
            +2164        )
            +2165        assert isinstance(resp, int)
            +2166        return resp
            +2167
            +2168    async def fetch_forum_tag_suggestions(
            +2169        self, partial_tag: str, /
            +2170    ) -> typedefs.JSONObject:
            +2171        resp = await self._request(
            +2172            RequestMethod.GET,
            +2173            "Forum/GetForumTagSuggestions/",
            +2174            json={"partialtag": partial_tag},
            +2175        )
            +2176        assert isinstance(resp, dict)
            +2177        return resp
            +2178
            +2179    async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject:
            +2180        resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/")
            +2181        assert isinstance(resp, dict)
            +2182        return resp
            +2183
            +2184    async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray:
            +2185        resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/")
            +2186        assert isinstance(resp, list)
            +2187        return resp
            +2188
            +2189    async def fetch_recommended_groups(
            +2190        self,
            +2191        accecss_token: str,
            +2192        /,
            +2193        *,
            +2194        date_range: int = 0,
            +2195        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            +2196    ) -> typedefs.JSONArray:
            +2197        resp = await self._request(
            +2198            RequestMethod.POST,
            +2199            f"GroupV2/Recommended/{int(group_type)}/{date_range}/",
            +2200            auth=accecss_token,
            +2201        )
            +2202        assert isinstance(resp, list)
            +2203        return resp
            +2204
            +2205    async def fetch_available_avatars(self) -> collections.Mapping[str, int]:
            +2206        resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/")
            +2207        assert isinstance(resp, dict)
            +2208        return resp
            +2209
            +2210    async def fetch_user_clan_invite_setting(
            +2211        self,
            +2212        access_token: str,
            +2213        /,
            +2214        membership_type: typedefs.IntAnd[enums.MembershipType],
            +2215    ) -> bool:
            +2216        resp = await self._request(
            +2217            RequestMethod.GET,
            +2218            f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/",
            +2219            auth=access_token,
            +2220        )
            +2221        assert isinstance(resp, bool)
            +2222        return resp
            +2223
            +2224    async def fetch_banned_group_members(
            +2225        self, access_token: str, group_id: int, /, *, page: int = 1
            +2226    ) -> typedefs.JSONObject:
            +2227        resp = await self._request(
            +2228            RequestMethod.GET,
            +2229            f"GroupV2/{group_id}/Banned/?currentpage={page}",
            +2230            auth=access_token,
            +2231        )
            +2232        assert isinstance(resp, dict)
            +2233        return resp
            +2234
            +2235    async def fetch_pending_group_memberships(
            +2236        self, access_token: str, group_id: int, /, *, current_page: int = 1
            +2237    ) -> typedefs.JSONObject:
            +2238        resp = await self._request(
            +2239            RequestMethod.GET,
            +2240            f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}",
            +2241            auth=access_token,
            +2242        )
            +2243        assert isinstance(resp, dict)
            +2244        return resp
            +2245
            +2246    async def fetch_invited_group_memberships(
            +2247        self, access_token: str, group_id: int, /, *, current_page: int = 1
            +2248    ) -> typedefs.JSONObject:
            +2249        resp = await self._request(
            +2250            RequestMethod.GET,
            +2251            f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}",
            +2252            auth=access_token,
            +2253        )
            +2254        assert isinstance(resp, dict)
            +2255        return resp
            +2256
            +2257    async def invite_member_to_group(
            +2258        self,
            +2259        access_token: str,
            +2260        /,
            +2261        group_id: int,
            +2262        membership_id: int,
            +2263        membership_type: typedefs.IntAnd[enums.MembershipType],
            +2264        *,
            +2265        message: undefined.UndefinedOr[str] = undefined.Undefined,
            +2266    ) -> typedefs.JSONObject:
            +2267        resp = await self._request(
            +2268            RequestMethod.POST,
            +2269            f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/",
            +2270            auth=access_token,
            +2271            json={"message": str(message)},
            +2272        )
            +2273        assert isinstance(resp, dict)
            +2274        return resp
            +2275
            +2276    async def cancel_group_member_invite(
            +2277        self,
            +2278        access_token: str,
            +2279        /,
            +2280        group_id: int,
            +2281        membership_id: int,
            +2282        membership_type: typedefs.IntAnd[enums.MembershipType],
            +2283    ) -> typedefs.JSONObject:
            +2284        resp = await self._request(
            +2285            RequestMethod.POST,
            +2286            f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/",
            +2287            auth=access_token,
            +2288        )
            +2289        assert isinstance(resp, dict)
            +2290        return resp
            +2291
            +2292    async def fetch_historical_definition(self) -> typedefs.JSONObject:
            +2293        resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/")
            +2294        assert isinstance(resp, dict)
            +2295        return resp
            +2296
            +2297    async def fetch_historical_stats(
            +2298        self,
            +2299        character_id: int,
            +2300        membership_id: int,
            +2301        membership_type: typedefs.IntAnd[enums.MembershipType],
            +2302        day_start: datetime.datetime,
            +2303        day_end: datetime.datetime,
            +2304        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
            +2305        modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]],
            +2306        *,
            +2307        period_type: enums.PeriodType = enums.PeriodType.ALL_TIME,
            +2308    ) -> typedefs.JSONObject:
            +2309
            +2310        end, start = time.parse_date_range(day_end, day_start)
            +2311        resp = await self._request(
            +2312            RequestMethod.GET,
            +2313            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/",
            +2314            json={
            +2315                "dayend": end,
            +2316                "daystart": start,
            +2317                "groups": [str(int(group)) for group in groups],
            +2318                "modes": [str(int(mode)) for mode in modes],
            +2319                "periodType": int(period_type),
            +2320            },
            +2321        )
            +2322        assert isinstance(resp, dict)
            +2323        return resp
            +2324
            +2325    async def fetch_historical_stats_for_account(
            +2326        self,
            +2327        membership_id: int,
            +2328        membership_type: typedefs.IntAnd[enums.MembershipType],
            +2329        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
            +2330    ) -> typedefs.JSONObject:
            +2331        resp = await self._request(
            +2332            RequestMethod.GET,
            +2333            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/",
            +2334            json={"groups": [str(int(group)) for group in groups]},
            +2335        )
            +2336        assert isinstance(resp, dict)
            +2337        return resp
            +2338
            +2339    async def fetch_aggregated_activity_stats(
            +2340        self,
            +2341        character_id: int,
            +2342        membership_id: int,
            +2343        membership_type: typedefs.IntAnd[enums.MembershipType],
            +2344        /,
            +2345    ) -> typedefs.JSONObject:
            +2346        resp = await self._request(
            +2347            RequestMethod.GET,
            +2348            f"Destiny2/{int(membership_type)}/Account/{membership_id}/"
            +2349            f"Character/{character_id}/Stats/AggregateActivityStats/",
            +2350        )
            +2351        assert isinstance(resp, dict)
            +2352        return resp
             
            @@ -4843,7 +4818,8 @@

            Example
            -
            import aiobungie
            +
            +
            import aiobungie
             
             async def main():
                 async with aiobungie.RESTClient("TOKEN") as rest_client:
            @@ -4852,7 +4828,8 @@ 
            Example
            for member in clan_members: for k, v in member['destinyUserInfo'].items(): print(k, v) -
            +
            +
            Parameters
            @@ -4898,27 +4875,27 @@
            Logging Levels
            -
            425    def __init__(
            -426        self,
            -427        token: str,
            -428        /,
            -429        client_secret: typing.Optional[str] = None,
            -430        client_id: typing.Optional[int] = None,
            -431        *,
            -432        max_retries: int = 4,
            -433        max_ratelimit_retries: int = 3,
            -434        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
            -435    ) -> None:
            -436        self._session: typing.Optional[_Session] = None
            -437        self._lock: typing.Optional[asyncio.Lock] = None
            -438        self._client_secret = client_secret
            -439        self._client_id = client_id
            -440        self._token: str = token
            -441        self._max_retries = max_retries
            -442        self._max_rate_limit_retries = max_ratelimit_retries
            -443        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
            -444
            -445        self._set_debug_level(enable_debugging)
            +            
            423    def __init__(
            +424        self,
            +425        token: str,
            +426        /,
            +427        client_secret: typing.Optional[str] = None,
            +428        client_id: typing.Optional[int] = None,
            +429        *,
            +430        max_retries: int = 4,
            +431        max_ratelimit_retries: int = 3,
            +432        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
            +433    ) -> None:
            +434        self._session: typing.Optional[_Session] = None
            +435        self._lock: typing.Optional[asyncio.Lock] = None
            +436        self._client_secret = client_secret
            +437        self._client_id = client_id
            +438        self._token: str = token
            +439        self._max_retries = max_retries
            +440        self._max_rate_limit_retries = max_ratelimit_retries
            +441        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
            +442
            +443        self._set_debug_level(enable_debugging)
             
            @@ -4952,7 +4929,8 @@
            Logging Levels
            Example
            -
            import aiobungie
            +
            +
            import aiobungie
             
             client = aiobungie.RESTClient(ā€¦)
             
            @@ -4967,7 +4945,8 @@ 
            Example
            # Use them to fetch your user. user = await client.fetch_current_user_memberships(tokens.access_token) -
            +
            +
            @@ -4997,11 +4976,11 @@
            Example
            -
            459    @typing.final
            -460    async def close(self) -> None:
            -461        session = self._get_session()
            -462        await session.close()
            -463        self._session = None
            +            
            457    @typing.final
            +458    async def close(self) -> None:
            +459        session = self._get_session()
            +460        await session.close()
            +461        self._session = None
             
            @@ -5030,19 +5009,13 @@
            Raises
            -
            465    @typing.final
            -466    def open(self) -> None:
            -467        """Open a new client session. This is called internally with contextmanager usage."""
            -468        if self.is_alive:
            -469            raise RuntimeError("Cannot open a new session while it's already open.")
            -470
            -471        self._session = _Session.create(
            -472            owner=False,
            -473            raise_status=False,
            -474            connect=None,
            -475            socket_read=None,
            -476            socket_connect=None,
            -477        )
            +            
            463    @typing.final
            +464    def open(self) -> None:
            +465        """Open a new client session. This is called internally with contextmanager usage."""
            +466        if self.is_alive:
            +467            raise RuntimeError("Cannot open a new session while it's already open.")
            +468
            +469        self._session = _Session.create(owner=False, raise_status=False)
             
            @@ -5063,14 +5036,14 @@
            Raises
            -
            479    @typing.final
            -480    def enable_debugging(
            -481        self,
            -482        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
            -483        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
            -484        /,
            -485    ) -> None:
            -486        self._set_debug_level(level, file)
            +            
            471    @typing.final
            +472    def enable_debugging(
            +473        self,
            +474        level: typing.Union[typing.Literal["TRACE"], bool, int] = False,
            +475        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
            +476        /,
            +477    ) -> None:
            +478        self._set_debug_level(level, file)
             
            @@ -5108,16 +5081,16 @@
            Parameters
            -
            488    @typing.final
            -489    async def static_request(
            -490        self,
            -491        method: typing.Union[RequestMethod, str],
            -492        path: str,
            -493        *,
            -494        auth: typing.Optional[str] = None,
            -495        json: typing.Optional[dict[str, typing.Any]] = None,
            -496    ) -> ResponseSig:
            -497        return await self._request(method, path, auth=auth, json=json)
            +            
            480    @typing.final
            +481    async def static_request(
            +482        self,
            +483        method: typing.Union[RequestMethod, str],
            +484        path: str,
            +485        *,
            +486        auth: typing.Optional[str] = None,
            +487        json: typing.Optional[dict[str, typing.Any]] = None,
            +488    ) -> ResponseSig:
            +489        return await self._request(method, path, auth=auth, json=json)
             
            @@ -5152,30 +5125,28 @@
            Returns
            @typing.final
            def - build_oauth2_url(self, client_id: Optional[int] = None) -> Optional[str]: + build_oauth2_url( self, client_id: Optional[int] = None) -> Optional[aiobungie.builders.OAuthURL]:
            -
            499    @typing.final
            -500    def build_oauth2_url(
            -501        self, client_id: typing.Optional[int] = None
            -502    ) -> typing.Optional[str]:
            -503        client_id = client_id or self._client_id
            -504        if client_id is None:
            -505            return None
            -506
            -507        return url.OAUTH2_EP_BUILDER.format(
            -508            oauth_endpoint=url.OAUTH_EP,
            -509            client_id=client_id,
            -510            uuid=_uuid(),
            -511        )
            +            
            491    @typing.final
            +492    def build_oauth2_url(
            +493        self, client_id: typing.Optional[int] = None
            +494    ) -> typing.Optional[builders.OAuthURL]:
            +495        client_id = client_id or self._client_id
            +496        if client_id is None:
            +497            return None
            +498
            +499        return builders.OAuthURL(client_id=client_id)
             

            Builds an OAuth2 URL using the provided user REST/Base client secret/id.

            +

            You can't get the complete string URL by using .compile() method.

            +
            Parameters
              @@ -5187,8 +5158,8 @@
              Parameters
              Returns
            @@ -5206,32 +5177,32 @@
            Returns
            -
            738    async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response:
            -739
            -740        if not isinstance(self._client_id, int):
            -741            raise TypeError(
            -742                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
            -743            )
            -744
            -745        if not isinstance(self._client_secret, str):
            -746            raise TypeError(
            -747                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
            -748            )
            -749
            -750        headers = {
            -751            "client_secret": self._client_secret,
            -752        }
            -753
            -754        data = (
            -755            f"grant_type=authorization_code&code={code}"
            -756            f"&client_id={self._client_id}&client_secret={self._client_secret}"
            -757        )
            -758
            -759        response = await self._request(
            -760            RequestMethod.POST, "", headers=headers, data=data, oauth2=True
            -761        )
            -762        assert isinstance(response, dict)
            -763        return builders.OAuth2Response.build_response(response)
            +            
            726    async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response:
            +727
            +728        if not isinstance(self._client_id, int):
            +729            raise TypeError(
            +730                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
            +731            )
            +732
            +733        if not isinstance(self._client_secret, str):
            +734            raise TypeError(
            +735                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
            +736            )
            +737
            +738        headers = {
            +739            "client_secret": self._client_secret,
            +740        }
            +741
            +742        data = (
            +743            f"grant_type=authorization_code&code={code}"
            +744            f"&client_id={self._client_id}&client_secret={self._client_secret}"
            +745        )
            +746
            +747        response = await self._request(
            +748            RequestMethod.POST, "", headers=headers, data=data, oauth2=True
            +749        )
            +750        assert isinstance(response, dict)
            +751        return builders.OAuth2Response.build_response(response)
             
            @@ -5270,30 +5241,30 @@
            Raises
            -
            765    async def refresh_access_token(
            -766        self, refresh_token: str, /
            -767    ) -> builders.OAuth2Response:
            -768        if not isinstance(self._client_id, int):
            -769            raise TypeError(
            -770                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
            -771            )
            -772
            -773        if not isinstance(self._client_secret, str):
            -774            raise TypeError(
            -775                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
            -776            )
            -777
            -778        data = {
            -779            "grant_type": "refresh_token",
            -780            "refresh_token": refresh_token,
            -781            "client_id": self._client_id,
            -782            "client_secret": self._client_secret,
            -783            "Content-Type": "application/x-www-form-urlencoded",
            -784        }
            -785
            -786        response = await self._request(RequestMethod.POST, "", data=data, oauth2=True)
            -787        assert isinstance(response, dict)
            -788        return builders.OAuth2Response.build_response(response)
            +            
            753    async def refresh_access_token(
            +754        self, refresh_token: str, /
            +755    ) -> builders.OAuth2Response:
            +756        if not isinstance(self._client_id, int):
            +757            raise TypeError(
            +758                f"Expected (int) for client id but got {type(self._client_id).__qualname__}"  # type: ignore
            +759            )
            +760
            +761        if not isinstance(self._client_secret, str):
            +762            raise TypeError(
            +763                f"Expected (str) for client secret but got {type(self._client_secret).__qualname__}"  # type: ignore
            +764            )
            +765
            +766        data = {
            +767            "grant_type": "refresh_token",
            +768            "refresh_token": refresh_token,
            +769            "client_id": self._client_id,
            +770            "client_secret": self._client_secret,
            +771            "Content-Type": "application/x-www-form-urlencoded",
            +772        }
            +773
            +774        response = await self._request(RequestMethod.POST, "", data=data, oauth2=True)
            +775        assert isinstance(response, dict)
            +776        return builders.OAuth2Response.build_response(response)
             
            @@ -5326,13 +5297,13 @@
            Returns
            -
            790    async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject:
            -791        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -792        resp = await self._request(
            -793            RequestMethod.GET, f"User/GetBungieNetUserById/{id}/"
            -794        )
            -795        assert isinstance(resp, dict)
            -796        return resp
            +            
            778    async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject:
            +779        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +780        resp = await self._request(
            +781            RequestMethod.GET, f"User/GetBungieNetUserById/{id}/"
            +782        )
            +783        assert isinstance(resp, dict)
            +784        return resp
             
            @@ -5371,11 +5342,11 @@
            Raises
            -
            798    async def fetch_user_themes(self) -> typedefs.JSONArray:
            -799        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -800        resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/")
            -801        assert isinstance(resp, list)
            -802        return resp
            +            
            786    async def fetch_user_themes(self) -> typedefs.JSONArray:
            +787        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +788        resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/")
            +789        assert isinstance(resp, list)
            +790        return resp
             
            @@ -5401,18 +5372,18 @@
            Returns
            -
            804    async def fetch_membership_from_id(
            -805        self,
            -806        id: int,
            -807        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
            -808        /,
            -809    ) -> typedefs.JSONObject:
            -810        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -811        resp = await self._request(
            -812            RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}"
            -813        )
            -814        assert isinstance(resp, dict)
            -815        return resp
            +            
            792    async def fetch_membership_from_id(
            +793        self,
            +794        id: int,
            +795        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
            +796        /,
            +797    ) -> typedefs.JSONObject:
            +798        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +799        resp = await self._request(
            +800            RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}"
            +801        )
            +802        assert isinstance(resp, dict)
            +803        return resp
             
            @@ -5453,21 +5424,21 @@
            Raises
            -
            817    async def fetch_player(
            -818        self,
            -819        name: str,
            -820        code: int,
            -821        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
            -822        /,
            -823    ) -> typedefs.JSONArray:
            -824        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -825        resp = await self._request(
            -826            RequestMethod.POST,
            -827            f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}",
            -828            json={"displayName": name, "displayNameCode": code},
            -829        )
            -830        assert isinstance(resp, list)
            -831        return resp
            +            
            805    async def fetch_player(
            +806        self,
            +807        name: str,
            +808        code: int,
            +809        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL,
            +810        /,
            +811    ) -> typedefs.JSONArray:
            +812        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +813        resp = await self._request(
            +814            RequestMethod.POST,
            +815            f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}",
            +816            json={"displayName": name, "displayNameCode": code},
            +817        )
            +818        assert isinstance(resp, list)
            +819        return resp
             
            @@ -5511,15 +5482,15 @@
            Raises
            -
            833    async def search_users(self, name: str, /) -> typedefs.JSONObject:
            -834        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -835        resp = await self._request(
            -836            RequestMethod.POST,
            -837            "User/Search/GlobalName/0",
            -838            json={"displayNamePrefix": name},
            -839        )
            -840        assert isinstance(resp, dict)
            -841        return resp
            +            
            821    async def search_users(self, name: str, /) -> typedefs.JSONObject:
            +822        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +823        resp = await self._request(
            +824            RequestMethod.POST,
            +825            "User/Search/GlobalName/0",
            +826            json={"displayNamePrefix": name},
            +827        )
            +828        assert isinstance(resp, dict)
            +829        return resp
             
            @@ -5558,15 +5529,15 @@
            Raises
            -
            843    async def fetch_clan_from_id(
            -844        self, id: int, /, access_token: typing.Optional[str] = None
            -845    ) -> typedefs.JSONObject:
            -846        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -847        resp = await self._request(
            -848            RequestMethod.GET, f"GroupV2/{id}", auth=access_token
            -849        )
            -850        assert isinstance(resp, dict)
            -851        return resp
            +            
            831    async def fetch_clan_from_id(
            +832        self, id: int, /, access_token: typing.Optional[str] = None
            +833    ) -> typedefs.JSONObject:
            +834        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +835        resp = await self._request(
            +836            RequestMethod.GET, f"GroupV2/{id}", auth=access_token
            +837        )
            +838        assert isinstance(resp, dict)
            +839        return resp
             
            @@ -5616,20 +5587,20 @@
            Raises
            -
            853    async def fetch_clan(
            -854        self,
            -855        name: str,
            -856        /,
            -857        access_token: typing.Optional[str] = None,
            -858        *,
            -859        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            -860    ) -> typedefs.JSONObject:
            -861        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -862        resp = await self._request(
            -863            RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token
            -864        )
            -865        assert isinstance(resp, dict)
            -866        return resp
            +            
            841    async def fetch_clan(
            +842        self,
            +843        name: str,
            +844        /,
            +845        access_token: typing.Optional[str] = None,
            +846        *,
            +847        type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            +848    ) -> typedefs.JSONObject:
            +849        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +850        resp = await self._request(
            +851            RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token
            +852        )
            +853        assert isinstance(resp, dict)
            +854        return resp
             
            @@ -5682,13 +5653,13 @@
            Raises
            -
            868    async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject:
            -869        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -870        resp = await self._request(
            -871            RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/"
            -872        )
            -873        assert isinstance(resp, dict)
            -874        return resp
            +            
            856    async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject:
            +857        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +858        resp = await self._request(
            +859            RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/"
            +860        )
            +861        assert isinstance(resp, dict)
            +862        return resp
             
            @@ -5727,13 +5698,13 @@
            Raises
            -
            876    async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray:
            -877        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -878        resp = await self._request(
            -879            RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/"
            -880        )
            -881        assert isinstance(resp, list)
            -882        return resp
            +            
            864    async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray:
            +865        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +866        resp = await self._request(
            +867            RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/"
            +868        )
            +869        assert isinstance(resp, list)
            +870        return resp
             
            @@ -5766,11 +5737,11 @@
            Returns
            -
            884    async def fetch_application(self, appid: int, /) -> typedefs.JSONObject:
            -885        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -886        resp = await self._request(RequestMethod.GET, f"App/Application/{appid}")
            -887        assert isinstance(resp, dict)
            -888        return resp
            +            
            872    async def fetch_application(self, appid: int, /) -> typedefs.JSONObject:
            +873        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +874        resp = await self._request(RequestMethod.GET, f"App/Application/{appid}")
            +875        assert isinstance(resp, dict)
            +876        return resp
             
            @@ -5803,24 +5774,24 @@
            Returns
            -
            890    async def fetch_character(
            -891        self,
            -892        member_id: int,
            -893        membership_type: typedefs.IntAnd[enums.MembershipType],
            -894        character_id: int,
            -895        components: list[enums.ComponentType],
            -896        auth: typing.Optional[str] = None,
            -897    ) -> typedefs.JSONObject:
            -898        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -899        collector = _collect_components(components)
            -900        response = await self._request(
            -901            RequestMethod.GET,
            -902            f"Destiny2/{int(membership_type)}/Profile/{member_id}/"
            -903            f"Character/{character_id}/?components={collector}",
            -904            auth=auth,
            -905        )
            -906        assert isinstance(response, dict)
            -907        return response
            +            
            878    async def fetch_character(
            +879        self,
            +880        member_id: int,
            +881        membership_type: typedefs.IntAnd[enums.MembershipType],
            +882        character_id: int,
            +883        components: list[enums.ComponentType],
            +884        auth: typing.Optional[str] = None,
            +885    ) -> typedefs.JSONObject:
            +886        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +887        collector = _collect_components(components)
            +888        response = await self._request(
            +889            RequestMethod.GET,
            +890            f"Destiny2/{int(membership_type)}/Profile/{member_id}/"
            +891            f"Character/{character_id}/?components={collector}",
            +892            auth=auth,
            +893        )
            +894        assert isinstance(response, dict)
            +895        return response
             
            @@ -5873,27 +5844,27 @@
            Raises
            -
            909    async def fetch_activities(
            -910        self,
            -911        member_id: int,
            -912        character_id: int,
            -913        mode: typedefs.IntAnd[enums.GameMode],
            -914        membership_type: typedefs.IntAnd[
            -915            enums.MembershipType
            -916        ] = enums.MembershipType.ALL,
            -917        *,
            -918        page: int = 0,
            -919        limit: int = 1,
            -920    ) -> typedefs.JSONObject:
            -921        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -922        resp = await self._request(
            -923            RequestMethod.GET,
            -924            f"Destiny2/{int(membership_type)}/Account/"
            -925            f"{member_id}/Character/{character_id}/Stats/Activities"
            -926            f"/?mode={int(mode)}&count={limit}&page={page}",
            -927        )
            -928        assert isinstance(resp, dict)
            -929        return resp
            +            
            897    async def fetch_activities(
            +898        self,
            +899        member_id: int,
            +900        character_id: int,
            +901        mode: typedefs.IntAnd[enums.GameMode],
            +902        membership_type: typedefs.IntAnd[
            +903            enums.MembershipType
            +904        ] = enums.MembershipType.ALL,
            +905        *,
            +906        page: int = 0,
            +907        limit: int = 1,
            +908    ) -> typedefs.JSONObject:
            +909        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +910        resp = await self._request(
            +911            RequestMethod.GET,
            +912            f"Destiny2/{int(membership_type)}/Account/"
            +913            f"{member_id}/Character/{character_id}/Stats/Activities"
            +914            f"/?mode={int(mode)}&count={limit}&page={page}",
            +915        )
            +916        assert isinstance(resp, dict)
            +917        return resp
             
            @@ -5948,14 +5919,14 @@
            Raises
            -
            931    async def fetch_vendor_sales(self) -> typedefs.JSONObject:
            -932        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -933        resp = await self._request(
            -934            RequestMethod.GET,
            -935            f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}",
            -936        )
            -937        assert isinstance(resp, dict)
            -938        return resp
            +            
            919    async def fetch_vendor_sales(self) -> typedefs.JSONObject:
            +920        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +921        resp = await self._request(
            +922            RequestMethod.GET,
            +923            f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}",
            +924        )
            +925        assert isinstance(resp, dict)
            +926        return resp
             
            @@ -5973,22 +5944,22 @@
            Raises
            -
            940    async def fetch_profile(
            -941        self,
            -942        membership_id: int,
            -943        type: typedefs.IntAnd[enums.MembershipType],
            -944        components: list[enums.ComponentType],
            -945        auth: typing.Optional[str] = None,
            -946    ) -> typedefs.JSONObject:
            -947        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -948        collector = _collect_components(components)
            -949        response = await self._request(
            -950            RequestMethod.GET,
            -951            f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}",
            -952            auth=auth,
            -953        )
            -954        assert isinstance(response, dict)
            -955        return response
            +            
            928    async def fetch_profile(
            +929        self,
            +930        membership_id: int,
            +931        type: typedefs.IntAnd[enums.MembershipType],
            +932        components: list[enums.ComponentType],
            +933        auth: typing.Optional[str] = None,
            +934    ) -> typedefs.JSONObject:
            +935        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +936        collector = _collect_components(components)
            +937        response = await self._request(
            +938            RequestMethod.GET,
            +939            f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}",
            +940            auth=auth,
            +941        )
            +942        assert isinstance(response, dict)
            +943        return response
             
            @@ -6039,13 +6010,13 @@
            Raises
            -
            957    async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject:
            -958        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -959        response = await self._request(
            -960            RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}"
            -961        )
            -962        assert isinstance(response, dict)
            -963        return response
            +            
            945    async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject:
            +946        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +947        response = await self._request(
            +948            RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}"
            +949        )
            +950        assert isinstance(response, dict)
            +951        return response
             
            @@ -6080,11 +6051,11 @@
            Returns
            -
            965    async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject:
            -966        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -967        resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash)
            -968        assert isinstance(resp, dict)
            -969        return resp
            +            
            953    async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject:
            +954        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +955        resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash)
            +956        assert isinstance(resp, dict)
            +957        return resp
             
            @@ -6117,11 +6088,11 @@
            Returns
            -
            971    async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject:
            -972        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            -973        resp = await self.fetch_entity("DestinyObjectiveDefinition", hash)
            -974        assert isinstance(resp, dict)
            -975        return resp
            +            
            959    async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject:
            +960        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
            +961        resp = await self.fetch_entity("DestinyObjectiveDefinition", hash)
            +962        assert isinstance(resp, dict)
            +963        return resp
             
            @@ -6154,21 +6125,21 @@
            Returns
            -
            977    async def fetch_groups_for_member(
            -978        self,
            -979        member_id: int,
            -980        member_type: typedefs.IntAnd[enums.MembershipType],
            -981        /,
            -982        *,
            -983        filter: int = 0,
            -984        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            -985    ) -> typedefs.JSONObject:
            -986        resp = await self._request(
            -987            RequestMethod.GET,
            -988            f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
            -989        )
            -990        assert isinstance(resp, dict)
            -991        return resp
            +            
            965    async def fetch_groups_for_member(
            +966        self,
            +967        member_id: int,
            +968        member_type: typedefs.IntAnd[enums.MembershipType],
            +969        /,
            +970        *,
            +971        filter: int = 0,
            +972        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
            +973    ) -> typedefs.JSONObject:
            +974        resp = await self._request(
            +975            RequestMethod.GET,
            +976            f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
            +977        )
            +978        assert isinstance(resp, dict)
            +979        return resp
             
            @@ -6190,7 +6161,7 @@
            Other Parameters
            Filter apply to list of joined groups. This Default to 0

          • group_type (aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. -This is always set to aiobungie.GroupType.CLAN and should not be changed.
          • +This is always set to aiobungie.GroupType.CLAN and should not be changed.
          Returns
          @@ -6213,21 +6184,21 @@
          Returns
          -
           993    async def fetch_potential_groups_for_member(
          - 994        self,
          - 995        member_id: int,
          - 996        member_type: typedefs.IntAnd[enums.MembershipType],
          - 997        /,
          - 998        *,
          - 999        filter: int = 0,
          -1000        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
          -1001    ) -> typedefs.JSONObject:
          -1002        resp = await self._request(
          -1003            RequestMethod.GET,
          -1004            f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
          -1005        )
          -1006        assert isinstance(resp, dict)
          -1007        return resp
          +            
          981    async def fetch_potential_groups_for_member(
          +982        self,
          +983        member_id: int,
          +984        member_type: typedefs.IntAnd[enums.MembershipType],
          +985        /,
          +986        *,
          +987        filter: int = 0,
          +988        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
          +989    ) -> typedefs.JSONObject:
          +990        resp = await self._request(
          +991            RequestMethod.GET,
          +992            f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/",
          +993        )
          +994        assert isinstance(resp, dict)
          +995        return resp
           
          @@ -6249,7 +6220,7 @@
          Other Parameters
          Filter apply to list of joined groups. This Default to 0
        • group_type (aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. -This is always set to aiobungie.GroupType.CLAN and should not be changed.
        • +This is always set to aiobungie.GroupType.CLAN and should not be changed.

        Returns
        @@ -6272,21 +6243,21 @@
        Returns
        -
        1009    async def fetch_clan_members(
        -1010        self,
        -1011        clan_id: int,
        -1012        /,
        -1013        *,
        -1014        name: typing.Optional[str] = None,
        -1015        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
        -1016    ) -> typedefs.JSONObject:
        -1017        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
        -1018        resp = await self._request(
        -1019            RequestMethod.GET,
        -1020            f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}&currentpage=1",
        -1021        )
        -1022        assert isinstance(resp, dict)
        -1023        return resp
        +            
         997    async def fetch_clan_members(
        + 998        self,
        + 999        clan_id: int,
        +1000        /,
        +1001        *,
        +1002        name: typing.Optional[str] = None,
        +1003        type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE,
        +1004    ) -> typedefs.JSONObject:
        +1005        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
        +1006        resp = await self._request(
        +1007            RequestMethod.GET,
        +1008            f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}&currentpage=1",
        +1009        )
        +1010        assert isinstance(resp, dict)
        +1011        return resp
         
        @@ -6306,7 +6277,7 @@
        Other Parameters
        If provided, Only players matching this name will be returned.
      • type (aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): An optional clan member's membership type. -Default is set to aiobungie.MembershipType.NONE +Default is set to aiobungie.MembershipType.NONE Which returns the first matched clan member by their name.
      @@ -6336,25 +6307,25 @@
      Raises
      -
      1025    async def fetch_hardlinked_credentials(
      -1026        self,
      -1027        credential: int,
      -1028        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
      -1029        /,
      -1030    ) -> typedefs.JSONObject:
      -1031        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1032        resp = await self._request(
      -1033            RequestMethod.GET,
      -1034            f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/",
      -1035        )
      -1036        assert isinstance(resp, dict)
      -1037        return resp
      +            
      1013    async def fetch_hardlinked_credentials(
      +1014        self,
      +1015        credential: int,
      +1016        type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID,
      +1017        /,
      +1018    ) -> typedefs.JSONObject:
      +1019        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1020        resp = await self._request(
      +1021            RequestMethod.GET,
      +1022            f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/",
      +1023        )
      +1024        assert isinstance(resp, dict)
      +1025        return resp
       

      Gets any hard linked membership given a credential.

      -

      Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now. +

      Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now. Cross Save aware.

      Parameters
      @@ -6387,16 +6358,16 @@
      Returns
      -
      1039    async def fetch_user_credentials(
      -1040        self, access_token: str, membership_id: int, /
      -1041    ) -> typedefs.JSONArray:
      -1042        resp = await self._request(
      -1043            RequestMethod.GET,
      -1044            f"User/GetCredentialTypesForTargetAccount/{membership_id}",
      -1045            auth=access_token,
      -1046        )
      -1047        assert isinstance(resp, list)
      -1048        return resp
      +            
      1027    async def fetch_user_credentials(
      +1028        self, access_token: str, membership_id: int, /
      +1029    ) -> typedefs.JSONArray:
      +1030        resp = await self._request(
      +1031            RequestMethod.GET,
      +1032            f"User/GetCredentialTypesForTargetAccount/{membership_id}",
      +1033            auth=access_token,
      +1034        )
      +1035        assert isinstance(resp, list)
      +1036        return resp
       
      @@ -6443,31 +6414,31 @@
      Raises
      -
      1050    async def insert_socket_plug(
      -1051        self,
      -1052        action_token: str,
      -1053        /,
      -1054        instance_id: int,
      -1055        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
      -1056        character_id: int,
      -1057        membership_type: typedefs.IntAnd[enums.MembershipType],
      -1058    ) -> typedefs.JSONObject:
      -1059
      -1060        if isinstance(plug, builders.PlugSocketBuilder):
      -1061            plug = plug.collect()
      -1062
      -1063        body = {
      -1064            "actionToken": action_token,
      -1065            "itemInstanceId": instance_id,
      -1066            "plug": plug,
      -1067            "characterId": character_id,
      -1068            "membershipType": int(membership_type),
      -1069        }
      -1070        resp = await self._request(
      -1071            RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body
      -1072        )
      -1073        assert isinstance(resp, dict)
      -1074        return resp
      +            
      1038    async def insert_socket_plug(
      +1039        self,
      +1040        action_token: str,
      +1041        /,
      +1042        instance_id: int,
      +1043        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
      +1044        character_id: int,
      +1045        membership_type: typedefs.IntAnd[enums.MembershipType],
      +1046    ) -> typedefs.JSONObject:
      +1047
      +1048        if isinstance(plug, builders.PlugSocketBuilder):
      +1049            plug = plug.collect()
      +1050
      +1051        body = {
      +1052            "actionToken": action_token,
      +1053            "itemInstanceId": instance_id,
      +1054            "plug": plug,
      +1055            "characterId": character_id,
      +1056            "membershipType": int(membership_type),
      +1057        }
      +1058        resp = await self._request(
      +1059            RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body
      +1060        )
      +1061        assert isinstance(resp, dict)
      +1062        return resp
       
      @@ -6492,7 +6463,8 @@
      Parameters
      Example
      -
      plug = (
      +
      +
      plug = (
           aiobungie.PlugSocketBuilder()
           .set_socket_array(0)
           .set_socket_index(0)
      @@ -6500,7 +6472,8 @@ 
      Example
      .collect() ) await insert_socket_plug_free(..., plug=plug) -
      +
      +

      character_id : int The character's id. @@ -6533,33 +6506,33 @@

      Raises
      -
      1076    async def insert_socket_plug_free(
      -1077        self,
      -1078        access_token: str,
      -1079        /,
      -1080        instance_id: int,
      -1081        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
      -1082        character_id: int,
      -1083        membership_type: typedefs.IntAnd[enums.MembershipType],
      -1084    ) -> typedefs.JSONObject:
      -1085
      -1086        if isinstance(plug, builders.PlugSocketBuilder):
      -1087            plug = plug.collect()
      -1088
      -1089        body = {
      -1090            "itemInstanceId": instance_id,
      -1091            "plug": plug,
      -1092            "characterId": character_id,
      -1093            "membershipType": int(membership_type),
      -1094        }
      -1095        resp = await self._request(
      -1096            RequestMethod.POST,
      -1097            "Destiny2/Actions/Items/InsertSocketPlugFree",
      -1098            json=body,
      -1099            auth=access_token,
      -1100        )
      -1101        assert isinstance(resp, dict)
      -1102        return resp
      +            
      1064    async def insert_socket_plug_free(
      +1065        self,
      +1066        access_token: str,
      +1067        /,
      +1068        instance_id: int,
      +1069        plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]],
      +1070        character_id: int,
      +1071        membership_type: typedefs.IntAnd[enums.MembershipType],
      +1072    ) -> typedefs.JSONObject:
      +1073
      +1074        if isinstance(plug, builders.PlugSocketBuilder):
      +1075            plug = plug.collect()
      +1076
      +1077        body = {
      +1078            "itemInstanceId": instance_id,
      +1079            "plug": plug,
      +1080            "characterId": character_id,
      +1081            "membershipType": int(membership_type),
      +1082        }
      +1083        resp = await self._request(
      +1084            RequestMethod.POST,
      +1085            "Destiny2/Actions/Items/InsertSocketPlugFree",
      +1086            json=body,
      +1087            auth=access_token,
      +1088        )
      +1089        assert isinstance(resp, dict)
      +1090        return resp
       
      @@ -6582,7 +6555,8 @@
      Parameters
      Example
      -
      plug = (
      +
      +
      plug = (
           aiobungie.PlugSocketBuilder()
           .set_socket_array(0)
           .set_socket_index(0)
      @@ -6590,7 +6564,8 @@ 
      Example
      .collect() ) await insert_socket_plug_free(..., plug=plug) -
      +
      +

      character_id : int The character's id. @@ -6623,29 +6598,29 @@

      Raises
      -
      1104    async def set_item_lock_state(
      -1105        self,
      -1106        access_token: str,
      -1107        state: bool,
      -1108        /,
      -1109        item_id: int,
      -1110        character_id: int,
      -1111        membership_type: typedefs.IntAnd[enums.MembershipType],
      -1112    ) -> int:
      -1113        body = {
      -1114            "state": state,
      -1115            "itemId": item_id,
      -1116            "characterId": character_id,
      -1117            "membership_type": int(membership_type),
      -1118        }
      -1119        response = await self._request(
      -1120            RequestMethod.POST,
      -1121            "Destiny2/Actions/Items/SetLockState",
      -1122            json=body,
      -1123            auth=access_token,
      -1124        )
      -1125        assert isinstance(response, int)
      -1126        return response
      +            
      1092    async def set_item_lock_state(
      +1093        self,
      +1094        access_token: str,
      +1095        state: bool,
      +1096        /,
      +1097        item_id: int,
      +1098        character_id: int,
      +1099        membership_type: typedefs.IntAnd[enums.MembershipType],
      +1100    ) -> int:
      +1101        body = {
      +1102            "state": state,
      +1103            "itemId": item_id,
      +1104            "characterId": character_id,
      +1105            "membership_type": int(membership_type),
      +1106        }
      +1107        response = await self._request(
      +1108            RequestMethod.POST,
      +1109            "Destiny2/Actions/Items/SetLockState",
      +1110            json=body,
      +1111            auth=access_token,
      +1112        )
      +1113        assert isinstance(response, int)
      +1114        return response
       
      @@ -6702,29 +6677,29 @@
      Raises
      -
      1128    async def set_quest_track_state(
      -1129        self,
      -1130        access_token: str,
      -1131        state: bool,
      -1132        /,
      -1133        item_id: int,
      -1134        character_id: int,
      -1135        membership_type: typedefs.IntAnd[enums.MembershipType],
      -1136    ) -> int:
      -1137        body = {
      -1138            "state": state,
      -1139            "itemId": item_id,
      -1140            "characterId": character_id,
      -1141            "membership_type": int(membership_type),
      -1142        }
      -1143        response = await self._request(
      -1144            RequestMethod.POST,
      -1145            "Destiny2/Actions/Items/SetTrackedState",
      -1146            json=body,
      -1147            auth=access_token,
      -1148        )
      -1149        assert isinstance(response, int)
      -1150        return response
      +            
      1116    async def set_quest_track_state(
      +1117        self,
      +1118        access_token: str,
      +1119        state: bool,
      +1120        /,
      +1121        item_id: int,
      +1122        character_id: int,
      +1123        membership_type: typedefs.IntAnd[enums.MembershipType],
      +1124    ) -> int:
      +1125        body = {
      +1126            "state": state,
      +1127            "itemId": item_id,
      +1128            "characterId": character_id,
      +1129            "membership_type": int(membership_type),
      +1130        }
      +1131        response = await self._request(
      +1132            RequestMethod.POST,
      +1133            "Destiny2/Actions/Items/SetTrackedState",
      +1134            json=body,
      +1135            auth=access_token,
      +1136        )
      +1137        assert isinstance(response, int)
      +1138        return response
       
      @@ -6781,11 +6756,11 @@
      Raises
      -
      1152    async def fetch_manifest_path(self) -> typedefs.JSONObject:
      -1153        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1154        path = await self._request(RequestMethod.GET, "Destiny2/Manifest")
      -1155        assert isinstance(path, dict)
      -1156        return path
      +            
      1140    async def fetch_manifest_path(self) -> typedefs.JSONObject:
      +1141        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1142        path = await self._request(RequestMethod.GET, "Destiny2/Manifest")
      +1143        assert isinstance(path, dict)
      +1144        return path
       
      @@ -6811,19 +6786,19 @@
      Returns
      -
      1158    async def read_manifest_bytes(self, language: str = "en", /) -> bytes:
      -1159        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1160        _ensure_manifest_language(language)
      -1161
      -1162        content = await self.fetch_manifest_path()
      -1163        resp = await self._request(
      -1164            RequestMethod.GET,
      -1165            content["mobileWorldContentPaths"][language],
      -1166            unwrapping="read",
      -1167            base=True,
      -1168        )
      -1169        assert isinstance(resp, bytes)
      -1170        return resp
      +            
      1146    async def read_manifest_bytes(self, language: str = "en", /) -> bytes:
      +1147        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1148        _ensure_manifest_language(language)
      +1149
      +1150        content = await self.fetch_manifest_path()
      +1151        resp = await self._request(
      +1152            RequestMethod.GET,
      +1153            content["mobileWorldContentPaths"][language],
      +1154            unwrapping="read",
      +1155            base=True,
      +1156        )
      +1157        assert isinstance(resp, bytes)
      +1158        return resp
       
      @@ -6859,37 +6834,37 @@
      Returns
      -
      1172    async def download_manifest(
      -1173        self,
      -1174        language: str = "en",
      -1175        name: str = "manifest",
      -1176        path: typing.Union[pathlib.Path, str] = ".",
      -1177        *,
      -1178        force: bool = False,
      -1179    ) -> None:
      -1180        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1181        complete_path = _get_path(name, path, sql=True)
      -1182
      -1183        if complete_path.exists() and force:
      -1184            if force:
      -1185                _LOG.info(
      -1186                    f"Found manifest in {complete_path!s}. Forcing to Re-Download."
      -1187                )
      -1188                complete_path.unlink(missing_ok=True)
      -1189
      -1190                return await self.download_manifest(language, name, path, force=force)
      -1191
      -1192            else:
      -1193                raise FileExistsError(
      -1194                    "Manifest file already exists, "
      -1195                    "To force download, set the `force` parameter to `True`."
      -1196                )
      -1197
      -1198        _LOG.info(f"Downloading manifest. Location: {complete_path!s}")
      -1199        data_bytes = await self.read_manifest_bytes(language)
      -1200        await asyncio.get_running_loop().run_in_executor(
      -1201            None, _write_sqlite_bytes, data_bytes, path, name
      -1202        )
      +            
      1160    async def download_manifest(
      +1161        self,
      +1162        language: str = "en",
      +1163        name: str = "manifest",
      +1164        path: typing.Union[pathlib.Path, str] = ".",
      +1165        *,
      +1166        force: bool = False,
      +1167    ) -> None:
      +1168        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1169        complete_path = _get_path(name, path, sql=True)
      +1170
      +1171        if complete_path.exists() and force:
      +1172            if force:
      +1173                _LOG.info(
      +1174                    f"Found manifest in {complete_path!s}. Forcing to Re-Download."
      +1175                )
      +1176                complete_path.unlink(missing_ok=True)
      +1177
      +1178                return await self.download_manifest(language, name, path, force=force)
      +1179
      +1180            else:
      +1181                raise FileExistsError(
      +1182                    "Manifest file already exists, "
      +1183                    "To force download, set the `force` parameter to `True`."
      +1184                )
      +1185
      +1186        _LOG.info(f"Downloading manifest. Location: {complete_path!s}")
      +1187        data_bytes = await self.read_manifest_bytes(language)
      +1188        await asyncio.get_running_loop().run_in_executor(
      +1189            None, _write_sqlite_bytes, data_bytes, path, name
      +1190        )
       
      @@ -6941,28 +6916,28 @@
      Raises
      -
      1204    async def download_json_manifest(
      -1205        self,
      -1206        file_name: str = "manifest",
      -1207        path: typing.Union[str, pathlib.Path] = ".",
      -1208        language: str = "en",
      -1209    ) -> None:
      -1210        _ensure_manifest_language(language)
      -1211
      -1212        _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...")
      -1213
      -1214        content = await self.fetch_manifest_path()
      -1215        json_bytes = await self._request(
      -1216            RequestMethod.GET,
      -1217            content["jsonWorldContentPaths"][language],
      -1218            unwrapping="read",
      -1219            base=True,
      -1220        )
      -1221
      -1222        await asyncio.get_running_loop().run_in_executor(
      -1223            None, _write_json_bytes, json_bytes, file_name, path
      -1224        )
      -1225        _LOG.info("Finished downloading manifest JSON.")
      +            
      1192    async def download_json_manifest(
      +1193        self,
      +1194        file_name: str = "manifest",
      +1195        path: typing.Union[str, pathlib.Path] = ".",
      +1196        language: str = "en",
      +1197    ) -> None:
      +1198        _ensure_manifest_language(language)
      +1199
      +1200        _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...")
      +1201
      +1202        content = await self.fetch_manifest_path()
      +1203        json_bytes = await self._request(
      +1204            RequestMethod.GET,
      +1205            content["jsonWorldContentPaths"][language],
      +1206            unwrapping="read",
      +1207            base=True,
      +1208        )
      +1209
      +1210        await asyncio.get_running_loop().run_in_executor(
      +1211            None, _write_json_bytes, json_bytes, file_name, path
      +1212        )
      +1213        _LOG.info("Finished downloading manifest JSON.")
       
      @@ -6993,8 +6968,8 @@
      Parameters
      -
      1227    async def fetch_manifest_version(self) -> str:
      -1228        return typing.cast(str, (await self.fetch_manifest_path())["version"])
      +            
      1215    async def fetch_manifest_version(self) -> str:
      +1216        return typing.cast(str, (await self.fetch_manifest_path())["version"])
       
      @@ -7020,21 +6995,21 @@
      Returns
      -
      1230    async def fetch_linked_profiles(
      -1231        self,
      -1232        member_id: int,
      -1233        member_type: typedefs.IntAnd[enums.MembershipType],
      -1234        /,
      -1235        *,
      -1236        all: bool = False,
      -1237    ) -> typedefs.JSONObject:
      -1238        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1239        resp = await self._request(
      -1240            RequestMethod.GET,
      -1241            f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}",
      -1242        )
      -1243        assert isinstance(resp, dict)
      -1244        return resp
      +            
      1218    async def fetch_linked_profiles(
      +1219        self,
      +1220        member_id: int,
      +1221        member_type: typedefs.IntAnd[enums.MembershipType],
      +1222        /,
      +1223        *,
      +1224        all: bool = False,
      +1225    ) -> typedefs.JSONObject:
      +1226        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1227        resp = await self._request(
      +1228            RequestMethod.GET,
      +1229            f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}",
      +1230        )
      +1231        assert isinstance(resp, dict)
      +1232        return resp
       
      @@ -7089,13 +7064,13 @@
      Returns
      -
      1246    async def fetch_clan_banners(self) -> typedefs.JSONObject:
      -1247        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1248        resp = await self._request(
      -1249            RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/"
      -1250        )
      -1251        assert isinstance(resp, dict)
      -1252        return resp
      +            
      1234    async def fetch_clan_banners(self) -> typedefs.JSONObject:
      +1235        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1236        resp = await self._request(
      +1237            RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/"
      +1238        )
      +1239        assert isinstance(resp, dict)
      +1240        return resp
       
      @@ -7121,11 +7096,11 @@
      Returns
      -
      1254    async def fetch_public_milestones(self) -> typedefs.JSONObject:
      -1255        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1256        resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/")
      -1257        assert isinstance(resp, dict)
      -1258        return resp
      +            
      1242    async def fetch_public_milestones(self) -> typedefs.JSONObject:
      +1243        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1244        resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/")
      +1245        assert isinstance(resp, dict)
      +1246        return resp
       
      @@ -7151,15 +7126,15 @@
      Returns
      -
      1260    async def fetch_public_milestone_content(
      -1261        self, milestone_hash: int, /
      -1262    ) -> typedefs.JSONObject:
      -1263        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1264        resp = await self._request(
      -1265            RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/"
      -1266        )
      -1267        assert isinstance(resp, dict)
      -1268        return resp
      +            
      1248    async def fetch_public_milestone_content(
      +1249        self, milestone_hash: int, /
      +1250    ) -> typedefs.JSONObject:
      +1251        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1252        resp = await self._request(
      +1253            RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/"
      +1254        )
      +1255        assert isinstance(resp, dict)
      +1256        return resp
       
      @@ -7192,17 +7167,17 @@
      Returns
      -
      1270    async def fetch_current_user_memberships(
      -1271        self, access_token: str, /
      -1272    ) -> typedefs.JSONObject:
      -1273        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1274        resp = await self._request(
      -1275            RequestMethod.GET,
      -1276            "User/GetMembershipsForCurrentUser/",
      -1277            auth=access_token,
      -1278        )
      -1279        assert isinstance(resp, dict)
      -1280        return resp
      +            
      1258    async def fetch_current_user_memberships(
      +1259        self, access_token: str, /
      +1260    ) -> typedefs.JSONObject:
      +1261        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1262        resp = await self._request(
      +1263            RequestMethod.GET,
      +1264            "User/GetMembershipsForCurrentUser/",
      +1265            auth=access_token,
      +1266        )
      +1267        assert isinstance(resp, dict)
      +1268        return resp
       
      @@ -7242,27 +7217,27 @@
      Returns
      -
      1282    async def equip_item(
      -1283        self,
      -1284        access_token: str,
      -1285        /,
      -1286        item_id: int,
      -1287        character_id: int,
      -1288        membership_type: typedefs.IntAnd[enums.MembershipType],
      -1289    ) -> None:
      -1290        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1291        payload = {
      -1292            "itemId": item_id,
      -1293            "characterId": character_id,
      -1294            "membershipType": int(membership_type),
      -1295        }
      -1296
      -1297        await self._request(
      -1298            RequestMethod.POST,
      -1299            "Destiny2/Actions/Items/EquipItem/",
      -1300            json=payload,
      -1301            auth=access_token,
      -1302        )
      +            
      1270    async def equip_item(
      +1271        self,
      +1272        access_token: str,
      +1273        /,
      +1274        item_id: int,
      +1275        character_id: int,
      +1276        membership_type: typedefs.IntAnd[enums.MembershipType],
      +1277    ) -> None:
      +1278        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1279        payload = {
      +1280            "itemId": item_id,
      +1281            "characterId": character_id,
      +1282            "membershipType": int(membership_type),
      +1283        }
      +1284
      +1285        await self._request(
      +1286            RequestMethod.POST,
      +1287            "Destiny2/Actions/Items/EquipItem/",
      +1288            json=payload,
      +1289            auth=access_token,
      +1290        )
       
      @@ -7303,26 +7278,26 @@
      Parameters
      -
      1304    async def equip_items(
      -1305        self,
      -1306        access_token: str,
      -1307        /,
      -1308        item_ids: list[int],
      -1309        character_id: int,
      -1310        membership_type: typedefs.IntAnd[enums.MembershipType],
      -1311    ) -> None:
      -1312        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1313        payload = {
      -1314            "itemIds": item_ids,
      -1315            "characterId": character_id,
      -1316            "membershipType": int(membership_type),
      -1317        }
      -1318        await self._request(
      -1319            RequestMethod.POST,
      -1320            "Destiny2/Actions/Items/EquipItems/",
      -1321            json=payload,
      -1322            auth=access_token,
      -1323        )
      +            
      1292    async def equip_items(
      +1293        self,
      +1294        access_token: str,
      +1295        /,
      +1296        item_ids: list[int],
      +1297        character_id: int,
      +1298        membership_type: typedefs.IntAnd[enums.MembershipType],
      +1299    ) -> None:
      +1300        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1301        payload = {
      +1302            "itemIds": item_ids,
      +1303            "characterId": character_id,
      +1304            "membershipType": int(membership_type),
      +1305        }
      +1306        await self._request(
      +1307            RequestMethod.POST,
      +1308            "Destiny2/Actions/Items/EquipItems/",
      +1309            json=payload,
      +1310            auth=access_token,
      +1311        )
       
      @@ -7363,25 +7338,25 @@
      Parameters
      -
      1325    async def ban_clan_member(
      -1326        self,
      -1327        access_token: str,
      -1328        /,
      -1329        group_id: int,
      -1330        membership_id: int,
      -1331        membership_type: typedefs.IntAnd[enums.MembershipType],
      -1332        *,
      -1333        length: int = 0,
      -1334        comment: undefined.UndefinedOr[str] = undefined.Undefined,
      -1335    ) -> None:
      -1336        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1337        payload = {"comment": str(comment), "length": length}
      -1338        await self._request(
      -1339            RequestMethod.POST,
      -1340            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/",
      -1341            json=payload,
      -1342            auth=access_token,
      -1343        )
      +            
      1313    async def ban_clan_member(
      +1314        self,
      +1315        access_token: str,
      +1316        /,
      +1317        group_id: int,
      +1318        membership_id: int,
      +1319        membership_type: typedefs.IntAnd[enums.MembershipType],
      +1320        *,
      +1321        length: int = 0,
      +1322        comment: undefined.UndefinedOr[str] = undefined.Undefined,
      +1323    ) -> None:
      +1324        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1325        payload = {"comment": str(comment), "length": length}
      +1326        await self._request(
      +1327            RequestMethod.POST,
      +1328            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/",
      +1329            json=payload,
      +1330            auth=access_token,
      +1331        )
       
      @@ -7411,7 +7386,7 @@
      Other Parameters
      • length (int): An optional ban length.
      • -
      • comment (aiobungie.UndefinedOr[str]): +
      • comment (aiobungie.UndefinedOr[str]): An optional comment to this ban. Default is UNDEFINED
      @@ -7429,20 +7404,20 @@
      Other Parameters
      -
      1345    async def unban_clan_member(
      -1346        self,
      -1347        access_token: str,
      -1348        /,
      -1349        group_id: int,
      -1350        membership_id: int,
      -1351        membership_type: typedefs.IntAnd[enums.MembershipType],
      -1352    ) -> None:
      -1353        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1354        await self._request(
      -1355            RequestMethod.POST,
      -1356            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/",
      -1357            auth=access_token,
      -1358        )
      +            
      1333    async def unban_clan_member(
      +1334        self,
      +1335        access_token: str,
      +1336        /,
      +1337        group_id: int,
      +1338        membership_id: int,
      +1339        membership_type: typedefs.IntAnd[enums.MembershipType],
      +1340    ) -> None:
      +1341        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1342        await self._request(
      +1343            RequestMethod.POST,
      +1344            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/",
      +1345            auth=access_token,
      +1346        )
       
      @@ -7481,22 +7456,22 @@
      Parameters
      -
      1360    async def kick_clan_member(
      -1361        self,
      -1362        access_token: str,
      -1363        /,
      -1364        group_id: int,
      -1365        membership_id: int,
      -1366        membership_type: typedefs.IntAnd[enums.MembershipType],
      -1367    ) -> typedefs.JSONObject:
      -1368        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1369        resp = await self._request(
      -1370            RequestMethod.POST,
      -1371            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/",
      -1372            auth=access_token,
      -1373        )
      -1374        assert isinstance(resp, dict)
      -1375        return resp
      +            
      1348    async def kick_clan_member(
      +1349        self,
      +1350        access_token: str,
      +1351        /,
      +1352        group_id: int,
      +1353        membership_id: int,
      +1354        membership_type: typedefs.IntAnd[enums.MembershipType],
      +1355    ) -> typedefs.JSONObject:
      +1356        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1357        resp = await self._request(
      +1358            RequestMethod.POST,
      +1359            f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/",
      +1360            auth=access_token,
      +1361        )
      +1362        assert isinstance(resp, dict)
      +1363        return resp
       
      @@ -7541,58 +7516,58 @@
      Returns
      -
      1377    async def edit_clan(
      -1378        self,
      -1379        access_token: str,
      -1380        /,
      -1381        group_id: int,
      -1382        *,
      -1383        name: typedefs.NoneOr[str] = None,
      -1384        about: typedefs.NoneOr[str] = None,
      -1385        motto: typedefs.NoneOr[str] = None,
      -1386        theme: typedefs.NoneOr[str] = None,
      -1387        tags: typedefs.NoneOr[collections.Sequence[str]] = None,
      -1388        is_public: typedefs.NoneOr[bool] = None,
      -1389        locale: typedefs.NoneOr[str] = None,
      -1390        avatar_image_index: typedefs.NoneOr[int] = None,
      -1391        membership_option: typedefs.NoneOr[
      -1392            typedefs.IntAnd[enums.MembershipOption]
      -1393        ] = None,
      -1394        allow_chat: typedefs.NoneOr[bool] = None,
      -1395        chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None,
      -1396        call_sign: typedefs.NoneOr[str] = None,
      -1397        homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
      -1398        enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None,
      -1399        default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
      -1400        is_public_topic_admin: typedefs.NoneOr[bool] = None,
      -1401    ) -> None:
      -1402        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      -1403        payload = {
      -1404            "name": name,
      -1405            "about": about,
      -1406            "motto": motto,
      -1407            "theme": theme,
      -1408            "tags": tags,
      -1409            "isPublic": is_public,
      -1410            "avatarImageIndex": avatar_image_index,
      -1411            "isPublicTopicAdminOnly": is_public_topic_admin,
      -1412            "allowChat": allow_chat,
      -1413            "chatSecurity": chat_security,
      -1414            "callsign": call_sign,
      -1415            "homepage": homepage,
      -1416            "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins,
      -1417            "defaultPublicity": default_publicity,
      -1418            "locale": locale,
      -1419        }
      -1420        if membership_option is not None:
      -1421            payload["membershipOption"] = int(membership_option)
      -1422
      -1423        await self._request(
      -1424            RequestMethod.POST,
      -1425            f"GroupV2/{group_id}/Edit",
      -1426            json=payload,
      -1427            auth=access_token,
      -1428        )
      +            
      1365    async def edit_clan(
      +1366        self,
      +1367        access_token: str,
      +1368        /,
      +1369        group_id: int,
      +1370        *,
      +1371        name: typedefs.NoneOr[str] = None,
      +1372        about: typedefs.NoneOr[str] = None,
      +1373        motto: typedefs.NoneOr[str] = None,
      +1374        theme: typedefs.NoneOr[str] = None,
      +1375        tags: typedefs.NoneOr[collections.Sequence[str]] = None,
      +1376        is_public: typedefs.NoneOr[bool] = None,
      +1377        locale: typedefs.NoneOr[str] = None,
      +1378        avatar_image_index: typedefs.NoneOr[int] = None,
      +1379        membership_option: typedefs.NoneOr[
      +1380            typedefs.IntAnd[enums.MembershipOption]
      +1381        ] = None,
      +1382        allow_chat: typedefs.NoneOr[bool] = None,
      +1383        chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None,
      +1384        call_sign: typedefs.NoneOr[str] = None,
      +1385        homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
      +1386        enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None,
      +1387        default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None,
      +1388        is_public_topic_admin: typedefs.NoneOr[bool] = None,
      +1389    ) -> None:
      +1390        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
      +1391        payload = {
      +1392            "name": name,
      +1393            "about": about,
      +1394            "motto": motto,
      +1395            "theme": theme,
      +1396            "tags": tags,
      +1397            "isPublic": is_public,
      +1398            "avatarImageIndex": avatar_image_index,
      +1399            "isPublicTopicAdminOnly": is_public_topic_admin,
      +1400            "allowChat": allow_chat,
      +1401            "chatSecurity": chat_security,
      +1402            "callsign": call_sign,
      +1403            "homepage": homepage,
      +1404            "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins,
      +1405            "defaultPublicity": default_publicity,
      +1406            "locale": locale,
      +1407        }
      +1408        if membership_option is not None:
      +1409            payload["membershipOption"] = int(membership_option)
      +1410
      +1411        await self._request(
      +1412            RequestMethod.POST,
      +1413            f"GroupV2/{group_id}/Edit",
      +1414            json=payload,
      +1415            auth=access_token,
      +1416        )
       
      @@ -7672,35 +7647,35 @@
      Other Parameters
      -
      1430    async def edit_clan_options(
      -1431        self,
      -1432        access_token: str,
      -1433        /,
      -1434        group_id: int,
      -1435        *,
      -1436        invite_permissions_override: typedefs.NoneOr[bool] = None,
      -1437        update_culture_permissionOverride: typedefs.NoneOr[bool] = None,
      -1438        host_guided_game_permission_override: typedefs.NoneOr[
      -1439            typing.Literal[0, 1, 2]
      -1440        ] = None,
      -1441        update_banner_permission_override: typedefs.NoneOr[bool] = None,
      -1442        join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None,
      -1443    ) -> None:
      -1444
      -1445        payload = {
      -1446            "InvitePermissionOverride": invite_permissions_override,
      -1447            "UpdateCulturePermissionOverride": update_culture_permissionOverride,
      -1448            "HostGuidedGamePermissionOverride": host_guided_game_permission_override,
      -1449            "UpdateBannerPermissionOverride": update_banner_permission_override,
      -1450            "JoinLevel": int(join_level) if join_level else None,
      -1451        }
      -1452
      -1453        await self._request(
      -1454            RequestMethod.POST,
      -1455            f"GroupV2/{group_id}/EditFounderOptions",
      -1456            json=payload,
      -1457            auth=access_token,
      -1458        )
      +            
      1418    async def edit_clan_options(
      +1419        self,
      +1420        access_token: str,
      +1421        /,
      +1422        group_id: int,
      +1423        *,
      +1424        invite_permissions_override: typedefs.NoneOr[bool] = None,
      +1425        update_culture_permissionOverride: typedefs.NoneOr[bool] = None,
      +1426        host_guided_game_permission_override: typedefs.NoneOr[
      +1427            typing.Literal[0, 1, 2]
      +1428        ] = None,
      +1429        update_banner_permission_override: typedefs.NoneOr[bool] = None,
      +1430        join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None,
      +1431    ) -> None:
      +1432
      +1433        payload = {
      +1434            "InvitePermissionOverride": invite_permissions_override,
      +1435            "UpdateCulturePermissionOverride": update_culture_permissionOverride,
      +1436            "HostGuidedGamePermissionOverride": host_guided_game_permission_override,
      +1437            "UpdateBannerPermissionOverride": update_banner_permission_override,
      +1438            "JoinLevel": int(join_level) if join_level else None,
      +1439        }
      +1440
      +1441        await self._request(
      +1442            RequestMethod.POST,
      +1443            f"GroupV2/{group_id}/EditFounderOptions",
      +1444            json=payload,
      +1445            auth=access_token,
      +1446        )
       
      @@ -7747,7 +7722,7 @@
      Other Parameters
      Default is False for clans, True for groups.
    • join_level (aiobungie.ClanMemberType): Level to join a member at when accepting an invite, application, or joining an open clan. -Default is aiobungie.ClanMemberType.BEGINNER
    • +Default is aiobungie.ClanMemberType.BEGINNER
    @@ -7764,15 +7739,15 @@
    Other Parameters
    -
    1460    async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject:
    -1461        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1462        resp = await self._request(
    -1463            RequestMethod.GET,
    -1464            "Social/Friends/",
    -1465            auth=access_token,
    -1466        )
    -1467        assert isinstance(resp, dict)
    -1468        return resp
    +            
    1448    async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject:
    +1449        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1450        resp = await self._request(
    +1451            RequestMethod.GET,
    +1452            "Social/Friends/",
    +1453            auth=access_token,
    +1454        )
    +1455        assert isinstance(resp, dict)
    +1456        return resp
     
    @@ -7811,15 +7786,15 @@
    Returns
    -
    1470    async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject:
    -1471        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1472        resp = await self._request(
    -1473            RequestMethod.GET,
    -1474            "Social/Friends/Requests",
    -1475            auth=access_token,
    -1476        )
    -1477        assert isinstance(resp, dict)
    -1478        return resp
    +            
    1458    async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject:
    +1459        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1460        resp = await self._request(
    +1461            RequestMethod.GET,
    +1462            "Social/Friends/Requests",
    +1463            auth=access_token,
    +1464        )
    +1465        assert isinstance(resp, dict)
    +1466        return resp
     
    @@ -7858,13 +7833,13 @@
    Returns
    -
    1480    async def accept_friend_request(self, access_token: str, /, member_id: int) -> None:
    -1481        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1482        await self._request(
    -1483            RequestMethod.POST,
    -1484            f"Social/Friends/Requests/Accept/{member_id}",
    -1485            auth=access_token,
    -1486        )
    +            
    1468    async def accept_friend_request(self, access_token: str, /, member_id: int) -> None:
    +1469        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1470        await self._request(
    +1471            RequestMethod.POST,
    +1472            f"Social/Friends/Requests/Accept/{member_id}",
    +1473            auth=access_token,
    +1474        )
     
    @@ -7899,13 +7874,13 @@
    Parameters
    -
    1488    async def send_friend_request(self, access_token: str, /, member_id: int) -> None:
    -1489        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1490        await self._request(
    -1491            RequestMethod.POST,
    -1492            f"Social/Friends/Add/{member_id}",
    -1493            auth=access_token,
    -1494        )
    +            
    1476    async def send_friend_request(self, access_token: str, /, member_id: int) -> None:
    +1477        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1478        await self._request(
    +1479            RequestMethod.POST,
    +1480            f"Social/Friends/Add/{member_id}",
    +1481            auth=access_token,
    +1482        )
     
    @@ -7940,15 +7915,15 @@
    Parameters
    -
    1496    async def decline_friend_request(
    -1497        self, access_token: str, /, member_id: int
    -1498    ) -> None:
    -1499        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1500        await self._request(
    -1501            RequestMethod.POST,
    -1502            f"Social/Friends/Requests/Decline/{member_id}",
    -1503            auth=access_token,
    -1504        )
    +            
    1484    async def decline_friend_request(
    +1485        self, access_token: str, /, member_id: int
    +1486    ) -> None:
    +1487        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1488        await self._request(
    +1489            RequestMethod.POST,
    +1490            f"Social/Friends/Requests/Decline/{member_id}",
    +1491            auth=access_token,
    +1492        )
     
    @@ -7983,13 +7958,13 @@
    Parameters
    -
    1506    async def remove_friend(self, access_token: str, /, member_id: int) -> None:
    -1507        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1508        await self._request(
    -1509            RequestMethod.POST,
    -1510            f"Social/Friends/Remove/{member_id}",
    -1511            auth=access_token,
    -1512        )
    +            
    1494    async def remove_friend(self, access_token: str, /, member_id: int) -> None:
    +1495        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1496        await self._request(
    +1497            RequestMethod.POST,
    +1498            f"Social/Friends/Remove/{member_id}",
    +1499            auth=access_token,
    +1500        )
     
    @@ -8024,13 +7999,13 @@
    Parameters
    -
    1514    async def remove_friend_request(self, access_token: str, /, member_id: int) -> None:
    -1515        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1516        await self._request(
    -1517            RequestMethod.POST,
    -1518            f"Social/Friends/Requests/Remove/{member_id}",
    -1519            auth=access_token,
    -1520        )
    +            
    1502    async def remove_friend_request(self, access_token: str, /, member_id: int) -> None:
    +1503        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1504        await self._request(
    +1505            RequestMethod.POST,
    +1506            f"Social/Friends/Requests/Remove/{member_id}",
    +1507            auth=access_token,
    +1508        )
     
    @@ -8062,20 +8037,20 @@
    Parameters
    -
    1522    async def approve_all_pending_group_users(
    -1523        self,
    -1524        access_token: str,
    -1525        /,
    -1526        group_id: int,
    -1527        message: undefined.UndefinedOr[str] = undefined.Undefined,
    -1528    ) -> None:
    -1529        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1530        await self._request(
    -1531            RequestMethod.POST,
    -1532            f"GroupV2/{group_id}/Members/ApproveAll",
    -1533            auth=access_token,
    -1534            json={"message": str(message)},
    -1535        )
    +            
    1510    async def approve_all_pending_group_users(
    +1511        self,
    +1512        access_token: str,
    +1513        /,
    +1514        group_id: int,
    +1515        message: undefined.UndefinedOr[str] = undefined.Undefined,
    +1516    ) -> None:
    +1517        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1518        await self._request(
    +1519            RequestMethod.POST,
    +1520            f"GroupV2/{group_id}/Members/ApproveAll",
    +1521            auth=access_token,
    +1522            json={"message": str(message)},
    +1523        )
     
    @@ -8099,7 +8074,7 @@
    Parameters
    Other Parameters
      -
    • message (aiobungie.UndefinedOr[str]): +
    • message (aiobungie.UndefinedOr[str]): An optional message to send with the request. Default is UNDEFINED.
    @@ -8117,21 +8092,21 @@
    Other Parameters
    -
    1537    async def deny_all_pending_group_users(
    -1538        self,
    -1539        access_token: str,
    -1540        /,
    -1541        group_id: int,
    -1542        *,
    -1543        message: undefined.UndefinedOr[str] = undefined.Undefined,
    -1544    ) -> None:
    -1545        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1546        await self._request(
    -1547            RequestMethod.POST,
    -1548            f"GroupV2/{group_id}/Members/DenyAll",
    -1549            auth=access_token,
    -1550            json={"message": str(message)},
    -1551        )
    +            
    1525    async def deny_all_pending_group_users(
    +1526        self,
    +1527        access_token: str,
    +1528        /,
    +1529        group_id: int,
    +1530        *,
    +1531        message: undefined.UndefinedOr[str] = undefined.Undefined,
    +1532    ) -> None:
    +1533        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1534        await self._request(
    +1535            RequestMethod.POST,
    +1536            f"GroupV2/{group_id}/Members/DenyAll",
    +1537            auth=access_token,
    +1538            json={"message": str(message)},
    +1539        )
     
    @@ -8155,7 +8130,7 @@
    Parameters
    Other Parameters
      -
    • message (aiobungie.UndefinedOr[str]): +
    • message (aiobungie.UndefinedOr[str]): An optional message to send with the request. Default is UNDEFINED.
    @@ -8173,23 +8148,23 @@
    Other Parameters
    -
    1553    async def add_optional_conversation(
    -1554        self,
    -1555        access_token: str,
    -1556        /,
    -1557        group_id: int,
    -1558        *,
    -1559        name: undefined.UndefinedOr[str] = undefined.Undefined,
    -1560        security: typing.Literal[0, 1] = 0,
    -1561    ) -> None:
    -1562        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1563        payload = {"chatName": str(name), "chatSecurity": security}
    -1564        await self._request(
    -1565            RequestMethod.POST,
    -1566            f"GroupV2/{group_id}/OptionalConversations/Add",
    -1567            json=payload,
    -1568            auth=access_token,
    -1569        )
    +            
    1541    async def add_optional_conversation(
    +1542        self,
    +1543        access_token: str,
    +1544        /,
    +1545        group_id: int,
    +1546        *,
    +1547        name: undefined.UndefinedOr[str] = undefined.Undefined,
    +1548        security: typing.Literal[0, 1] = 0,
    +1549    ) -> None:
    +1550        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1551        payload = {"chatName": str(name), "chatSecurity": security}
    +1552        await self._request(
    +1553            RequestMethod.POST,
    +1554            f"GroupV2/{group_id}/OptionalConversations/Add",
    +1555            json=payload,
    +1556            auth=access_token,
    +1557        )
     
    @@ -8212,7 +8187,7 @@
    Parameters
    Other parameters
    -

    name: aiobungie.UndefinedOr[str] +

    name: aiobungie.UndefinedOr[str] The chat name. Default to UNDEFINED security: typing.Literal[0, 1] The security level of the chat.

    @@ -8236,29 +8211,29 @@
    Other parameters
    -
    1571    async def edit_optional_conversation(
    -1572        self,
    -1573        access_token: str,
    -1574        /,
    -1575        group_id: int,
    -1576        conversation_id: int,
    -1577        *,
    -1578        name: undefined.UndefinedOr[str] = undefined.Undefined,
    -1579        security: typing.Literal[0, 1] = 0,
    -1580        enable_chat: bool = False,
    -1581    ) -> None:
    -1582        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1583        payload = {
    -1584            "chatEnabled": enable_chat,
    -1585            "chatName": str(name),
    -1586            "chatSecurity": security,
    -1587        }
    -1588        await self._request(
    -1589            RequestMethod.POST,
    -1590            f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}",
    -1591            json=payload,
    -1592            auth=access_token,
    -1593        )
    +            
    1559    async def edit_optional_conversation(
    +1560        self,
    +1561        access_token: str,
    +1562        /,
    +1563        group_id: int,
    +1564        conversation_id: int,
    +1565        *,
    +1566        name: undefined.UndefinedOr[str] = undefined.Undefined,
    +1567        security: typing.Literal[0, 1] = 0,
    +1568        enable_chat: bool = False,
    +1569    ) -> None:
    +1570        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1571        payload = {
    +1572            "chatEnabled": enable_chat,
    +1573            "chatName": str(name),
    +1574            "chatSecurity": security,
    +1575        }
    +1576        await self._request(
    +1577            RequestMethod.POST,
    +1578            f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}",
    +1579            json=payload,
    +1580            auth=access_token,
    +1581        )
     
    @@ -8283,7 +8258,7 @@
    Parameters
    Other parameters
    -

    name: aiobungie.UndefinedOr[str] +

    name: aiobungie.UndefinedOr[str] The new chat name. Default to UNDEFINED security: typing.Literal[0, 1] The new security level of the chat.

    @@ -8311,33 +8286,33 @@
    Other parameters
    -
    1595    async def transfer_item(
    -1596        self,
    -1597        access_token: str,
    -1598        /,
    -1599        item_id: int,
    -1600        item_hash: int,
    -1601        character_id: int,
    -1602        member_type: typedefs.IntAnd[enums.MembershipType],
    -1603        *,
    -1604        stack_size: int = 1,
    -1605        vault: bool = False,
    -1606    ) -> None:
    -1607        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1608        payload = {
    -1609            "characterId": character_id,
    -1610            "membershipType": int(member_type),
    -1611            "itemId": item_id,
    -1612            "itemReferenceHash": item_hash,
    -1613            "stackSize": stack_size,
    -1614            "transferToVault": vault,
    -1615        }
    -1616        await self._request(
    -1617            RequestMethod.POST,
    -1618            "Destiny2/Actions/Items/TransferItem",
    -1619            json=payload,
    -1620            auth=access_token,
    -1621        )
    +            
    1583    async def transfer_item(
    +1584        self,
    +1585        access_token: str,
    +1586        /,
    +1587        item_id: int,
    +1588        item_hash: int,
    +1589        character_id: int,
    +1590        member_type: typedefs.IntAnd[enums.MembershipType],
    +1591        *,
    +1592        stack_size: int = 1,
    +1593        vault: bool = False,
    +1594    ) -> None:
    +1595        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1596        payload = {
    +1597            "characterId": character_id,
    +1598            "membershipType": int(member_type),
    +1599            "itemId": item_id,
    +1600            "itemReferenceHash": item_hash,
    +1601            "stackSize": stack_size,
    +1602            "transferToVault": vault,
    +1603        }
    +1604        await self._request(
    +1605            RequestMethod.POST,
    +1606            "Destiny2/Actions/Items/TransferItem",
    +1607            json=payload,
    +1608            auth=access_token,
    +1609        )
     
    @@ -8388,33 +8363,33 @@
    Other Parameters
    -
    1623    async def pull_item(
    -1624        self,
    -1625        access_token: str,
    -1626        /,
    -1627        item_id: int,
    -1628        item_hash: int,
    -1629        character_id: int,
    -1630        member_type: typedefs.IntAnd[enums.MembershipType],
    -1631        *,
    -1632        stack_size: int = 1,
    -1633        vault: bool = False,
    -1634    ) -> None:
    -1635        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    -1636        payload = {
    -1637            "characterId": character_id,
    -1638            "membershipType": int(member_type),
    -1639            "itemId": item_id,
    -1640            "itemReferenceHash": item_hash,
    -1641            "stackSize": stack_size,
    -1642            "transferToVault": vault,
    -1643        }
    -1644        await self._request(
    -1645            RequestMethod.POST,
    -1646            "Destiny2/Actions/Items/PullFromPostmaster",
    -1647            json=payload,
    -1648            auth=access_token,
    -1649        )
    +            
    1611    async def pull_item(
    +1612        self,
    +1613        access_token: str,
    +1614        /,
    +1615        item_id: int,
    +1616        item_hash: int,
    +1617        character_id: int,
    +1618        member_type: typedefs.IntAnd[enums.MembershipType],
    +1619        *,
    +1620        stack_size: int = 1,
    +1621        vault: bool = False,
    +1622    ) -> None:
    +1623        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>
    +1624        payload = {
    +1625            "characterId": character_id,
    +1626            "membershipType": int(member_type),
    +1627            "itemId": item_id,
    +1628            "itemReferenceHash": item_hash,
    +1629            "stackSize": stack_size,
    +1630            "transferToVault": vault,
    +1631        }
    +1632        await self._request(
    +1633            RequestMethod.POST,
    +1634            "Destiny2/Actions/Items/PullFromPostmaster",
    +1635            json=payload,
    +1636            auth=access_token,
    +1637        )
     
    @@ -8465,29 +8440,29 @@
    Other Parameters
    -
    1651    async def fetch_fireteams(
    -1652        self,
    -1653        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    -1654        *,
    -1655        platform: typedefs.IntAnd[
    -1656            fireteams.FireteamPlatform
    -1657        ] = fireteams.FireteamPlatform.ANY,
    -1658        language: typing.Union[
    -1659            fireteams.FireteamLanguage, str
    -1660        ] = fireteams.FireteamLanguage.ALL,
    -1661        date_range: typedefs.IntAnd[
    -1662            fireteams.FireteamDate
    -1663        ] = fireteams.FireteamDate.ALL,
    -1664        page: int = 0,
    -1665        slots_filter: int = 0,
    -1666    ) -> typedefs.JSONObject:
    -1667        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1668        resp = await self._request(
    -1669            RequestMethod.GET,
    -1670            f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}",  # noqa: E501 Line too long
    -1671        )
    -1672        assert isinstance(resp, dict)
    -1673        return resp
    +            
    1639    async def fetch_fireteams(
    +1640        self,
    +1641        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    +1642        *,
    +1643        platform: typedefs.IntAnd[
    +1644            fireteams.FireteamPlatform
    +1645        ] = fireteams.FireteamPlatform.ANY,
    +1646        language: typing.Union[
    +1647            fireteams.FireteamLanguage, str
    +1648        ] = fireteams.FireteamLanguage.ALL,
    +1649        date_range: typedefs.IntAnd[
    +1650            fireteams.FireteamDate
    +1651        ] = fireteams.FireteamDate.ALL,
    +1652        page: int = 0,
    +1653        slots_filter: int = 0,
    +1654    ) -> typedefs.JSONObject:
    +1655        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1656        resp = await self._request(
    +1657            RequestMethod.GET,
    +1658            f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}",  # noqa: E501 Line too long
    +1659        )
    +1660        assert isinstance(resp, dict)
    +1661        return resp
     
    @@ -8510,7 +8485,7 @@
    Other Parameters
    A locale language to filter the used language in that fireteam. Defaults to aiobungie.crates.FireteamLanguage.ALL
  • date_range (aiobungie.typedefs.IntAnd[aiobungie.FireteamDate]): -An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • +An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • page (int): The page number. By default its 0 which returns all available activities.
  • slots_filter (int): @@ -8537,30 +8512,30 @@
    Returns
    -
    1675    async def fetch_avaliable_clan_fireteams(
    -1676        self,
    -1677        access_token: str,
    -1678        group_id: int,
    -1679        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    -1680        *,
    -1681        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    -1682        language: typing.Union[fireteams.FireteamLanguage, str],
    -1683        date_range: typedefs.IntAnd[
    -1684            fireteams.FireteamDate
    -1685        ] = fireteams.FireteamDate.ALL,
    -1686        page: int = 0,
    -1687        public_only: bool = False,
    -1688        slots_filter: int = 0,
    -1689    ) -> typedefs.JSONObject:
    -1690        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1691        resp = await self._request(
    -1692            RequestMethod.GET,
    -1693            f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}",  # noqa: E501
    -1694            json={"langFilter": str(language)},
    -1695            auth=access_token,
    -1696        )
    -1697        assert isinstance(resp, dict)
    -1698        return resp
    +            
    1663    async def fetch_avaliable_clan_fireteams(
    +1664        self,
    +1665        access_token: str,
    +1666        group_id: int,
    +1667        activity_type: typedefs.IntAnd[fireteams.FireteamActivity],
    +1668        *,
    +1669        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    +1670        language: typing.Union[fireteams.FireteamLanguage, str],
    +1671        date_range: typedefs.IntAnd[
    +1672            fireteams.FireteamDate
    +1673        ] = fireteams.FireteamDate.ALL,
    +1674        page: int = 0,
    +1675        public_only: bool = False,
    +1676        slots_filter: int = 0,
    +1677    ) -> typedefs.JSONObject:
    +1678        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1679        resp = await self._request(
    +1680            RequestMethod.GET,
    +1681            f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}",  # noqa: E501
    +1682            json={"langFilter": str(language)},
    +1683            auth=access_token,
    +1684        )
    +1685        assert isinstance(resp, dict)
    +1686        return resp
     
    @@ -8593,7 +8568,7 @@
    Other Parameters
    A locale language to filter the used language in that fireteam. Defaults to aiobungie.crates.FireteamLanguage.ALL
  • date_range (aiobungie.typedefs.IntAnd[aiobungie.FireteamDate]): -An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • +An integer to filter the date range of the returned fireteams. Defaults to aiobungie.FireteamDate.ALL.
  • page (int): The page number. By default its 0 which returns all available activities.
  • public_only (bool): @@ -8622,17 +8597,17 @@
    Returns
    -
    1700    async def fetch_clan_fireteam(
    -1701        self, access_token: str, fireteam_id: int, group_id: int
    -1702    ) -> typedefs.JSONObject:
    -1703        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1704        resp = await self._request(
    -1705            RequestMethod.GET,
    -1706            f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}",
    -1707            auth=access_token,
    -1708        )
    -1709        assert isinstance(resp, dict)
    -1710        return resp
    +            
    1688    async def fetch_clan_fireteam(
    +1689        self, access_token: str, fireteam_id: int, group_id: int
    +1690    ) -> typedefs.JSONObject:
    +1691        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1692        resp = await self._request(
    +1693            RequestMethod.GET,
    +1694            f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}",
    +1695            auth=access_token,
    +1696        )
    +1697        assert isinstance(resp, dict)
    +1698        return resp
     
    @@ -8675,27 +8650,27 @@
    Returns
    -
    1712    async def fetch_my_clan_fireteams(
    -1713        self,
    -1714        access_token: str,
    -1715        group_id: int,
    -1716        *,
    -1717        include_closed: bool = True,
    -1718        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    -1719        language: typing.Union[fireteams.FireteamLanguage, str],
    -1720        filtered: bool = True,
    -1721        page: int = 0,
    -1722    ) -> typedefs.JSONObject:
    -1723        payload = {"groupFilter": filtered, "langFilter": str(language)}
    -1724        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1725        resp = await self._request(
    -1726            RequestMethod.GET,
    -1727            f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}",
    -1728            json=payload,
    -1729            auth=access_token,
    -1730        )
    -1731        assert isinstance(resp, dict)
    -1732        return resp
    +            
    1700    async def fetch_my_clan_fireteams(
    +1701        self,
    +1702        access_token: str,
    +1703        group_id: int,
    +1704        *,
    +1705        include_closed: bool = True,
    +1706        platform: typedefs.IntAnd[fireteams.FireteamPlatform],
    +1707        language: typing.Union[fireteams.FireteamLanguage, str],
    +1708        filtered: bool = True,
    +1709        page: int = 0,
    +1710    ) -> typedefs.JSONObject:
    +1711        payload = {"groupFilter": filtered, "langFilter": str(language)}
    +1712        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1713        resp = await self._request(
    +1714            RequestMethod.GET,
    +1715            f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}",
    +1716            json=payload,
    +1717            auth=access_token,
    +1718        )
    +1719        assert isinstance(resp, dict)
    +1720        return resp
     
    @@ -8755,17 +8730,17 @@
    Returns
    -
    1734    async def fetch_private_clan_fireteams(
    -1735        self, access_token: str, group_id: int, /
    -1736    ) -> int:
    -1737        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1738        resp = await self._request(
    -1739            RequestMethod.GET,
    -1740            f"Fireteam/Clan/{group_id}/ActiveCount",
    -1741            auth=access_token,
    -1742        )
    -1743        assert isinstance(resp, int)
    -1744        return resp
    +            
    1722    async def fetch_private_clan_fireteams(
    +1723        self, access_token: str, group_id: int, /
    +1724    ) -> int:
    +1725        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1726        resp = await self._request(
    +1727            RequestMethod.GET,
    +1728            f"Fireteam/Clan/{group_id}/ActiveCount",
    +1729            auth=access_token,
    +1730        )
    +1731        assert isinstance(resp, int)
    +1732        return resp
     
    @@ -8806,13 +8781,13 @@
    Returns
    -
    1746    async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject:
    -1747        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1748        resp = await self._request(
    -1749            RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}"
    -1750        )
    -1751        assert isinstance(resp, dict)
    -1752        return resp
    +            
    1734    async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject:
    +1735        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1736        resp = await self._request(
    +1737            RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}"
    +1738        )
    +1739        assert isinstance(resp, dict)
    +1740        return resp
     
    @@ -8845,17 +8820,17 @@
    Returns
    -
    1754    async def search_entities(
    -1755        self, name: str, entity_type: str, *, page: int = 0
    -1756    ) -> typedefs.JSONObject:
    -1757        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1758        resp = await self._request(
    -1759            RequestMethod.GET,
    -1760            f"Destiny2/Armory/Search/{entity_type}/{name}/",
    -1761            json={"page": page},
    -1762        )
    -1763        assert isinstance(resp, dict)
    -1764        return resp
    +            
    1742    async def search_entities(
    +1743        self, name: str, entity_type: str, *, page: int = 0
    +1744    ) -> typedefs.JSONObject:
    +1745        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1746        resp = await self._request(
    +1747            RequestMethod.GET,
    +1748            f"Destiny2/Armory/Search/{entity_type}/{name}/",
    +1749            json={"page": page},
    +1750        )
    +1751        assert isinstance(resp, dict)
    +1752        return resp
     
    @@ -8897,19 +8872,19 @@
    Returns
    -
    1766    async def fetch_unique_weapon_history(
    -1767        self,
    -1768        membership_id: int,
    -1769        character_id: int,
    -1770        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1771    ) -> typedefs.JSONObject:
    -1772        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1773        resp = await self._request(
    -1774            RequestMethod.GET,
    -1775            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/",
    -1776        )
    -1777        assert isinstance(resp, dict)
    -1778        return resp
    +            
    1754    async def fetch_unique_weapon_history(
    +1755        self,
    +1756        membership_id: int,
    +1757        character_id: int,
    +1758        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1759    ) -> typedefs.JSONObject:
    +1760        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1761        resp = await self._request(
    +1762            RequestMethod.GET,
    +1763            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/",
    +1764        )
    +1765        assert isinstance(resp, dict)
    +1766        return resp
     
    @@ -8946,21 +8921,21 @@
    Returns
    -
    1780    async def fetch_item(
    -1781        self,
    -1782        member_id: int,
    -1783        item_id: int,
    -1784        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1785        components: list[enums.ComponentType],
    -1786    ) -> typedefs.JSONObject:
    -1787        collector = _collect_components(components)
    -1788        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1789        resp = await self._request(
    -1790            RequestMethod.GET,
    -1791            f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}",
    -1792        )
    -1793        assert isinstance(resp, dict)
    -1794        return resp
    +            
    1768    async def fetch_item(
    +1769        self,
    +1770        member_id: int,
    +1771        item_id: int,
    +1772        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1773        components: list[enums.ComponentType],
    +1774    ) -> typedefs.JSONObject:
    +1775        collector = _collect_components(components)
    +1776        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1777        resp = await self._request(
    +1778            RequestMethod.GET,
    +1779            f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}",
    +1780        )
    +1781        assert isinstance(resp, dict)
    +1782        return resp
     
    @@ -8999,13 +8974,13 @@
    Returns
    -
    1796    async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject:
    -1797        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1798        resp = await self._request(
    -1799            RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/"
    -1800        )
    -1801        assert isinstance(resp, dict)
    -1802        return resp
    +            
    1784    async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject:
    +1785        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1786        resp = await self._request(
    +1787            RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/"
    +1788        )
    +1789        assert isinstance(resp, dict)
    +1790        return resp
     
    @@ -9038,13 +9013,13 @@
    Returns
    -
    1804    async def fetch_available_locales(self) -> typedefs.JSONObject:
    -1805        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1806        resp = await self._request(
    -1807            RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/"
    -1808        )
    -1809        assert isinstance(resp, dict)
    -1810        return resp
    +            
    1792    async def fetch_available_locales(self) -> typedefs.JSONObject:
    +1793        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1794        resp = await self._request(
    +1795            RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/"
    +1796        )
    +1797        assert isinstance(resp, dict)
    +1798        return resp
     
    @@ -9070,11 +9045,11 @@
    Returns
    -
    1812    async def fetch_common_settings(self) -> typedefs.JSONObject:
    -1813        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1814        resp = await self._request(RequestMethod.GET, "Settings")
    -1815        assert isinstance(resp, dict)
    -1816        return resp
    +            
    1800    async def fetch_common_settings(self) -> typedefs.JSONObject:
    +1801        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1802        resp = await self._request(RequestMethod.GET, "Settings")
    +1803        assert isinstance(resp, dict)
    +1804        return resp
     
    @@ -9100,11 +9075,11 @@
    Returns
    -
    1818    async def fetch_user_systems_overrides(self) -> typedefs.JSONObject:
    -1819        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1820        resp = await self._request(RequestMethod.GET, "UserSystemOverrides")
    -1821        assert isinstance(resp, dict)
    -1822        return resp
    +            
    1806    async def fetch_user_systems_overrides(self) -> typedefs.JSONObject:
    +1807        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1808        resp = await self._request(RequestMethod.GET, "UserSystemOverrides")
    +1809        assert isinstance(resp, dict)
    +1810        return resp
     
    @@ -9130,15 +9105,15 @@
    Returns
    -
    1824    async def fetch_global_alerts(
    -1825        self, *, include_streaming: bool = False
    -1826    ) -> typedefs.JSONArray:
    -1827        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1828        resp = await self._request(
    -1829            RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}"
    -1830        )
    -1831        assert isinstance(resp, list)
    -1832        return resp
    +            
    1812    async def fetch_global_alerts(
    +1813        self, *, include_streaming: bool = False
    +1814    ) -> typedefs.JSONArray:
    +1815        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1816        resp = await self._request(
    +1817            RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}"
    +1818        )
    +1819        assert isinstance(resp, list)
    +1820        return resp
     
    @@ -9171,31 +9146,31 @@
    Returns
    -
    1834    async def awainitialize_request(
    -1835        self,
    -1836        access_token: str,
    -1837        type: typing.Literal[0, 1],
    -1838        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1839        /,
    -1840        *,
    -1841        affected_item_id: typing.Optional[int] = None,
    -1842        character_id: typing.Optional[int] = None,
    -1843    ) -> typedefs.JSONObject:
    -1844        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1845
    -1846        body = {"type": type, "membershipType": int(membership_type)}
    -1847
    -1848        if affected_item_id is not None:
    -1849            body["affectedItemId"] = affected_item_id
    -1850
    -1851        if character_id is not None:
    -1852            body["characterId"] = character_id
    -1853
    -1854        resp = await self._request(
    -1855            RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token
    -1856        )
    -1857        assert isinstance(resp, dict)
    -1858        return resp
    +            
    1822    async def awainitialize_request(
    +1823        self,
    +1824        access_token: str,
    +1825        type: typing.Literal[0, 1],
    +1826        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1827        /,
    +1828        *,
    +1829        affected_item_id: typing.Optional[int] = None,
    +1830        character_id: typing.Optional[int] = None,
    +1831    ) -> typedefs.JSONObject:
    +1832        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1833
    +1834        body = {"type": type, "membershipType": int(membership_type)}
    +1835
    +1836        if affected_item_id is not None:
    +1837            body["affectedItemId"] = affected_item_id
    +1838
    +1839        if character_id is not None:
    +1840            body["characterId"] = character_id
    +1841
    +1842        resp = await self._request(
    +1843            RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token
    +1844        )
    +1845        assert isinstance(resp, dict)
    +1846        return resp
     
    @@ -9249,17 +9224,17 @@
    Returns
    -
    1860    async def awaget_action_token(
    -1861        self, access_token: str, correlation_id: str, /
    -1862    ) -> typedefs.JSONObject:
    -1863        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1864        resp = await self._request(
    -1865            RequestMethod.POST,
    -1866            f"Destiny2/Awa/GetActionToken/{correlation_id}",
    -1867            auth=access_token,
    -1868        )
    -1869        assert isinstance(resp, dict)
    -1870        return resp
    +            
    1848    async def awaget_action_token(
    +1849        self, access_token: str, correlation_id: str, /
    +1850    ) -> typedefs.JSONObject:
    +1851        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1852        resp = await self._request(
    +1853            RequestMethod.POST,
    +1854            f"Destiny2/Awa/GetActionToken/{correlation_id}",
    +1855            auth=access_token,
    +1856        )
    +1857        assert isinstance(resp, dict)
    +1858        return resp
     
    @@ -9300,25 +9275,25 @@
    Returns
    -
    1872    async def awa_provide_authorization_result(
    -1873        self,
    -1874        access_token: str,
    -1875        selection: int,
    -1876        correlation_id: str,
    -1877        nonce: collections.MutableSequence[typing.Union[str, bytes]],
    -1878    ) -> int:
    -1879        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1880
    -1881        body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce}
    -1882
    -1883        resp = await self._request(
    -1884            RequestMethod.POST,
    -1885            "Destiny2/Awa/AwaProvideAuthorizationResult",
    -1886            json=body,
    -1887            auth=access_token,
    -1888        )
    -1889        assert isinstance(resp, int)
    -1890        return resp
    +            
    1860    async def awa_provide_authorization_result(
    +1861        self,
    +1862        access_token: str,
    +1863        selection: int,
    +1864        correlation_id: str,
    +1865        nonce: collections.MutableSequence[typing.Union[str, bytes]],
    +1866    ) -> int:
    +1867        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1868
    +1869        body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce}
    +1870
    +1871        resp = await self._request(
    +1872            RequestMethod.POST,
    +1873            "Destiny2/Awa/AwaProvideAuthorizationResult",
    +1874            json=body,
    +1875            auth=access_token,
    +1876        )
    +1877        assert isinstance(resp, int)
    +1878        return resp
     
    @@ -9363,33 +9338,33 @@
    Returns
    -
    1892    async def fetch_vendors(
    -1893        self,
    -1894        access_token: str,
    -1895        character_id: int,
    -1896        membership_id: int,
    -1897        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1898        /,
    -1899        components: list[enums.ComponentType],
    -1900        filter: typing.Optional[int] = None,
    -1901    ) -> typedefs.JSONObject:
    -1902        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1903        components_ = _collect_components(components)
    -1904        route = (
    -1905            f"Destiny2/{int(membership_type)}/Profile/{membership_id}"
    -1906            f"/Character/{character_id}/Vendors/?components={components_}"
    -1907        )
    -1908
    -1909        if filter is not None:
    -1910            route = route + f"&filter={filter}"
    -1911
    -1912        resp = await self._request(
    -1913            RequestMethod.GET,
    -1914            route,
    -1915            auth=access_token,
    -1916        )
    -1917        assert isinstance(resp, dict)
    -1918        return resp
    +            
    1880    async def fetch_vendors(
    +1881        self,
    +1882        access_token: str,
    +1883        character_id: int,
    +1884        membership_id: int,
    +1885        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1886        /,
    +1887        components: list[enums.ComponentType],
    +1888        filter: typing.Optional[int] = None,
    +1889    ) -> typedefs.JSONObject:
    +1890        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1891        components_ = _collect_components(components)
    +1892        route = (
    +1893            f"Destiny2/{int(membership_type)}/Profile/{membership_id}"
    +1894            f"/Character/{character_id}/Vendors/?components={components_}"
    +1895        )
    +1896
    +1897        if filter is not None:
    +1898            route = route + f"&filter={filter}"
    +1899
    +1900        resp = await self._request(
    +1901            RequestMethod.GET,
    +1902            route,
    +1903            auth=access_token,
    +1904        )
    +1905        assert isinstance(resp, dict)
    +1906        return resp
     
    @@ -9437,28 +9412,28 @@
    Returns
    -
    1920    async def fetch_vendor(
    -1921        self,
    -1922        access_token: str,
    -1923        character_id: int,
    -1924        membership_id: int,
    -1925        membership_type: typedefs.IntAnd[enums.MembershipType],
    -1926        vendor_hash: int,
    -1927        /,
    -1928        components: list[enums.ComponentType],
    -1929    ) -> typedefs.JSONObject:
    -1930        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    -1931        components_ = _collect_components(components)
    -1932        resp = await self._request(
    -1933            RequestMethod.GET,
    -1934            (
    -1935                f"Platform/Destiny2/{int(membership_type)}/Profile/{membership_id}"
    -1936                f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}"
    -1937            ),
    -1938            auth=access_token,
    -1939        )
    -1940        assert isinstance(resp, dict)
    -1941        return resp
    +            
    1908    async def fetch_vendor(
    +1909        self,
    +1910        access_token: str,
    +1911        character_id: int,
    +1912        membership_id: int,
    +1913        membership_type: typedefs.IntAnd[enums.MembershipType],
    +1914        vendor_hash: int,
    +1915        /,
    +1916        components: list[enums.ComponentType],
    +1917    ) -> typedefs.JSONObject:
    +1918        # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>.
    +1919        components_ = _collect_components(components)
    +1920        resp = await self._request(
    +1921            RequestMethod.GET,
    +1922            (
    +1923                f"Platform/Destiny2/{int(membership_type)}/Profile/{membership_id}"
    +1924                f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}"
    +1925            ),
    +1926            auth=access_token,
    +1927        )
    +1928        assert isinstance(resp, dict)
    +1929        return resp
     
    @@ -9501,24 +9476,24 @@
    Returns
    -
    1943    async def fetch_application_api_usage(
    -1944        self,
    -1945        access_token: str,
    -1946        application_id: int,
    -1947        /,
    -1948        *,
    -1949        start: typing.Optional[datetime.datetime] = None,
    -1950        end: typing.Optional[datetime.datetime] = None,
    -1951    ) -> typedefs.JSONObject:
    -1952
    -1953        end_date, start_date = time.parse_date_range(end, start)
    -1954        resp = await self._request(
    -1955            RequestMethod.GET,
    -1956            f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}",
    -1957            auth=access_token,
    -1958        )
    -1959        assert isinstance(resp, dict)
    -1960        return resp
    +            
    1931    async def fetch_application_api_usage(
    +1932        self,
    +1933        access_token: str,
    +1934        application_id: int,
    +1935        /,
    +1936        *,
    +1937        start: typing.Optional[datetime.datetime] = None,
    +1938        end: typing.Optional[datetime.datetime] = None,
    +1939    ) -> typedefs.JSONObject:
    +1940
    +1941        end_date, start_date = time.parse_date_range(end, start)
    +1942        resp = await self._request(
    +1943            RequestMethod.GET,
    +1944            f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}",
    +1945            auth=access_token,
    +1946        )
    +1947        assert isinstance(resp, dict)
    +1948        return resp
     
    @@ -9549,13 +9524,15 @@
    Other Parameters
    Example
    -
    import datetime
    +
    +
    import datetime
     
     # Fetch data from 2021 Dec 10th to 2021 Dec 20th
     await fetch_application_api_usage(
         start=datetime.datetime(2021, 12, 10), end=datetime.datetime(2021, 12, 20)
     )
    -
    +
    +
    Returns
    @@ -9577,10 +9554,10 @@
    Returns
    -
    1962    async def fetch_bungie_applications(self) -> typedefs.JSONArray:
    -1963        resp = await self._request(RequestMethod.GET, "App/FirstParty")
    -1964        assert isinstance(resp, list)
    -1965        return resp
    +            
    1950    async def fetch_bungie_applications(self) -> typedefs.JSONArray:
    +1951        resp = await self._request(RequestMethod.GET, "App/FirstParty")
    +1952        assert isinstance(resp, list)
    +1953        return resp
     
    @@ -9606,10 +9583,10 @@
    Returns
    -
    1967    async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject:
    -1968        resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/")
    -1969        assert isinstance(resp, dict)
    -1970        return resp
    +            
    1955    async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject:
    +1956        resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/")
    +1957        assert isinstance(resp, dict)
    +1958        return resp
     
    @@ -9627,16 +9604,16 @@
    Returns
    -
    1972    async def fetch_content_by_id(
    -1973        self, id: int, locale: str, /, *, head: bool = False
    -1974    ) -> typedefs.JSONObject:
    -1975        resp = await self._request(
    -1976            RequestMethod.GET,
    -1977            f"Content/GetContentById/{id}/{locale}/",
    -1978            json={"head": head},
    -1979        )
    -1980        assert isinstance(resp, dict)
    -1981        return resp
    +            
    1960    async def fetch_content_by_id(
    +1961        self, id: int, locale: str, /, *, head: bool = False
    +1962    ) -> typedefs.JSONObject:
    +1963        resp = await self._request(
    +1964            RequestMethod.GET,
    +1965            f"Content/GetContentById/{id}/{locale}/",
    +1966            json={"head": head},
    +1967        )
    +1968        assert isinstance(resp, dict)
    +1969        return resp
     
    @@ -9654,16 +9631,16 @@
    Returns
    -
    1983    async def fetch_content_by_tag_and_type(
    -1984        self, locale: str, tag: str, type: str, *, head: bool = False
    -1985    ) -> typedefs.JSONObject:
    -1986        resp = await self._request(
    -1987            RequestMethod.GET,
    -1988            f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/",
    -1989            json={"head": head},
    -1990        )
    -1991        assert isinstance(resp, dict)
    -1992        return resp
    +            
    1971    async def fetch_content_by_tag_and_type(
    +1972        self, locale: str, tag: str, type: str, *, head: bool = False
    +1973    ) -> typedefs.JSONObject:
    +1974        resp = await self._request(
    +1975            RequestMethod.GET,
    +1976            f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/",
    +1977            json={"head": head},
    +1978        )
    +1979        assert isinstance(resp, dict)
    +1980        return resp
     
    @@ -9681,38 +9658,38 @@
    Returns
    -
    1994    async def search_content_with_text(
    -1995        self,
    -1996        locale: str,
    -1997        /,
    -1998        content_type: str,
    -1999        search_text: str,
    -2000        tag: str,
    -2001        *,
    -2002        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2003        source: undefined.UndefinedOr[str] = undefined.Undefined,
    -2004    ) -> typedefs.JSONObject:
    -2005
    -2006        body: typedefs.JSONObject = {}
    -2007
    -2008        body["ctype"] = content_type
    -2009        body["searchtext"] = search_text
    -2010        body["tag"] = tag
    -2011
    -2012        if page is not undefined.Undefined:
    -2013            body["currentpage"] = page
    -2014        else:
    -2015            body["currentpage"] = 1
    -2016
    -2017        if source is not undefined.Undefined:
    -2018            body["source"] = source
    -2019        else:
    -2020            source = ""
    -2021        resp = await self._request(
    -2022            RequestMethod.GET, f"Content/Search/{locale}/", json=body
    -2023        )
    -2024        assert isinstance(resp, dict)
    -2025        return resp
    +            
    1982    async def search_content_with_text(
    +1983        self,
    +1984        locale: str,
    +1985        /,
    +1986        content_type: str,
    +1987        search_text: str,
    +1988        tag: str,
    +1989        *,
    +1990        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +1991        source: undefined.UndefinedOr[str] = undefined.Undefined,
    +1992    ) -> typedefs.JSONObject:
    +1993
    +1994        body: typedefs.JSONObject = {}
    +1995
    +1996        body["ctype"] = content_type
    +1997        body["searchtext"] = search_text
    +1998        body["tag"] = tag
    +1999
    +2000        if page is not undefined.Undefined:
    +2001            body["currentpage"] = page
    +2002        else:
    +2003            body["currentpage"] = 1
    +2004
    +2005        if source is not undefined.Undefined:
    +2006            body["source"] = source
    +2007        else:
    +2008            source = ""
    +2009        resp = await self._request(
    +2010            RequestMethod.GET, f"Content/Search/{locale}/", json=body
    +2011        )
    +2012        assert isinstance(resp, dict)
    +2013        return resp
     
    @@ -9730,23 +9707,23 @@
    Returns
    -
    2027    async def search_content_by_tag_and_type(
    -2028        self,
    -2029        locale: str,
    -2030        tag: str,
    -2031        type: str,
    -2032        *,
    -2033        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2034    ) -> typedefs.JSONObject:
    -2035        body: typedefs.JSONObject = {}
    -2036        body["currentpage"] = 1 if page is undefined.Undefined else page
    -2037        resp = await self._request(
    -2038            RequestMethod.GET,
    -2039            f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/",
    -2040            json=body,
    -2041        )
    -2042        assert isinstance(resp, dict)
    -2043        return resp
    +            
    2015    async def search_content_by_tag_and_type(
    +2016        self,
    +2017        locale: str,
    +2018        tag: str,
    +2019        type: str,
    +2020        *,
    +2021        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +2022    ) -> typedefs.JSONObject:
    +2023        body: typedefs.JSONObject = {}
    +2024        body["currentpage"] = 1 if page is undefined.Undefined else page
    +2025        resp = await self._request(
    +2026            RequestMethod.GET,
    +2027            f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/",
    +2028            json=body,
    +2029        )
    +2030        assert isinstance(resp, dict)
    +2031        return resp
     
    @@ -9764,14 +9741,14 @@
    Returns
    -
    2045    async def search_help_articles(
    -2046        self, text: str, size: str, /
    -2047    ) -> typedefs.JSONObject:
    -2048        resp = await self._request(
    -2049            RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/"
    -2050        )
    -2051        assert isinstance(resp, dict)
    -2052        return resp
    +            
    2033    async def search_help_articles(
    +2034        self, text: str, size: str, /
    +2035    ) -> typedefs.JSONObject:
    +2036        resp = await self._request(
    +2037            RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/"
    +2038        )
    +2039        assert isinstance(resp, dict)
    +2040        return resp
     
    @@ -9789,38 +9766,38 @@
    Returns
    -
    2054    async def fetch_topics_page(
    -2055        self,
    -2056        category_filter: int,
    -2057        group: int,
    -2058        date_filter: int,
    -2059        sort: typing.Union[str, bytes],
    -2060        *,
    -2061        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2062        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    -2063        tag_filter: undefined.UndefinedOr[str] = undefined.Undefined,
    -2064    ) -> typedefs.JSONObject:
    -2065
    -2066        body: typedefs.JSONObject = {}
    -2067        if locales is not undefined.Undefined:
    -2068            body["locales"] = ",".join(str(locales))
    -2069        else:
    -2070            body["locales"] = ",".join([])
    -2071
    -2072        if tag_filter is not undefined.Undefined:
    -2073            body["tagstring"] = tag_filter
    -2074        else:
    -2075            body["tagstring"] = ""
    -2076
    -2077        page = 0 if page is not undefined.Undefined else page
    -2078
    -2079        resp = await self._request(
    -2080            RequestMethod.GET,
    -2081            f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/",
    -2082            json=body,
    -2083        )
    -2084        assert isinstance(resp, dict)
    -2085        return resp
    +            
    2042    async def fetch_topics_page(
    +2043        self,
    +2044        category_filter: int,
    +2045        group: int,
    +2046        date_filter: int,
    +2047        sort: typing.Union[str, bytes],
    +2048        *,
    +2049        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +2050        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    +2051        tag_filter: undefined.UndefinedOr[str] = undefined.Undefined,
    +2052    ) -> typedefs.JSONObject:
    +2053
    +2054        body: typedefs.JSONObject = {}
    +2055        if locales is not undefined.Undefined:
    +2056            body["locales"] = ",".join(str(locales))
    +2057        else:
    +2058            body["locales"] = ",".join([])
    +2059
    +2060        if tag_filter is not undefined.Undefined:
    +2061            body["tagstring"] = tag_filter
    +2062        else:
    +2063            body["tagstring"] = ""
    +2064
    +2065        page = 0 if page is not undefined.Undefined else page
    +2066
    +2067        resp = await self._request(
    +2068            RequestMethod.GET,
    +2069            f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/",
    +2070            json=body,
    +2071        )
    +2072        assert isinstance(resp, dict)
    +2073        return resp
     
    @@ -9838,30 +9815,30 @@
    Returns
    -
    2087    async def fetch_core_topics_page(
    -2088        self,
    -2089        category_filter: int,
    -2090        date_filter: int,
    -2091        sort: typing.Union[str, bytes],
    -2092        *,
    -2093        page: undefined.UndefinedOr[int] = undefined.Undefined,
    -2094        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    -2095    ) -> typedefs.JSONObject:
    -2096        body: typedefs.JSONObject = {}
    -2097
    -2098        if locales is not undefined.Undefined:
    -2099            body["locales"] = ",".join(str(locales))
    -2100        else:
    -2101            body["locales"] = ",".join([])
    -2102
    -2103        resp = await self._request(
    -2104            RequestMethod.GET,
    -2105            f"Forum/GetCoreTopicsPaged/{0 if page is undefined.Undefined else page}"
    -2106            f"/{sort!s}/{date_filter}/{category_filter}/",
    -2107            json=body,
    -2108        )
    -2109        assert isinstance(resp, dict)
    -2110        return resp
    +            
    2075    async def fetch_core_topics_page(
    +2076        self,
    +2077        category_filter: int,
    +2078        date_filter: int,
    +2079        sort: typing.Union[str, bytes],
    +2080        *,
    +2081        page: undefined.UndefinedOr[int] = undefined.Undefined,
    +2082        locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.Undefined,
    +2083    ) -> typedefs.JSONObject:
    +2084        body: typedefs.JSONObject = {}
    +2085
    +2086        if locales is not undefined.Undefined:
    +2087            body["locales"] = ",".join(str(locales))
    +2088        else:
    +2089            body["locales"] = ",".join([])
    +2090
    +2091        resp = await self._request(
    +2092            RequestMethod.GET,
    +2093            f"Forum/GetCoreTopicsPaged/{0 if page is undefined.Undefined else page}"
    +2094            f"/{sort!s}/{date_filter}/{category_filter}/",
    +2095            json=body,
    +2096        )
    +2097        assert isinstance(resp, dict)
    +2098        return resp
     
    @@ -9879,25 +9856,25 @@
    Returns
    -
    2112    async def fetch_posts_threaded_page(
    -2113        self,
    -2114        parent_post: bool,
    -2115        page: int,
    -2116        page_size: int,
    -2117        parent_post_id: int,
    -2118        reply_size: int,
    -2119        root_thread_mode: bool,
    -2120        sort_mode: int,
    -2121        show_banned: typing.Optional[str] = None,
    -2122    ) -> typedefs.JSONObject:
    -2123        resp = await self._request(
    -2124            RequestMethod.GET,
    -2125            f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/"
    -2126            f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/",
    -2127            json={"showbanned": show_banned},
    -2128        )
    -2129        assert isinstance(resp, dict)
    -2130        return resp
    +            
    2100    async def fetch_posts_threaded_page(
    +2101        self,
    +2102        parent_post: bool,
    +2103        page: int,
    +2104        page_size: int,
    +2105        parent_post_id: int,
    +2106        reply_size: int,
    +2107        root_thread_mode: bool,
    +2108        sort_mode: int,
    +2109        show_banned: typing.Optional[str] = None,
    +2110    ) -> typedefs.JSONObject:
    +2111        resp = await self._request(
    +2112            RequestMethod.GET,
    +2113            f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/"
    +2114            f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/",
    +2115            json={"showbanned": show_banned},
    +2116        )
    +2117        assert isinstance(resp, dict)
    +2118        return resp
     
    @@ -9915,24 +9892,24 @@
    Returns
    -
    2132    async def fetch_posts_threaded_page_from_child(
    -2133        self,
    -2134        child_id: bool,
    -2135        page: int,
    -2136        page_size: int,
    -2137        reply_size: int,
    -2138        root_thread_mode: bool,
    -2139        sort_mode: int,
    -2140        show_banned: typing.Optional[str] = None,
    -2141    ) -> typedefs.JSONObject:
    -2142        resp = await self._request(
    -2143            RequestMethod.GET,
    -2144            f"Forum/GetPostsThreadedPagedFromChild/{child_id}/"
    -2145            f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/",
    -2146            json={"showbanned": show_banned},
    -2147        )
    -2148        assert isinstance(resp, dict)
    -2149        return resp
    +            
    2120    async def fetch_posts_threaded_page_from_child(
    +2121        self,
    +2122        child_id: bool,
    +2123        page: int,
    +2124        page_size: int,
    +2125        reply_size: int,
    +2126        root_thread_mode: bool,
    +2127        sort_mode: int,
    +2128        show_banned: typing.Optional[str] = None,
    +2129    ) -> typedefs.JSONObject:
    +2130        resp = await self._request(
    +2131            RequestMethod.GET,
    +2132            f"Forum/GetPostsThreadedPagedFromChild/{child_id}/"
    +2133            f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/",
    +2134            json={"showbanned": show_banned},
    +2135        )
    +2136        assert isinstance(resp, dict)
    +2137        return resp
     
    @@ -9950,16 +9927,16 @@
    Returns
    -
    2151    async def fetch_post_and_parent(
    -2152        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
    -2153    ) -> typedefs.JSONObject:
    -2154        resp = await self._request(
    -2155            RequestMethod.GET,
    -2156            f"Forum/GetPostAndParent/{child_id}/",
    -2157            json={"showbanned": show_banned},
    -2158        )
    -2159        assert isinstance(resp, dict)
    -2160        return resp
    +            
    2139    async def fetch_post_and_parent(
    +2140        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
    +2141    ) -> typedefs.JSONObject:
    +2142        resp = await self._request(
    +2143            RequestMethod.GET,
    +2144            f"Forum/GetPostAndParent/{child_id}/",
    +2145            json={"showbanned": show_banned},
    +2146        )
    +2147        assert isinstance(resp, dict)
    +2148        return resp
     
    @@ -9977,16 +9954,16 @@
    Returns
    -
    2162    async def fetch_posts_and_parent_awaiting(
    -2163        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
    -2164    ) -> typedefs.JSONObject:
    -2165        resp = await self._request(
    -2166            RequestMethod.GET,
    -2167            f"Forum/GetPostAndParentAwaitingApproval/{child_id}/",
    -2168            json={"showbanned": show_banned},
    -2169        )
    -2170        assert isinstance(resp, dict)
    -2171        return resp
    +            
    2150    async def fetch_posts_and_parent_awaiting(
    +2151        self, child_id: int, /, *, show_banned: typing.Optional[str] = None
    +2152    ) -> typedefs.JSONObject:
    +2153        resp = await self._request(
    +2154            RequestMethod.GET,
    +2155            f"Forum/GetPostAndParentAwaitingApproval/{child_id}/",
    +2156            json={"showbanned": show_banned},
    +2157        )
    +2158        assert isinstance(resp, dict)
    +2159        return resp
     
    @@ -10004,12 +9981,12 @@
    Returns
    -
    2173    async def fetch_topic_for_content(self, content_id: int, /) -> int:
    -2174        resp = await self._request(
    -2175            RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/"
    -2176        )
    -2177        assert isinstance(resp, int)
    -2178        return resp
    +            
    2161    async def fetch_topic_for_content(self, content_id: int, /) -> int:
    +2162        resp = await self._request(
    +2163            RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/"
    +2164        )
    +2165        assert isinstance(resp, int)
    +2166        return resp
     
    @@ -10027,16 +10004,16 @@
    Returns
    -
    2180    async def fetch_forum_tag_suggestions(
    -2181        self, partial_tag: str, /
    -2182    ) -> typedefs.JSONObject:
    -2183        resp = await self._request(
    -2184            RequestMethod.GET,
    -2185            "Forum/GetForumTagSuggestions/",
    -2186            json={"partialtag": partial_tag},
    -2187        )
    -2188        assert isinstance(resp, dict)
    -2189        return resp
    +            
    2168    async def fetch_forum_tag_suggestions(
    +2169        self, partial_tag: str, /
    +2170    ) -> typedefs.JSONObject:
    +2171        resp = await self._request(
    +2172            RequestMethod.GET,
    +2173            "Forum/GetForumTagSuggestions/",
    +2174            json={"partialtag": partial_tag},
    +2175        )
    +2176        assert isinstance(resp, dict)
    +2177        return resp
     
    @@ -10054,10 +10031,10 @@
    Returns
    -
    2191    async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject:
    -2192        resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/")
    -2193        assert isinstance(resp, dict)
    -2194        return resp
    +            
    2179    async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject:
    +2180        resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/")
    +2181        assert isinstance(resp, dict)
    +2182        return resp
     
    @@ -10075,10 +10052,10 @@
    Returns
    -
    2196    async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray:
    -2197        resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/")
    -2198        assert isinstance(resp, list)
    -2199        return resp
    +            
    2184    async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray:
    +2185        resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/")
    +2186        assert isinstance(resp, list)
    +2187        return resp
     
    @@ -10096,21 +10073,21 @@
    Returns
    -
    2201    async def fetch_recommended_groups(
    -2202        self,
    -2203        accecss_token: str,
    -2204        /,
    -2205        *,
    -2206        date_range: int = 0,
    -2207        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    -2208    ) -> typedefs.JSONArray:
    -2209        resp = await self._request(
    -2210            RequestMethod.POST,
    -2211            f"GroupV2/Recommended/{int(group_type)}/{date_range}/",
    -2212            auth=accecss_token,
    -2213        )
    -2214        assert isinstance(resp, list)
    -2215        return resp
    +            
    2189    async def fetch_recommended_groups(
    +2190        self,
    +2191        accecss_token: str,
    +2192        /,
    +2193        *,
    +2194        date_range: int = 0,
    +2195        group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN,
    +2196    ) -> typedefs.JSONArray:
    +2197        resp = await self._request(
    +2198            RequestMethod.POST,
    +2199            f"GroupV2/Recommended/{int(group_type)}/{date_range}/",
    +2200            auth=accecss_token,
    +2201        )
    +2202        assert isinstance(resp, list)
    +2203        return resp
     
    @@ -10128,10 +10105,10 @@
    Returns
    -
    2217    async def fetch_available_avatars(self) -> collections.Mapping[str, int]:
    -2218        resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/")
    -2219        assert isinstance(resp, dict)
    -2220        return resp
    +            
    2205    async def fetch_available_avatars(self) -> collections.Mapping[str, int]:
    +2206        resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/")
    +2207        assert isinstance(resp, dict)
    +2208        return resp
     
    @@ -10149,19 +10126,19 @@
    Returns
    -
    2222    async def fetch_user_clan_invite_setting(
    -2223        self,
    -2224        access_token: str,
    -2225        /,
    -2226        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2227    ) -> bool:
    -2228        resp = await self._request(
    -2229            RequestMethod.GET,
    -2230            f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/",
    -2231            auth=access_token,
    -2232        )
    -2233        assert isinstance(resp, bool)
    -2234        return resp
    +            
    2210    async def fetch_user_clan_invite_setting(
    +2211        self,
    +2212        access_token: str,
    +2213        /,
    +2214        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2215    ) -> bool:
    +2216        resp = await self._request(
    +2217            RequestMethod.GET,
    +2218            f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/",
    +2219            auth=access_token,
    +2220        )
    +2221        assert isinstance(resp, bool)
    +2222        return resp
     
    @@ -10179,16 +10156,16 @@
    Returns
    -
    2236    async def fetch_banned_group_members(
    -2237        self, access_token: str, group_id: int, /, *, page: int = 1
    -2238    ) -> typedefs.JSONObject:
    -2239        resp = await self._request(
    -2240            RequestMethod.GET,
    -2241            f"GroupV2/{group_id}/Banned/?currentpage={page}",
    -2242            auth=access_token,
    -2243        )
    -2244        assert isinstance(resp, dict)
    -2245        return resp
    +            
    2224    async def fetch_banned_group_members(
    +2225        self, access_token: str, group_id: int, /, *, page: int = 1
    +2226    ) -> typedefs.JSONObject:
    +2227        resp = await self._request(
    +2228            RequestMethod.GET,
    +2229            f"GroupV2/{group_id}/Banned/?currentpage={page}",
    +2230            auth=access_token,
    +2231        )
    +2232        assert isinstance(resp, dict)
    +2233        return resp
     
    @@ -10206,16 +10183,16 @@
    Returns
    -
    2247    async def fetch_pending_group_memberships(
    -2248        self, access_token: str, group_id: int, /, *, current_page: int = 1
    -2249    ) -> typedefs.JSONObject:
    -2250        resp = await self._request(
    -2251            RequestMethod.GET,
    -2252            f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}",
    -2253            auth=access_token,
    -2254        )
    -2255        assert isinstance(resp, dict)
    -2256        return resp
    +            
    2235    async def fetch_pending_group_memberships(
    +2236        self, access_token: str, group_id: int, /, *, current_page: int = 1
    +2237    ) -> typedefs.JSONObject:
    +2238        resp = await self._request(
    +2239            RequestMethod.GET,
    +2240            f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}",
    +2241            auth=access_token,
    +2242        )
    +2243        assert isinstance(resp, dict)
    +2244        return resp
     
    @@ -10233,16 +10210,16 @@
    Returns
    -
    2258    async def fetch_invited_group_memberships(
    -2259        self, access_token: str, group_id: int, /, *, current_page: int = 1
    -2260    ) -> typedefs.JSONObject:
    -2261        resp = await self._request(
    -2262            RequestMethod.GET,
    -2263            f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}",
    -2264            auth=access_token,
    -2265        )
    -2266        assert isinstance(resp, dict)
    -2267        return resp
    +            
    2246    async def fetch_invited_group_memberships(
    +2247        self, access_token: str, group_id: int, /, *, current_page: int = 1
    +2248    ) -> typedefs.JSONObject:
    +2249        resp = await self._request(
    +2250            RequestMethod.GET,
    +2251            f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}",
    +2252            auth=access_token,
    +2253        )
    +2254        assert isinstance(resp, dict)
    +2255        return resp
     
    @@ -10260,24 +10237,24 @@
    Returns
    -
    2269    async def invite_member_to_group(
    -2270        self,
    -2271        access_token: str,
    -2272        /,
    -2273        group_id: int,
    -2274        membership_id: int,
    -2275        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2276        *,
    -2277        message: undefined.UndefinedOr[str] = undefined.Undefined,
    -2278    ) -> typedefs.JSONObject:
    -2279        resp = await self._request(
    -2280            RequestMethod.POST,
    -2281            f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/",
    -2282            auth=access_token,
    -2283            json={"message": str(message)},
    -2284        )
    -2285        assert isinstance(resp, dict)
    -2286        return resp
    +            
    2257    async def invite_member_to_group(
    +2258        self,
    +2259        access_token: str,
    +2260        /,
    +2261        group_id: int,
    +2262        membership_id: int,
    +2263        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2264        *,
    +2265        message: undefined.UndefinedOr[str] = undefined.Undefined,
    +2266    ) -> typedefs.JSONObject:
    +2267        resp = await self._request(
    +2268            RequestMethod.POST,
    +2269            f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/",
    +2270            auth=access_token,
    +2271            json={"message": str(message)},
    +2272        )
    +2273        assert isinstance(resp, dict)
    +2274        return resp
     
    @@ -10295,21 +10272,21 @@
    Returns
    -
    2288    async def cancel_group_member_invite(
    -2289        self,
    -2290        access_token: str,
    -2291        /,
    -2292        group_id: int,
    -2293        membership_id: int,
    -2294        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2295    ) -> typedefs.JSONObject:
    -2296        resp = await self._request(
    -2297            RequestMethod.POST,
    -2298            f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/",
    -2299            auth=access_token,
    -2300        )
    -2301        assert isinstance(resp, dict)
    -2302        return resp
    +            
    2276    async def cancel_group_member_invite(
    +2277        self,
    +2278        access_token: str,
    +2279        /,
    +2280        group_id: int,
    +2281        membership_id: int,
    +2282        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2283    ) -> typedefs.JSONObject:
    +2284        resp = await self._request(
    +2285            RequestMethod.POST,
    +2286            f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/",
    +2287            auth=access_token,
    +2288        )
    +2289        assert isinstance(resp, dict)
    +2290        return resp
     
    @@ -10327,10 +10304,10 @@
    Returns
    -
    2304    async def fetch_historical_definition(self) -> typedefs.JSONObject:
    -2305        resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/")
    -2306        assert isinstance(resp, dict)
    -2307        return resp
    +            
    2292    async def fetch_historical_definition(self) -> typedefs.JSONObject:
    +2293        resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/")
    +2294        assert isinstance(resp, dict)
    +2295        return resp
     
    @@ -10348,33 +10325,33 @@
    Returns
    -
    2309    async def fetch_historical_stats(
    -2310        self,
    -2311        character_id: int,
    -2312        membership_id: int,
    -2313        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2314        day_start: datetime.datetime,
    -2315        day_end: datetime.datetime,
    -2316        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    -2317        modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]],
    -2318        *,
    -2319        period_type: enums.PeriodType = enums.PeriodType.ALL_TIME,
    -2320    ) -> typedefs.JSONObject:
    -2321
    -2322        end, start = time.parse_date_range(day_end, day_start)
    -2323        resp = await self._request(
    -2324            RequestMethod.GET,
    -2325            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/",
    -2326            json={
    -2327                "dayend": end,
    -2328                "daystart": start,
    -2329                "groups": [str(int(group)) for group in groups],
    -2330                "modes": [str(int(mode)) for mode in modes],
    -2331                "periodType": int(period_type),
    -2332            },
    -2333        )
    -2334        assert isinstance(resp, dict)
    -2335        return resp
    +            
    2297    async def fetch_historical_stats(
    +2298        self,
    +2299        character_id: int,
    +2300        membership_id: int,
    +2301        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2302        day_start: datetime.datetime,
    +2303        day_end: datetime.datetime,
    +2304        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    +2305        modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]],
    +2306        *,
    +2307        period_type: enums.PeriodType = enums.PeriodType.ALL_TIME,
    +2308    ) -> typedefs.JSONObject:
    +2309
    +2310        end, start = time.parse_date_range(day_end, day_start)
    +2311        resp = await self._request(
    +2312            RequestMethod.GET,
    +2313            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/",
    +2314            json={
    +2315                "dayend": end,
    +2316                "daystart": start,
    +2317                "groups": [str(int(group)) for group in groups],
    +2318                "modes": [str(int(mode)) for mode in modes],
    +2319                "periodType": int(period_type),
    +2320            },
    +2321        )
    +2322        assert isinstance(resp, dict)
    +2323        return resp
     
    @@ -10422,19 +10399,19 @@
    Returns
    -
    2337    async def fetch_historical_stats_for_account(
    -2338        self,
    -2339        membership_id: int,
    -2340        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2341        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    -2342    ) -> typedefs.JSONObject:
    -2343        resp = await self._request(
    -2344            RequestMethod.GET,
    -2345            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/",
    -2346            json={"groups": [str(int(group)) for group in groups]},
    -2347        )
    -2348        assert isinstance(resp, dict)
    -2349        return resp
    +            
    2325    async def fetch_historical_stats_for_account(
    +2326        self,
    +2327        membership_id: int,
    +2328        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2329        groups: list[typedefs.IntAnd[enums.StatsGroupType]],
    +2330    ) -> typedefs.JSONObject:
    +2331        resp = await self._request(
    +2332            RequestMethod.GET,
    +2333            f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/",
    +2334            json={"groups": [str(int(group)) for group in groups]},
    +2335        )
    +2336        assert isinstance(resp, dict)
    +2337        return resp
     
    @@ -10472,20 +10449,20 @@
    Returns
    -
    2351    async def fetch_aggregated_activity_stats(
    -2352        self,
    -2353        character_id: int,
    -2354        membership_id: int,
    -2355        membership_type: typedefs.IntAnd[enums.MembershipType],
    -2356        /,
    -2357    ) -> typedefs.JSONObject:
    -2358        resp = await self._request(
    -2359            RequestMethod.GET,
    -2360            f"Destiny2/{int(membership_type)}/Account/{membership_id}/"
    -2361            f"Character/{character_id}/Stats/AggregateActivityStats/",
    -2362        )
    -2363        assert isinstance(resp, dict)
    -2364        return resp
    +            
    2339    async def fetch_aggregated_activity_stats(
    +2340        self,
    +2341        character_id: int,
    +2342        membership_id: int,
    +2343        membership_type: typedefs.IntAnd[enums.MembershipType],
    +2344        /,
    +2345    ) -> typedefs.JSONObject:
    +2346        resp = await self._request(
    +2347            RequestMethod.GET,
    +2348            f"Destiny2/{int(membership_type)}/Account/{membership_id}/"
    +2349            f"Character/{character_id}/Stats/AggregateActivityStats/",
    +2350        )
    +2351        assert isinstance(resp, dict)
    +2352        return resp
     
    @@ -10523,124 +10500,124 @@
    Returns
    -
    244class RESTPool:
    -245    """Pool of `RESTClient` instances.
    -246
    -247    This allows to create multiple instances of `RESTClient`s that can be acquired
    -248    which share the same config and metadata.
    -249
    -250    Example
    -251    -------
    -252    ```py
    -253    import aiobungie
    -254    import asyncio
    +            
    242class RESTPool:
    +243    """Pool of `RESTClient` instances.
    +244
    +245    This allows to create multiple instances of `RESTClient`s that can be acquired
    +246    which share the same config and metadata.
    +247
    +248    Example
    +249    -------
    +250    ```py
    +251    import aiobungie
    +252    import asyncio
    +253
    +254    client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret')
     255
    -256    client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret')
    -257
    -258    # Using a context manager to acquire an instance
    -259    # of the pool and close the connection after finishing.
    -260
    -261    async def first() -> str:
    -262        async with client_pool.acquire() as client:
    -263            return client.build_oauth2_url()
    -264
    -265    async def second() -> None:
    -266        async with client_pool.acquire() as client:
    -267            new_tokens = await client.refresh_access_token("token")
    -268            client.metadata['tokens'] = new_tokens
    -269
    -270    # Client instances are independent from first and second.
    -271    await asyncio.gather(first(), second())
    -272    ```
    -273
    -274    Parameters
    -275    ----------
    -276    token : `str`
    -277        A valid application token from Bungie's developer portal.
    -278
    -279    Other Parameters
    -280    ----------------
    -281    max_retries : `int`
    -282        The max retries number to retry if the request hit a `5xx` status code.
    -283    max_ratelimit_retries : `int`
    -284        The max retries number to retry if the request hit a `429` status code. Defaults to `3`.
    -285    client_secret : `typing.Optional[str]`
    -286        An optional application client secret,
    -287        This is only needed if you're fetching OAuth2 tokens with this client.
    -288    client_id : `typing.Optional[int]`
    -289        An optional application client id,
    -290        This is only needed if you're fetching OAuth2 tokens with this client.
    -291    enable_debugging : `bool | str`
    -292        Whether to enable logging responses or not.
    -293
    -294    Logging Levels
    -295    --------------
    -296    * `False`: This will disable logging.
    -297    * `True`: This will set the level to `DEBUG` and enable logging minimal information.
    -298    Like the response status, route, taken time and so on.
    -299    * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information.
    -300    """
    -301
    -302    __slots__ = (
    -303        "_token",
    -304        "_max_retries",
    -305        "_client_secret",
    -306        "_client_id",
    -307        "_max_rate_limit_retries",
    -308        "_metadata",
    -309        "_enable_debug",
    -310    )
    -311
    -312    # Looks like mypy doesn't like this.
    -313    if typing.TYPE_CHECKING:
    -314        _enable_debug: typing.Union[typing.Literal["TRACE"], bool, int]
    -315
    -316    def __init__(
    -317        self,
    -318        token: str,
    -319        /,
    -320        client_secret: typing.Optional[str] = None,
    -321        client_id: typing.Optional[int] = None,
    -322        *,
    -323        max_retries: int = 4,
    -324        max_rate_limit_retries: int = 3,
    -325        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    -326    ) -> None:
    -327        self._client_secret = client_secret
    -328        self._client_id = client_id
    -329        self._token: str = token
    -330        self._max_retries = max_retries
    -331        self._max_rate_limit_retries = max_rate_limit_retries
    -332        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    -333        self._enable_debug = enable_debugging
    -334
    -335    @property
    -336    def client_id(self) -> typing.Optional[int]:
    -337        return self._client_id
    -338
    -339    @property
    -340    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    -341        """Pool's Metadata. This is different from client instance metadata."""
    -342        return self._metadata
    -343
    -344    @typing.final
    -345    def acquire(self) -> RESTClient:
    -346        """Acquires a new `RESTClient` instance from this REST pool.
    -347
    -348        Returns
    -349        -------
    -350        `RESTClient`
    -351            An instance of a REST client.
    -352        """
    -353        instance = RESTClient(
    -354            self._token,
    -355            client_secret=self._client_secret,
    -356            client_id=self._client_id,
    -357            max_retries=self._max_retries,
    -358            max_ratelimit_retries=self._max_rate_limit_retries,
    -359            enable_debugging=self._enable_debug,
    -360        )
    -361        return instance
    +256    # Using a context manager to acquire an instance
    +257    # of the pool and close the connection after finishing.
    +258
    +259    async def first() -> str:
    +260        async with client_pool.acquire() as client:
    +261            return client.build_oauth2_url()
    +262
    +263    async def second() -> None:
    +264        async with client_pool.acquire() as client:
    +265            new_tokens = await client.refresh_access_token("token")
    +266            client.metadata['tokens'] = new_tokens
    +267
    +268    # Client instances are independent from first and second.
    +269    await asyncio.gather(first(), second())
    +270    ```
    +271
    +272    Parameters
    +273    ----------
    +274    token : `str`
    +275        A valid application token from Bungie's developer portal.
    +276
    +277    Other Parameters
    +278    ----------------
    +279    max_retries : `int`
    +280        The max retries number to retry if the request hit a `5xx` status code.
    +281    max_ratelimit_retries : `int`
    +282        The max retries number to retry if the request hit a `429` status code. Defaults to `3`.
    +283    client_secret : `typing.Optional[str]`
    +284        An optional application client secret,
    +285        This is only needed if you're fetching OAuth2 tokens with this client.
    +286    client_id : `typing.Optional[int]`
    +287        An optional application client id,
    +288        This is only needed if you're fetching OAuth2 tokens with this client.
    +289    enable_debugging : `bool | str`
    +290        Whether to enable logging responses or not.
    +291
    +292    Logging Levels
    +293    --------------
    +294    * `False`: This will disable logging.
    +295    * `True`: This will set the level to `DEBUG` and enable logging minimal information.
    +296    Like the response status, route, taken time and so on.
    +297    * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information.
    +298    """
    +299
    +300    __slots__ = (
    +301        "_token",
    +302        "_max_retries",
    +303        "_client_secret",
    +304        "_client_id",
    +305        "_max_rate_limit_retries",
    +306        "_metadata",
    +307        "_enable_debug",
    +308    )
    +309
    +310    # Looks like mypy doesn't like this.
    +311    if typing.TYPE_CHECKING:
    +312        _enable_debug: typing.Union[typing.Literal["TRACE"], bool, int]
    +313
    +314    def __init__(
    +315        self,
    +316        token: str,
    +317        /,
    +318        client_secret: typing.Optional[str] = None,
    +319        client_id: typing.Optional[int] = None,
    +320        *,
    +321        max_retries: int = 4,
    +322        max_rate_limit_retries: int = 3,
    +323        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    +324    ) -> None:
    +325        self._client_secret = client_secret
    +326        self._client_id = client_id
    +327        self._token: str = token
    +328        self._max_retries = max_retries
    +329        self._max_rate_limit_retries = max_rate_limit_retries
    +330        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    +331        self._enable_debug = enable_debugging
    +332
    +333    @property
    +334    def client_id(self) -> typing.Optional[int]:
    +335        return self._client_id
    +336
    +337    @property
    +338    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    +339        """Pool's Metadata. This is different from client instance metadata."""
    +340        return self._metadata
    +341
    +342    @typing.final
    +343    def acquire(self) -> RESTClient:
    +344        """Acquires a new `RESTClient` instance from this REST pool.
    +345
    +346        Returns
    +347        -------
    +348        `RESTClient`
    +349            An instance of a REST client.
    +350        """
    +351        instance = RESTClient(
    +352            self._token,
    +353            client_secret=self._client_secret,
    +354            client_id=self._client_id,
    +355            max_retries=self._max_retries,
    +356            max_ratelimit_retries=self._max_rate_limit_retries,
    +357            enable_debugging=self._enable_debug,
    +358        )
    +359        return instance
     
    @@ -10651,7 +10628,8 @@
    Returns
    Example
    -
    import aiobungie
    +
    +
    import aiobungie
     import asyncio
     
     client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret')
    @@ -10670,7 +10648,8 @@ 
    Example
    # Client instances are independent from first and second. await asyncio.gather(first(), second()) -
    +
    +
    Parameters
    @@ -10717,40 +10696,29 @@
    Logging Levels
    -
    316    def __init__(
    -317        self,
    -318        token: str,
    -319        /,
    -320        client_secret: typing.Optional[str] = None,
    -321        client_id: typing.Optional[int] = None,
    -322        *,
    -323        max_retries: int = 4,
    -324        max_rate_limit_retries: int = 3,
    -325        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    -326    ) -> None:
    -327        self._client_secret = client_secret
    -328        self._client_id = client_id
    -329        self._token: str = token
    -330        self._max_retries = max_retries
    -331        self._max_rate_limit_retries = max_rate_limit_retries
    -332        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    -333        self._enable_debug = enable_debugging
    +            
    314    def __init__(
    +315        self,
    +316        token: str,
    +317        /,
    +318        client_secret: typing.Optional[str] = None,
    +319        client_id: typing.Optional[int] = None,
    +320        *,
    +321        max_retries: int = 4,
    +322        max_rate_limit_retries: int = 3,
    +323        enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False,
    +324    ) -> None:
    +325        self._client_secret = client_secret
    +326        self._client_id = client_id
    +327        self._token: str = token
    +328        self._max_retries = max_retries
    +329        self._max_rate_limit_retries = max_rate_limit_retries
    +330        self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {}
    +331        self._enable_debug = enable_debugging
     
    -
    -
    -
    - client_id: Optional[int] - - -
    - - - -
    @@ -10777,24 +10745,24 @@
    Logging Levels
    -
    344    @typing.final
    -345    def acquire(self) -> RESTClient:
    -346        """Acquires a new `RESTClient` instance from this REST pool.
    -347
    -348        Returns
    -349        -------
    -350        `RESTClient`
    -351            An instance of a REST client.
    -352        """
    -353        instance = RESTClient(
    -354            self._token,
    -355            client_secret=self._client_secret,
    -356            client_id=self._client_id,
    -357            max_retries=self._max_retries,
    -358            max_ratelimit_retries=self._max_rate_limit_retries,
    -359            enable_debugging=self._enable_debug,
    -360        )
    -361        return instance
    +            
    342    @typing.final
    +343    def acquire(self) -> RESTClient:
    +344        """Acquires a new `RESTClient` instance from this REST pool.
    +345
    +346        Returns
    +347        -------
    +348        `RESTClient`
    +349            An instance of a REST client.
    +350        """
    +351        instance = RESTClient(
    +352            self._token,
    +353            client_secret=self._client_secret,
    +354            client_id=self._client_id,
    +355            max_retries=self._max_retries,
    +356            max_ratelimit_retries=self._max_rate_limit_retries,
    +357            enable_debugging=self._enable_debug,
    +358        )
    +359        return instance
     
    @@ -10821,19 +10789,19 @@
    Returns
    -
    225class RequestMethod(str, enums.Enum):
    -226    """HTTP request methods enum."""
    -227
    -228    GET = "GET"
    -229    """GET methods."""
    -230    POST = "POST"
    -231    """POST methods."""
    -232    PUT = "PUT"
    -233    """PUT methods."""
    -234    PATCH = "PATCH"
    -235    """PATCH methods."""
    -236    DELETE = "DELETE"
    -237    """DELETE methods"""
    +            
    223class RequestMethod(str, enums.Enum):
    +224    """HTTP request methods enum."""
    +225
    +226    GET = "GET"
    +227    """GET methods."""
    +228    POST = "POST"
    +229    """POST methods."""
    +230    PUT = "PUT"
    +231    """PUT methods."""
    +232    PATCH = "PATCH"
    +233    """PATCH methods."""
    +234    DELETE = "DELETE"
    +235    """DELETE methods"""
     
    @@ -10979,22 +10947,30 @@
    Inherited Members

    You can enable this with the following code

    -
    >>> import logging
    +
    +
    >>> import logging
     >>> logging.getLogger("aiobungie.rest").setLevel(aiobungie.TRACE)
     <h1 id="or">or</h1>
    -
    +
    +
    -
    >>> logging.basicConfig(level=aiobungie.TRACE)
    +
    +
    >>> logging.basicConfig(level=aiobungie.TRACE)
     <h1 id="or-2">Or</h1>
    -
    +
    +
    -
    >>> client = aiobungie.RESTClient(..., enable_debug="TRACE")
    +
    +
    >>> client = aiobungie.RESTClient(..., enable_debug="TRACE")
     <h1 id="or-if-youre-using-aiobungieclient">Or if you're using <code>aiobungie.Client</code></h1>
    -
    +
    +
    -
    >>> client = aiobungie.Client(...)
    +
    +
    >>> client = aiobungie.Client(...)
     >>> client.rest.enable_debugging(level=aiobungie.TRACE, file="rest_logs.txt") # optional file
    -
    +
    +
    @@ -11102,7 +11078,11 @@
    Inherited Members
    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/traits.html b/docs/aiobungie/traits.html index 6bcc43e1..c02c6a57 100644 --- a/docs/aiobungie/traits.html +++ b/docs/aiobungie/traits.html @@ -3,7 +3,7 @@ - + aiobungie.traits API documentation @@ -133,9 +133,9 @@

    Interfaces used for the core aiobungie implementations.

    - + - +
      1# MIT License
       2#
    @@ -172,247 +172,250 @@ 

    33if typing.TYPE_CHECKING: 34 import collections.abc as collections 35 - 36 from aiobungie import client - 37 from aiobungie import interfaces - 38 from aiobungie import rest - 39 from aiobungie.internal import factory as factory_ - 40 + 36 from aiobungie import builders + 37 from aiobungie import client + 38 from aiobungie import interfaces + 39 from aiobungie import rest + 40 from aiobungie.internal import factory as factory_ 41 - 42@typing.runtime_checkable - 43class Netrunner(typing.Protocol): - 44 """Types that can run external requests. - 45 - 46 These requests are performed by a reference of your `aiobungie.Client` instance. - 47 - 48 Example - 49 ------- - 50 ```py - 51 import aiobungie - 52 - 53 membership = aiobungie.crate.DestinyMembership(ā€¦) - 54 # Access the base client that references this membership. - 55 external_request = await membership.net.request.fetch_user(ā€¦) - 56 ``` - 57 """ - 58 - 59 __slots__ = () - 60 - 61 @property - 62 def request(self) -> client.Client: - 63 """A readonly `ClientApp` instance used for external requests.""" - 64 raise NotImplementedError - 65 + 42 + 43@typing.runtime_checkable + 44class Netrunner(typing.Protocol): + 45 """Types that can run external requests. + 46 + 47 These requests are performed by a reference of your `aiobungie.Client` instance. + 48 + 49 Example + 50 ------- + 51 ```py + 52 import aiobungie + 53 + 54 membership = aiobungie.crate.DestinyMembership(ā€¦) + 55 # Access the base client that references this membership. + 56 external_request = await membership.net.request.fetch_user(ā€¦) + 57 ``` + 58 """ + 59 + 60 __slots__ = () + 61 + 62 @property + 63 def request(self) -> client.Client: + 64 """A readonly `ClientApp` instance used for external requests.""" + 65 raise NotImplementedError 66 - 67@typing.runtime_checkable - 68class Serializable(typing.Protocol): - 69 """Types which can deserialize REST payloads responses - 70 into a `aiobungie.crate` implementation using the `Serializable.factory` property. - 71 - 72 Only `ClientApp` implement this trait - 73 """ - 74 - 75 __slots__ = () - 76 - 77 @property - 78 def factory(self) -> factory_.Factory: - 79 """Returns the marshalling factory for the client.""" - 80 raise NotImplementedError - 81 + 67 + 68@typing.runtime_checkable + 69class Serializable(typing.Protocol): + 70 """Types which can deserialize REST payloads responses + 71 into a `aiobungie.crate` implementation using the `Serializable.factory` property. + 72 + 73 Only `ClientApp` implement this trait + 74 """ + 75 + 76 __slots__ = () + 77 + 78 @property + 79 def factory(self) -> factory_.Factory: + 80 """Returns the marshalling factory for the client.""" + 81 raise NotImplementedError 82 - 83@typing.runtime_checkable - 84class Debug(typing.Protocol): - 85 """Objects that are able to enable debugging REST calls.""" - 86 - 87 def enable_debugging( - 88 self, - 89 level: typing.Union[typing.Literal["TRACE"], bool] = False, - 90 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, - 91 /, - 92 ) -> None: - 93 """Enables debugging for the REST calls. - 94 - 95 Logging Levels - 96 -------------- - 97 * `False`: This will disable logging. - 98 * `True`: This will set the level to `DEBUG` and enable logging minimal information. - 99 * `"TRACE"` | `aiobungie.TRACE`: This will log the response headers along with the minimal information. -100 -101 Parameters -102 ----------- -103 level : `str | bool | int` -104 The level of debugging to enable. -105 file : `pathlib.Path | str | None` -106 The file path to write the debug logs to. If provided. -107 """ -108 raise NotImplementedError -109 + 83 + 84@typing.runtime_checkable + 85class Debug(typing.Protocol): + 86 """Objects that are able to enable debugging REST calls.""" + 87 + 88 def enable_debugging( + 89 self, + 90 level: typing.Union[typing.Literal["TRACE"], bool] = False, + 91 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, + 92 /, + 93 ) -> None: + 94 """Enables debugging for the REST calls. + 95 + 96 Logging Levels + 97 -------------- + 98 * `False`: This will disable logging. + 99 * `True`: This will set the level to `DEBUG` and enable logging minimal information. +100 * `"TRACE"` | `aiobungie.TRACE`: This will log the response headers along with the minimal information. +101 +102 Parameters +103 ----------- +104 level : `str | bool | int` +105 The level of debugging to enable. +106 file : `pathlib.Path | str | None` +107 The file path to write the debug logs to. If provided. +108 """ +109 raise NotImplementedError 110 -111@typing.runtime_checkable -112class RESTful(Debug, typing.Protocol): -113 """Types which it is possible to interact with the API directly -114 which provides RESTful functionalities. -115 -116 Only `aiobungie.RESTClient` implement this trait, -117 `ClientApp` may access its RESTClient using `ClientApp.rest` property. -118 """ -119 -120 __slots__ = () -121 -122 @property -123 def client_id(self) -> typing.Optional[int]: -124 """Return the client id of this REST client if provided, Otherwise None.""" -125 raise NotImplementedError -126 -127 @property -128 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: -129 """A mutable mapping storage for the user's needs. -130 -131 This mapping is useful for storing any kind of data that the user may need. -132 -133 Example -134 ------- -135 ```py -136 import aiobungie -137 -138 client = aiobungie.RESTClient(ā€¦) -139 -140 async with client: -141 # Fetch auth tokens and store them -142 client.metadata["tokens"] = await client.fetch_access_token("code") -143 -144 # Some other time. -145 async with client: -146 # Retrieve the tokens -147 tokens: aiobungie.OAuth2Response = client.metadata["tokens"] -148 -149 # Use them to fetch your user. -150 user = await client.fetch_current_user_memberships(tokens.access_token) -151 ``` -152 """ -153 raise NotImplementedError -154 -155 @property -156 def is_alive(self) -> bool: -157 """Returns `True` if the REST client is alive and `False` otherwise.""" -158 raise NotImplementedError -159 -160 def build_oauth2_url( -161 self, client_id: typing.Optional[int] = None -162 ) -> typing.Optional[str]: -163 """Builds an OAuth2 URL using the provided user REST/Base client secret/id. -164 -165 Parameters -166 ---------- -167 client_id : `int | None` -168 An optional client id to provide, If left `None` it will roll back to the id passed -169 to the `RESTClient`, If both is `None` this method will return `None`. -170 -171 Returns -172 ------- -173 `str | None` -174 If the client id was provided as a parameter or provided in `aiobungie.RESTClient`, -175 A complete URL will be returned. -176 Otherwise `None` will be returned. -177 """ -178 raise NotImplementedError -179 -180 def open(self) -> None: -181 """Prepare and opens the REST client connection. +111 +112@typing.runtime_checkable +113class RESTful(Debug, typing.Protocol): +114 """Types which it is possible to interact with the API directly +115 which provides RESTful functionalities. +116 +117 Only `aiobungie.RESTClient` implement this trait, +118 `ClientApp` may access its RESTClient using `ClientApp.rest` property. +119 """ +120 +121 __slots__ = () +122 +123 @property +124 def client_id(self) -> typing.Optional[int]: +125 """Return the client id of this REST client if provided, Otherwise None.""" +126 raise NotImplementedError +127 +128 @property +129 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: +130 """A mutable mapping storage for the user's needs. +131 +132 This mapping is useful for storing any kind of data that the user may need. +133 +134 Example +135 ------- +136 ```py +137 import aiobungie +138 +139 client = aiobungie.RESTClient(ā€¦) +140 +141 async with client: +142 # Fetch auth tokens and store them +143 client.metadata["tokens"] = await client.fetch_access_token("code") +144 +145 # Some other time. +146 async with client: +147 # Retrieve the tokens +148 tokens: aiobungie.OAuth2Response = client.metadata["tokens"] +149 +150 # Use them to fetch your user. +151 user = await client.fetch_current_user_memberships(tokens.access_token) +152 ``` +153 """ +154 raise NotImplementedError +155 +156 @property +157 def is_alive(self) -> bool: +158 """Returns `True` if the REST client is alive and `False` otherwise.""" +159 raise NotImplementedError +160 +161 def build_oauth2_url( +162 self, client_id: typing.Optional[int] = None +163 ) -> typing.Optional[builders.OAuthURL]: +164 """Builds an OAuth2 URL using the provided user REST/Base client secret/id. +165 +166 You can't get the complete string URL by using `.compile()` method. +167 +168 Parameters +169 ---------- +170 client_id : `int | None` +171 An optional client id to provide, If left `None` it will roll back to the id passed +172 to the `RESTClient`, If both is `None` this method will return `None`. +173 +174 Returns +175 ------- +176 `aiobungie.builders.OAuthURL | None` +177 If the client id was provided as a parameter or provided in `aiobungie.RESTClient`, +178 A complete OAuthURL object will be returned. +179 Otherwise `None` will be returned. +180 """ +181 raise NotImplementedError 182 -183 This method is automatically called when using `async with` contextmanager. -184 -185 Raises -186 ------ -187 `RuntimeError` -188 If the client is already open. -189 """ -190 raise NotImplementedError -191 -192 async def close(self) -> None: -193 """Close this REST client session if it was acquired. +183 def open(self) -> None: +184 """Prepare and opens the REST client connection. +185 +186 This method is automatically called when using `async with` contextmanager. +187 +188 Raises +189 ------ +190 `RuntimeError` +191 If the client is already open. +192 """ +193 raise NotImplementedError 194 -195 This method is automatically called when using `async with` contextmanager. -196 -197 Raises -198 ------ -199 `RuntimeError` -200 If the client is already closed. -201 """ -202 raise NotImplementedError -203 -204 async def static_request( -205 self, -206 method: typing.Union[rest.RequestMethod, str], -207 path: str, -208 *, -209 auth: typing.Optional[str] = None, -210 json: typing.Optional[dict[str, typing.Any]] = None, -211 ) -> rest.ResponseSig: -212 """Perform an HTTP request given a valid Bungie endpoint. -213 -214 Parameters -215 ---------- -216 method : `aiobungie.rest.RequestMethod | str` -217 The request method, This may be `GET`, `POST`, `PUT`, etc. -218 path: `str` -219 The Bungie endpoint or path. -220 A path must look something like this `Destiny2/3/Profile/46111239123/...` -221 auth : `str | None` -222 An optional bearer token for methods that requires OAuth2 Authorization header. -223 json : `dict[str, typing.Any] | None` -224 An optional JSON data to include in the request. -225 -226 Returns -227 ------- -228 `aiobungie.rest.ResponseSig` -229 The response payload. -230 """ -231 raise NotImplementedError -232 -233 -234@typing.runtime_checkable -235class ClientApp(Netrunner, Serializable, typing.Protocol): -236 """Core trait for the standard `aiobungie.Client` implementation. -237 -238 This includes all aiobungie traits. -239 """ +195 async def close(self) -> None: +196 """Close this REST client session if it was acquired. +197 +198 This method is automatically called when using `async with` contextmanager. +199 +200 Raises +201 ------ +202 `RuntimeError` +203 If the client is already closed. +204 """ +205 raise NotImplementedError +206 +207 async def static_request( +208 self, +209 method: typing.Union[rest.RequestMethod, str], +210 path: str, +211 *, +212 auth: typing.Optional[str] = None, +213 json: typing.Optional[dict[str, typing.Any]] = None, +214 ) -> rest.ResponseSig: +215 """Perform an HTTP request given a valid Bungie endpoint. +216 +217 Parameters +218 ---------- +219 method : `aiobungie.rest.RequestMethod | str` +220 The request method, This may be `GET`, `POST`, `PUT`, etc. +221 path: `str` +222 The Bungie endpoint or path. +223 A path must look something like this `Destiny2/3/Profile/46111239123/...` +224 auth : `str | None` +225 An optional bearer token for methods that requires OAuth2 Authorization header. +226 json : `dict[str, typing.Any] | None` +227 An optional JSON data to include in the request. +228 +229 Returns +230 ------- +231 `aiobungie.rest.ResponseSig` +232 The response payload. +233 """ +234 raise NotImplementedError +235 +236 +237@typing.runtime_checkable +238class ClientApp(Netrunner, Serializable, typing.Protocol): +239 """Core trait for the standard `aiobungie.Client` implementation. 240 -241 __slots__ = () -242 -243 def run( -244 self, future: collections.Coroutine[None, None, None], debug: bool = False -245 ) -> None: -246 """Runs a coroutine function until its complete. -247 -248 This is equivalent to `asyncio.get_event_loop().run_until_complete(...)` -249 -250 Parameters -251 ---------- -252 future: `collections.Coroutine[None, None, None]` -253 A coroutine object. -254 debug : `bool` -255 Either to enable asyncio debug or not. Disabled by default. -256 -257 Example -258 ------- -259 ```py -260 async def main() -> None: -261 await fetch(...) -262 -263 # Run the coroutine. -264 client.run(main()) -265 ``` -266 """ -267 -268 @property -269 def rest(self) -> interfaces.RESTInterface: -270 """Returns the REST client for the this client.""" -271 raise NotImplementedError -272 -273 @property -274 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: -275 """A mutable mapping storage for the user's needs.""" -276 raise NotImplementedError +241 This includes all aiobungie traits. +242 """ +243 +244 __slots__ = () +245 +246 def run( +247 self, future: collections.Coroutine[None, None, None], debug: bool = False +248 ) -> None: +249 """Runs a coroutine function until its complete. +250 +251 This is equivalent to `asyncio.get_event_loop().run_until_complete(...)` +252 +253 Parameters +254 ---------- +255 future: `collections.Coroutine[None, None, None]` +256 A coroutine object. +257 debug : `bool` +258 Either to enable asyncio debug or not. Disabled by default. +259 +260 Example +261 ------- +262 ```py +263 async def main() -> None: +264 await fetch(...) +265 +266 # Run the coroutine. +267 client.run(main()) +268 ``` +269 """ +270 +271 @property +272 def rest(self) -> interfaces.RESTInterface: +273 """Returns the REST client for the this client.""" +274 raise NotImplementedError +275 +276 @property +277 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: +278 """A mutable mapping storage for the user's needs.""" +279 raise NotImplementedError

    @@ -429,49 +432,49 @@

    -
    235@typing.runtime_checkable
    -236class ClientApp(Netrunner, Serializable, typing.Protocol):
    -237    """Core trait for the standard `aiobungie.Client` implementation.
    -238
    -239    This includes all aiobungie traits.
    -240    """
    +            
    238@typing.runtime_checkable
    +239class ClientApp(Netrunner, Serializable, typing.Protocol):
    +240    """Core trait for the standard `aiobungie.Client` implementation.
     241
    -242    __slots__ = ()
    -243
    -244    def run(
    -245        self, future: collections.Coroutine[None, None, None], debug: bool = False
    -246    ) -> None:
    -247        """Runs a coroutine function until its complete.
    -248
    -249        This is equivalent to `asyncio.get_event_loop().run_until_complete(...)`
    -250
    -251        Parameters
    -252        ----------
    -253        future: `collections.Coroutine[None, None, None]`
    -254            A coroutine object.
    -255        debug : `bool`
    -256            Either to enable asyncio debug or not. Disabled by default.
    -257
    -258        Example
    -259        -------
    -260        ```py
    -261        async def main() -> None:
    -262            await fetch(...)
    -263
    -264        # Run the coroutine.
    -265        client.run(main())
    -266        ```
    -267        """
    -268
    -269    @property
    -270    def rest(self) -> interfaces.RESTInterface:
    -271        """Returns the REST client for the this client."""
    -272        raise NotImplementedError
    -273
    -274    @property
    -275    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    -276        """A mutable mapping storage for the user's needs."""
    -277        raise NotImplementedError
    +242    This includes all aiobungie traits.
    +243    """
    +244
    +245    __slots__ = ()
    +246
    +247    def run(
    +248        self, future: collections.Coroutine[None, None, None], debug: bool = False
    +249    ) -> None:
    +250        """Runs a coroutine function until its complete.
    +251
    +252        This is equivalent to `asyncio.get_event_loop().run_until_complete(...)`
    +253
    +254        Parameters
    +255        ----------
    +256        future: `collections.Coroutine[None, None, None]`
    +257            A coroutine object.
    +258        debug : `bool`
    +259            Either to enable asyncio debug or not. Disabled by default.
    +260
    +261        Example
    +262        -------
    +263        ```py
    +264        async def main() -> None:
    +265            await fetch(...)
    +266
    +267        # Run the coroutine.
    +268        client.run(main())
    +269        ```
    +270        """
    +271
    +272    @property
    +273    def rest(self) -> interfaces.RESTInterface:
    +274        """Returns the REST client for the this client."""
    +275        raise NotImplementedError
    +276
    +277    @property
    +278    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    +279        """A mutable mapping storage for the user's needs."""
    +280        raise NotImplementedError
     
    @@ -535,30 +538,30 @@

    -
    244    def run(
    -245        self, future: collections.Coroutine[None, None, None], debug: bool = False
    -246    ) -> None:
    -247        """Runs a coroutine function until its complete.
    -248
    -249        This is equivalent to `asyncio.get_event_loop().run_until_complete(...)`
    -250
    -251        Parameters
    -252        ----------
    -253        future: `collections.Coroutine[None, None, None]`
    -254            A coroutine object.
    -255        debug : `bool`
    -256            Either to enable asyncio debug or not. Disabled by default.
    -257
    -258        Example
    -259        -------
    -260        ```py
    -261        async def main() -> None:
    -262            await fetch(...)
    -263
    -264        # Run the coroutine.
    -265        client.run(main())
    -266        ```
    -267        """
    +            
    247    def run(
    +248        self, future: collections.Coroutine[None, None, None], debug: bool = False
    +249    ) -> None:
    +250        """Runs a coroutine function until its complete.
    +251
    +252        This is equivalent to `asyncio.get_event_loop().run_until_complete(...)`
    +253
    +254        Parameters
    +255        ----------
    +256        future: `collections.Coroutine[None, None, None]`
    +257            A coroutine object.
    +258        debug : `bool`
    +259            Either to enable asyncio debug or not. Disabled by default.
    +260
    +261        Example
    +262        -------
    +263        ```py
    +264        async def main() -> None:
    +265            await fetch(...)
    +266
    +267        # Run the coroutine.
    +268        client.run(main())
    +269        ```
    +270        """
     
    @@ -577,12 +580,14 @@
    Parameters
    Example
    -
    async def main() -> None:
    +
    +
    async def main() -> None:
         await fetch(...)
     
     # Run the coroutine.
     client.run(main())
    -
    +
    +
    @@ -639,29 +644,29 @@
    Inherited Members
    -
    43@typing.runtime_checkable
    -44class Netrunner(typing.Protocol):
    -45    """Types that can run external requests.
    -46
    -47    These requests are performed by a reference of your `aiobungie.Client` instance.
    -48
    -49    Example
    -50    -------
    -51    ```py
    -52    import aiobungie
    -53
    -54    membership = aiobungie.crate.DestinyMembership(ā€¦)
    -55    # Access the base client that references this membership.
    -56    external_request = await membership.net.request.fetch_user(ā€¦)
    -57    ```
    -58    """
    -59
    -60    __slots__ = ()
    -61
    -62    @property
    -63    def request(self) -> client.Client:
    -64        """A readonly `ClientApp` instance used for external requests."""
    -65        raise NotImplementedError
    +            
    44@typing.runtime_checkable
    +45class Netrunner(typing.Protocol):
    +46    """Types that can run external requests.
    +47
    +48    These requests are performed by a reference of your `aiobungie.Client` instance.
    +49
    +50    Example
    +51    -------
    +52    ```py
    +53    import aiobungie
    +54
    +55    membership = aiobungie.crate.DestinyMembership(ā€¦)
    +56    # Access the base client that references this membership.
    +57    external_request = await membership.net.request.fetch_user(ā€¦)
    +58    ```
    +59    """
    +60
    +61    __slots__ = ()
    +62
    +63    @property
    +64    def request(self) -> client.Client:
    +65        """A readonly `ClientApp` instance used for external requests."""
    +66        raise NotImplementedError
     
    @@ -671,12 +676,14 @@
    Inherited Members
    Example
    -
    import aiobungie
    +
    +
    import aiobungie
     
     membership = aiobungie.crate.DestinyMembership(ā€¦)
     # Access the base client that references this membership.
     external_request = await membership.net.request.fetch_user(ā€¦)
    -
    +
    +
    @@ -749,20 +756,20 @@
    Example
    -
    68@typing.runtime_checkable
    -69class Serializable(typing.Protocol):
    -70    """Types which can deserialize REST payloads responses
    -71    into a `aiobungie.crate` implementation using the `Serializable.factory` property.
    -72
    -73    Only `ClientApp` implement this trait
    -74    """
    -75
    -76    __slots__ = ()
    -77
    -78    @property
    -79    def factory(self) -> factory_.Factory:
    -80        """Returns the marshalling factory for the client."""
    -81        raise NotImplementedError
    +            
    69@typing.runtime_checkable
    +70class Serializable(typing.Protocol):
    +71    """Types which can deserialize REST payloads responses
    +72    into a `aiobungie.crate` implementation using the `Serializable.factory` property.
    +73
    +74    Only `ClientApp` implement this trait
    +75    """
    +76
    +77    __slots__ = ()
    +78
    +79    @property
    +80    def factory(self) -> factory_.Factory:
    +81        """Returns the marshalling factory for the client."""
    +82        raise NotImplementedError
     
    @@ -842,127 +849,129 @@
    Example
    -
    112@typing.runtime_checkable
    -113class RESTful(Debug, typing.Protocol):
    -114    """Types which it is possible to interact with the API directly
    -115    which provides RESTful functionalities.
    -116
    -117    Only `aiobungie.RESTClient` implement this trait,
    -118    `ClientApp` may access its RESTClient using `ClientApp.rest` property.
    -119    """
    -120
    -121    __slots__ = ()
    -122
    -123    @property
    -124    def client_id(self) -> typing.Optional[int]:
    -125        """Return the client id of this REST client if provided, Otherwise None."""
    -126        raise NotImplementedError
    -127
    -128    @property
    -129    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    -130        """A mutable mapping storage for the user's needs.
    -131
    -132        This mapping is useful for storing any kind of data that the user may need.
    -133
    -134        Example
    -135        -------
    -136        ```py
    -137        import aiobungie
    -138
    -139        client = aiobungie.RESTClient(ā€¦)
    -140
    -141        async with client:
    -142            # Fetch auth tokens and store them
    -143            client.metadata["tokens"] = await client.fetch_access_token("code")
    -144
    -145        # Some other time.
    -146        async with client:
    -147            # Retrieve the tokens
    -148            tokens: aiobungie.OAuth2Response = client.metadata["tokens"]
    -149
    -150            # Use them to fetch your user.
    -151            user = await client.fetch_current_user_memberships(tokens.access_token)
    -152        ```
    -153        """
    -154        raise NotImplementedError
    -155
    -156    @property
    -157    def is_alive(self) -> bool:
    -158        """Returns `True` if the REST client is alive and `False` otherwise."""
    -159        raise NotImplementedError
    -160
    -161    def build_oauth2_url(
    -162        self, client_id: typing.Optional[int] = None
    -163    ) -> typing.Optional[str]:
    -164        """Builds an OAuth2 URL using the provided user REST/Base client secret/id.
    -165
    -166        Parameters
    -167        ----------
    -168        client_id : `int | None`
    -169            An optional client id to provide, If left `None` it will roll back to the id passed
    -170            to the `RESTClient`, If both is `None` this method will return `None`.
    -171
    -172        Returns
    -173        -------
    -174        `str | None`
    -175            If the client id was provided as a parameter or provided in `aiobungie.RESTClient`,
    -176            A complete URL will be returned.
    -177            Otherwise `None` will be returned.
    -178        """
    -179        raise NotImplementedError
    -180
    -181    def open(self) -> None:
    -182        """Prepare and opens the REST client connection.
    +            
    113@typing.runtime_checkable
    +114class RESTful(Debug, typing.Protocol):
    +115    """Types which it is possible to interact with the API directly
    +116    which provides RESTful functionalities.
    +117
    +118    Only `aiobungie.RESTClient` implement this trait,
    +119    `ClientApp` may access its RESTClient using `ClientApp.rest` property.
    +120    """
    +121
    +122    __slots__ = ()
    +123
    +124    @property
    +125    def client_id(self) -> typing.Optional[int]:
    +126        """Return the client id of this REST client if provided, Otherwise None."""
    +127        raise NotImplementedError
    +128
    +129    @property
    +130    def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]:
    +131        """A mutable mapping storage for the user's needs.
    +132
    +133        This mapping is useful for storing any kind of data that the user may need.
    +134
    +135        Example
    +136        -------
    +137        ```py
    +138        import aiobungie
    +139
    +140        client = aiobungie.RESTClient(ā€¦)
    +141
    +142        async with client:
    +143            # Fetch auth tokens and store them
    +144            client.metadata["tokens"] = await client.fetch_access_token("code")
    +145
    +146        # Some other time.
    +147        async with client:
    +148            # Retrieve the tokens
    +149            tokens: aiobungie.OAuth2Response = client.metadata["tokens"]
    +150
    +151            # Use them to fetch your user.
    +152            user = await client.fetch_current_user_memberships(tokens.access_token)
    +153        ```
    +154        """
    +155        raise NotImplementedError
    +156
    +157    @property
    +158    def is_alive(self) -> bool:
    +159        """Returns `True` if the REST client is alive and `False` otherwise."""
    +160        raise NotImplementedError
    +161
    +162    def build_oauth2_url(
    +163        self, client_id: typing.Optional[int] = None
    +164    ) -> typing.Optional[builders.OAuthURL]:
    +165        """Builds an OAuth2 URL using the provided user REST/Base client secret/id.
    +166
    +167        You can't get the complete string URL by using `.compile()` method.
    +168
    +169        Parameters
    +170        ----------
    +171        client_id : `int | None`
    +172            An optional client id to provide, If left `None` it will roll back to the id passed
    +173            to the `RESTClient`, If both is `None` this method will return `None`.
    +174
    +175        Returns
    +176        -------
    +177        `aiobungie.builders.OAuthURL | None`
    +178            If the client id was provided as a parameter or provided in `aiobungie.RESTClient`,
    +179            A complete OAuthURL object will be returned.
    +180            Otherwise `None` will be returned.
    +181        """
    +182        raise NotImplementedError
     183
    -184        This method is automatically called when using `async with` contextmanager.
    -185
    -186        Raises
    -187        ------
    -188        `RuntimeError`
    -189            If the client is already open.
    -190        """
    -191        raise NotImplementedError
    -192
    -193    async def close(self) -> None:
    -194        """Close this REST client session if it was acquired.
    +184    def open(self) -> None:
    +185        """Prepare and opens the REST client connection.
    +186
    +187        This method is automatically called when using `async with` contextmanager.
    +188
    +189        Raises
    +190        ------
    +191        `RuntimeError`
    +192            If the client is already open.
    +193        """
    +194        raise NotImplementedError
     195
    -196        This method is automatically called when using `async with` contextmanager.
    -197
    -198        Raises
    -199        ------
    -200        `RuntimeError`
    -201            If the client is already closed.
    -202        """
    -203        raise NotImplementedError
    -204
    -205    async def static_request(
    -206        self,
    -207        method: typing.Union[rest.RequestMethod, str],
    -208        path: str,
    -209        *,
    -210        auth: typing.Optional[str] = None,
    -211        json: typing.Optional[dict[str, typing.Any]] = None,
    -212    ) -> rest.ResponseSig:
    -213        """Perform an HTTP request given a valid Bungie endpoint.
    -214
    -215        Parameters
    -216        ----------
    -217        method : `aiobungie.rest.RequestMethod | str`
    -218            The request method, This may be `GET`, `POST`, `PUT`, etc.
    -219        path: `str`
    -220            The Bungie endpoint or path.
    -221            A path must look something like this `Destiny2/3/Profile/46111239123/...`
    -222        auth : `str | None`
    -223            An optional bearer token for methods that requires OAuth2 Authorization header.
    -224        json : `dict[str, typing.Any] | None`
    -225            An optional JSON data to include in the request.
    -226
    -227        Returns
    -228        -------
    -229        `aiobungie.rest.ResponseSig`
    -230            The response payload.
    -231        """
    -232        raise NotImplementedError
    +196    async def close(self) -> None:
    +197        """Close this REST client session if it was acquired.
    +198
    +199        This method is automatically called when using `async with` contextmanager.
    +200
    +201        Raises
    +202        ------
    +203        `RuntimeError`
    +204            If the client is already closed.
    +205        """
    +206        raise NotImplementedError
    +207
    +208    async def static_request(
    +209        self,
    +210        method: typing.Union[rest.RequestMethod, str],
    +211        path: str,
    +212        *,
    +213        auth: typing.Optional[str] = None,
    +214        json: typing.Optional[dict[str, typing.Any]] = None,
    +215    ) -> rest.ResponseSig:
    +216        """Perform an HTTP request given a valid Bungie endpoint.
    +217
    +218        Parameters
    +219        ----------
    +220        method : `aiobungie.rest.RequestMethod | str`
    +221            The request method, This may be `GET`, `POST`, `PUT`, etc.
    +222        path: `str`
    +223            The Bungie endpoint or path.
    +224            A path must look something like this `Destiny2/3/Profile/46111239123/...`
    +225        auth : `str | None`
    +226            An optional bearer token for methods that requires OAuth2 Authorization header.
    +227        json : `dict[str, typing.Any] | None`
    +228            An optional JSON data to include in the request.
    +229
    +230        Returns
    +231        -------
    +232        `aiobungie.rest.ResponseSig`
    +233            The response payload.
    +234        """
    +235        raise NotImplementedError
     
    @@ -1044,7 +1053,8 @@
    Example
    Example
    -
    import aiobungie
    +
    +
    import aiobungie
     
     client = aiobungie.RESTClient(ā€¦)
     
    @@ -1059,7 +1069,8 @@ 
    Example
    # Use them to fetch your user. user = await client.fetch_current_user_memberships(tokens.access_token) -
    +
    +
    @@ -1082,36 +1093,40 @@
    Example
    def - build_oauth2_url(self, client_id: Optional[int] = None) -> Optional[str]: + build_oauth2_url( self, client_id: Optional[int] = None) -> Optional[aiobungie.builders.OAuthURL]:
    -
    161    def build_oauth2_url(
    -162        self, client_id: typing.Optional[int] = None
    -163    ) -> typing.Optional[str]:
    -164        """Builds an OAuth2 URL using the provided user REST/Base client secret/id.
    -165
    -166        Parameters
    -167        ----------
    -168        client_id : `int | None`
    -169            An optional client id to provide, If left `None` it will roll back to the id passed
    -170            to the `RESTClient`, If both is `None` this method will return `None`.
    -171
    -172        Returns
    -173        -------
    -174        `str | None`
    -175            If the client id was provided as a parameter or provided in `aiobungie.RESTClient`,
    -176            A complete URL will be returned.
    -177            Otherwise `None` will be returned.
    -178        """
    -179        raise NotImplementedError
    +            
    162    def build_oauth2_url(
    +163        self, client_id: typing.Optional[int] = None
    +164    ) -> typing.Optional[builders.OAuthURL]:
    +165        """Builds an OAuth2 URL using the provided user REST/Base client secret/id.
    +166
    +167        You can't get the complete string URL by using `.compile()` method.
    +168
    +169        Parameters
    +170        ----------
    +171        client_id : `int | None`
    +172            An optional client id to provide, If left `None` it will roll back to the id passed
    +173            to the `RESTClient`, If both is `None` this method will return `None`.
    +174
    +175        Returns
    +176        -------
    +177        `aiobungie.builders.OAuthURL | None`
    +178            If the client id was provided as a parameter or provided in `aiobungie.RESTClient`,
    +179            A complete OAuthURL object will be returned.
    +180            Otherwise `None` will be returned.
    +181        """
    +182        raise NotImplementedError
     

    Builds an OAuth2 URL using the provided user REST/Base client secret/id.

    +

    You can't get the complete string URL by using .compile() method.

    +
    Parameters
      @@ -1123,8 +1138,8 @@
      Parameters
      Returns
    @@ -1142,17 +1157,17 @@
    Returns
    -
    181    def open(self) -> None:
    -182        """Prepare and opens the REST client connection.
    -183
    -184        This method is automatically called when using `async with` contextmanager.
    -185
    -186        Raises
    -187        ------
    -188        `RuntimeError`
    -189            If the client is already open.
    -190        """
    -191        raise NotImplementedError
    +            
    184    def open(self) -> None:
    +185        """Prepare and opens the REST client connection.
    +186
    +187        This method is automatically called when using `async with` contextmanager.
    +188
    +189        Raises
    +190        ------
    +191        `RuntimeError`
    +192            If the client is already open.
    +193        """
    +194        raise NotImplementedError
     
    @@ -1180,17 +1195,17 @@
    Raises
    -
    193    async def close(self) -> None:
    -194        """Close this REST client session if it was acquired.
    -195
    -196        This method is automatically called when using `async with` contextmanager.
    -197
    -198        Raises
    -199        ------
    -200        `RuntimeError`
    -201            If the client is already closed.
    -202        """
    -203        raise NotImplementedError
    +            
    196    async def close(self) -> None:
    +197        """Close this REST client session if it was acquired.
    +198
    +199        This method is automatically called when using `async with` contextmanager.
    +200
    +201        Raises
    +202        ------
    +203        `RuntimeError`
    +204            If the client is already closed.
    +205        """
    +206        raise NotImplementedError
     
    @@ -1218,34 +1233,34 @@
    Raises
    -
    205    async def static_request(
    -206        self,
    -207        method: typing.Union[rest.RequestMethod, str],
    -208        path: str,
    -209        *,
    -210        auth: typing.Optional[str] = None,
    -211        json: typing.Optional[dict[str, typing.Any]] = None,
    -212    ) -> rest.ResponseSig:
    -213        """Perform an HTTP request given a valid Bungie endpoint.
    -214
    -215        Parameters
    -216        ----------
    -217        method : `aiobungie.rest.RequestMethod | str`
    -218            The request method, This may be `GET`, `POST`, `PUT`, etc.
    -219        path: `str`
    -220            The Bungie endpoint or path.
    -221            A path must look something like this `Destiny2/3/Profile/46111239123/...`
    -222        auth : `str | None`
    -223            An optional bearer token for methods that requires OAuth2 Authorization header.
    -224        json : `dict[str, typing.Any] | None`
    -225            An optional JSON data to include in the request.
    -226
    -227        Returns
    -228        -------
    -229        `aiobungie.rest.ResponseSig`
    -230            The response payload.
    -231        """
    -232        raise NotImplementedError
    +            
    208    async def static_request(
    +209        self,
    +210        method: typing.Union[rest.RequestMethod, str],
    +211        path: str,
    +212        *,
    +213        auth: typing.Optional[str] = None,
    +214        json: typing.Optional[dict[str, typing.Any]] = None,
    +215    ) -> rest.ResponseSig:
    +216        """Perform an HTTP request given a valid Bungie endpoint.
    +217
    +218        Parameters
    +219        ----------
    +220        method : `aiobungie.rest.RequestMethod | str`
    +221            The request method, This may be `GET`, `POST`, `PUT`, etc.
    +222        path: `str`
    +223            The Bungie endpoint or path.
    +224            A path must look something like this `Destiny2/3/Profile/46111239123/...`
    +225        auth : `str | None`
    +226            An optional bearer token for methods that requires OAuth2 Authorization header.
    +227        json : `dict[str, typing.Any] | None`
    +228            An optional JSON data to include in the request.
    +229
    +230        Returns
    +231        -------
    +232        `aiobungie.rest.ResponseSig`
    +233            The response payload.
    +234        """
    +235        raise NotImplementedError
     
    @@ -1296,32 +1311,32 @@
    Inherited Members
    -
     84@typing.runtime_checkable
    - 85class Debug(typing.Protocol):
    - 86    """Objects that are able to enable debugging REST calls."""
    - 87
    - 88    def enable_debugging(
    - 89        self,
    - 90        level: typing.Union[typing.Literal["TRACE"], bool] = False,
    - 91        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
    - 92        /,
    - 93    ) -> None:
    - 94        """Enables debugging for the REST calls.
    - 95
    - 96        Logging Levels
    - 97        --------------
    - 98        * `False`: This will disable logging.
    - 99        * `True`: This will set the level to `DEBUG` and enable logging minimal information.
    -100        * `"TRACE"` | `aiobungie.TRACE`: This will log the response headers along with the minimal information.
    -101
    -102        Parameters
    -103        -----------
    -104        level : `str | bool | int`
    -105            The level of debugging to enable.
    -106        file : `pathlib.Path | str | None`
    -107            The file path to write the debug logs to. If provided.
    -108        """
    -109        raise NotImplementedError
    +            
     85@typing.runtime_checkable
    + 86class Debug(typing.Protocol):
    + 87    """Objects that are able to enable debugging REST calls."""
    + 88
    + 89    def enable_debugging(
    + 90        self,
    + 91        level: typing.Union[typing.Literal["TRACE"], bool] = False,
    + 92        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
    + 93        /,
    + 94    ) -> None:
    + 95        """Enables debugging for the REST calls.
    + 96
    + 97        Logging Levels
    + 98        --------------
    + 99        * `False`: This will disable logging.
    +100        * `True`: This will set the level to `DEBUG` and enable logging minimal information.
    +101        * `"TRACE"` | `aiobungie.TRACE`: This will log the response headers along with the minimal information.
    +102
    +103        Parameters
    +104        -----------
    +105        level : `str | bool | int`
    +106            The level of debugging to enable.
    +107        file : `pathlib.Path | str | None`
    +108            The file path to write the debug logs to. If provided.
    +109        """
    +110        raise NotImplementedError
     
    @@ -1383,28 +1398,28 @@
    Inherited Members
    -
     88    def enable_debugging(
    - 89        self,
    - 90        level: typing.Union[typing.Literal["TRACE"], bool] = False,
    - 91        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
    - 92        /,
    - 93    ) -> None:
    - 94        """Enables debugging for the REST calls.
    - 95
    - 96        Logging Levels
    - 97        --------------
    - 98        * `False`: This will disable logging.
    - 99        * `True`: This will set the level to `DEBUG` and enable logging minimal information.
    -100        * `"TRACE"` | `aiobungie.TRACE`: This will log the response headers along with the minimal information.
    -101
    -102        Parameters
    -103        -----------
    -104        level : `str | bool | int`
    -105            The level of debugging to enable.
    -106        file : `pathlib.Path | str | None`
    -107            The file path to write the debug logs to. If provided.
    -108        """
    -109        raise NotImplementedError
    +            
     89    def enable_debugging(
    + 90        self,
    + 91        level: typing.Union[typing.Literal["TRACE"], bool] = False,
    + 92        file: typing.Optional[typing.Union[pathlib.Path, str]] = None,
    + 93        /,
    + 94    ) -> None:
    + 95        """Enables debugging for the REST calls.
    + 96
    + 97        Logging Levels
    + 98        --------------
    + 99        * `False`: This will disable logging.
    +100        * `True`: This will set the level to `DEBUG` and enable logging minimal information.
    +101        * `"TRACE"` | `aiobungie.TRACE`: This will log the response headers along with the minimal information.
    +102
    +103        Parameters
    +104        -----------
    +105        level : `str | bool | int`
    +106            The level of debugging to enable.
    +107        file : `pathlib.Path | str | None`
    +108            The file path to write the debug logs to. If provided.
    +109        """
    +110        raise NotImplementedError
     
    @@ -1415,7 +1430,7 @@
    Logging Levels
    • False: This will disable logging.
    • True: This will set the level to DEBUG and enable logging minimal information.
    • -
    • "TRACE" | aiobungie.TRACE: This will log the response headers along with the minimal information.
    • +
    • "TRACE" | aiobungie.TRACE: This will log the response headers along with the minimal information.
    Parameters
    @@ -1534,7 +1549,11 @@
    Parameters
    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/typedefs.html b/docs/aiobungie/typedefs.html index 169b8454..495b157a 100644 --- a/docs/aiobungie/typedefs.html +++ b/docs/aiobungie/typedefs.html @@ -3,7 +3,7 @@ - + aiobungie.typedefs API documentation @@ -70,9 +70,9 @@

    A module that has type definitions used globally in aiobungie.

    - + - +
     1# MIT License
      2#
    @@ -353,7 +353,11 @@ 

    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/undefined.html b/docs/aiobungie/undefined.html index b280ad43..4a737988 100644 --- a/docs/aiobungie/undefined.html +++ b/docs/aiobungie/undefined.html @@ -3,7 +3,7 @@ - + aiobungie.undefined API documentation @@ -64,9 +64,9 @@

    An undefined type object.

    - + - +
     1# MIT License
      2#
    @@ -314,7 +314,11 @@ 

    let heading; switch (result.doc.type) { case "function": - heading = `${doc.funcdef} ${doc.fullname}${doc.signature}:`; + if (doc.fullname.endsWith(".__init__")) { + heading = `${doc.fullname.replace(/\.__init__$/, "")}${doc.signature}`; + } else { + heading = `${doc.funcdef} ${doc.fullname}${doc.signature}`; + } break; case "class": heading = `class ${doc.fullname}`; diff --git a/docs/aiobungie/url.html b/docs/aiobungie/url.html index a74bfb45..5520ed1b 100644 --- a/docs/aiobungie/url.html +++ b/docs/aiobungie/url.html @@ -3,7 +3,7 @@ - + aiobungie.url API documentation @@ -42,9 +42,6 @@

    API Documentation

  • TOKEN_EP
  • -
  • - OAUTH2_EP_BUILDER -
  • @@ -64,9 +61,9 @@

    Bungie API endpoint urls.

    - + - +
     1# MIT License
      2#
    @@ -94,7 +91,7 @@ 

    24 25from __future__ import annotations 26 -27__all__ = ("BASE", "REST_EP", "OAUTH_EP", "TOKEN_EP", "OAUTH2_EP_BUILDER") +27__all__ = ("BASE", "REST_EP", "OAUTH_EP", "TOKEN_EP") 28 29import typing 30 @@ -109,25 +106,6 @@

    39 40TOKEN_EP: typing.Final[str] = "/App/OAuth/token" 41"""OAuth token endpoint""" -42 -43OAUTH2_EP_BUILDER: typing.Final[ -44 str -45] = "{oauth_endpoint}?client_id={client_id}&response_type=code&state={uuid}" -46"""Builds an OAuth2 authorize URL given an application client id. -47 -48Parameters may be passed as kwargs using `str.format` method. i.e., -49 -50Example -51------- -52```py -53import aiobungie -54import uuid -55 -56aiobungie.url.OAUTH2_EP_BUILDER.format( -57 oauth_endpoint=aiobungie.url.OAUTH_EP, client_id=1234, uuid=str(uuid.uuid4()) -58) -59``` -60"""

    @@ -183,31 +161,6 @@

    - -
    -
    - OAUTH2_EP_BUILDER: Final[str] = '{oauth_endpoint}?client_id={client_id}&response_type=code&state={uuid}' - - -
    - - -

    Builds an OAuth2 authorize URL given an application client id.

    - -

    Parameters may be passed as kwargs using str.format method. i.e.,

    - -
    Example
    - -
    import aiobungie
    -import uuid
    -
    -aiobungie.url.OAUTH2_EP_BUILDER.format(
    -    oauth_endpoint=aiobungie.url.OAUTH_EP, client_id=1234, uuid=str(uuid.uuid4())
    -)
    -
    -
    - -