psnawp_api.models.client — PSNAWP 1.1.0 documentation

# Source code for psnawp_api.models.client

    from __future__ import annotations

    from typing import Any, Iterator, Optional, Literal

    from psnawp_api.models.group import Group
    from psnawp_api.models.title_stats import TitleStats
    from psnawp_api.models.trophies.trophy import Trophy, TrophyBuilder
    from psnawp_api.models.trophies.trophy_group import (
        TrophyGroupsSummary,
        TrophyGroupsSummaryBuilder,
    )
    from psnawp_api.models.trophies.trophy_summary import TrophySummary
    from psnawp_api.models.trophies.trophy_titles import TrophyTitles, TrophyTitle
    from psnawp_api.models.user import User
    from psnawp_api.utils.endpoints import BASE_PATH, API_PATH
    from psnawp_api.utils.request_builder import RequestBuilder

    class Client:
        """The Client class provides the information and methods for the currently authenticated user."""

        def __init__(self, request_builder: RequestBuilder):
            """Initialize a Client instance.

            .. note::

                This class is intended to be interfaced with through PSNAWP.

            :param request_builder: The instance of RequestBuilder. Used to make HTTPRequests.
            :type request_builder: RequestBuilder

            """
            self._request_builder = request_builder

        @property
        def online_id(self) -> str:
            """Gets the online ID of the client logged in the api.

            :returns: onlineID
            :rtype: str

            .. code-block:: Python

                client = psnawp.me()
                print(client.online_id)

            """
            response = self._request_builder.get(url=f"{BASE_PATH['profile_uri']}{API_PATH['profiles'].format(account_id=self.account_id)}").json()
            online_id: str = response["onlineId"]
            return online_id

        @property
        def account_id(self) -> str:
            """Gets the account ID of the client logged in the api.

            :returns: accountID
            :rtype: str

            .. code-block:: Python

                client = psnawp.me()
                print(client.account_id)

            """
            response = self._request_builder.get(url=f"{BASE_PATH['account_uri']}{API_PATH['my_account']}").json()
            account_id: str = response["accountId"]
            return account_id

        def get_profile_legacy(self) -> dict[str, Any]:
            """Gets the profile info from legacy api endpoint. Useful for legacy console (PS3, PS4) presence.

            :returns: A dict containing info similar to what is shown below:
            :rtype: dict[str, Any]

                .. literalinclude:: examples/client/get_profile_legacy.json
                    :language: json

            .. code-block:: Python

                client = psnawp.me()
                print(client.get_profile_legacy())

            """
            params = {
                "fields": "npId,onlineId,accountId,avatarUrls,plus,aboutMe,languagesUsed,trophySummary(@default,level,progress,earnedTrophies),"
                "isOfficiallyVerified,personalDetail(@default,profilePictureUrls),personalDetailSharing,personalDetailSharingRequestMessageFlag,"
                "primaryOnlineStatus,presences(@default,@titleInfo,platform,lastOnlineDate,hasBroadcastData),requestMessageFlag,blocking,friendRelation,"
                "following,consoleAvailability"
            }

            response: dict[str, Any] = self._request_builder.get(
                url=f"{BASE_PATH['legacy_profile_uri']}{API_PATH['legacy_profile'].format(online_id=self.online_id)}",
                params=params,
            ).json()

            return response

        def get_account_devices(self) -> list[dict[str, Any]]:
            """Gets the list of devices the client is logged into.

            :returns: A dict containing info similar to what is shown below:
            :rtype: list[dict[str, Any]]

                .. literalinclude:: examples/client/get_account_devices.json
                    :language: json

            .. code-block:: Python

                client = psnawp.me()
                print(client.get_account_devices())

            """
            params = {
                "includeFields": "device,systemData",
                "platform": "PS5,PS4,PS3,PSVita",
            }
            response = self._request_builder.get(url=f"{BASE_PATH['account_uri']}{API_PATH['my_account']}", params=params).json()

            # Just so mypy doesn't complain
            account_devices: list[dict[str, Any]] = response.get("accountDevices", [])
            return account_devices

        def friends_list(self, limit: int = 1000) -> Iterator[User]:
            """Gets the friends list and return their account ids.

            :param limit: The number of items from input max is 1000.
            :type limit: int

            :returns: All friends in your friends list.
            :rtype: Iterator[User]

            .. code-block:: Python

                client = psnawp.me()
                friends_list = client.friends_list()

                for friend in friends_list:
                    ...

            """
            limit = min(1000, limit)

            params = {"limit": limit}
            response = self._request_builder.get(url=f"{BASE_PATH['profile_uri']}{API_PATH['friends_list']}", params=params).json()
            return (
                User.from_account_id(
                    request_builder=self._request_builder,
                    account_id=account_id,
                )
                for account_id in response["friends"]
            )

        def available_to_play(self) -> Iterator[User]:
            """Gets the list of users on your "Notify when available" subscription list.

            :returns: Iterator of user objects.
            :rtype: Iterator[User]

            .. code-block:: Python

                client = psnawp.me()
                available_to_play = client.available_to_play()

                for user in available_to_play:
                    ...

            """
            response = self._request_builder.get(url=f"{BASE_PATH['profile_uri']}{API_PATH['available_to_play']}").json()
            return (
                User.from_account_id(
                    request_builder=self._request_builder,
                    account_id=account_id_dict["accountId"],
                )
                for account_id_dict in response["settings"]
            )

        def blocked_list(self) -> Iterator[User]:
            """Gets the blocked list and return their account ids.

            :returns: Al blocked users on your block list.
            :rtype: Iterator[User]

            .. code-block:: Python

                client = psnawp.me()
                blocked_list = client.blocked_list()

                for blocked_users in blocked_list:
                    ...

            """
            response = self._request_builder.get(url=f"{BASE_PATH['profile_uri']}{API_PATH['blocked_users']}").json()
            return (
                User.from_account_id(
                    request_builder=self._request_builder,
                    account_id=account_id,
                )
                for account_id in response["blockList"]
            )

        def get_groups(self, limit: int = 200, offset: int = 0) -> Iterator[Group]:
            """Gets all the groups you have participated in.

            :param limit: The number of groups to receive.
            :type limit: int
            :param offset: Lets you exclude first N items groups. Offset = 10 lets you skip the first 10 groups.
            :type offset: int

            :returns: Iterator of Group Objects.
            :rtype: Iterator[Group]

            """
            param = {"includeFields": "members", "limit": limit, "offset": offset}

            response = self._request_builder.get(url=f"{BASE_PATH['gaming_lounge']}{API_PATH['my_groups']}", params=param).json()

            return (
                Group(
                    request_builder=self._request_builder,
                    group_id=group_info["groupId"],
                    users=None,
                )
                for group_info in response["groups"]
            )

        def trophy_summary(self) -> TrophySummary:
            """Retrieve an overall summary of the number of trophies earned for a user broken down by

            - type
            - overall trophy level
            - progress towards the next level
            - current tier

            :returns: Trophy Summary Object containing all information
            :rtype: TrophySummary

            .. code-block:: Python

                client = psnawp.me()
                print(client.trophy_summary())

            """
            return TrophySummary.from_endpoint(request_builder=self._request_builder, account_id="me")

        def trophy_titles(self, limit: Optional[int] = None) -> Iterator[TrophyTitle]:
            """Retrieve all game titles associated with an account, and a summary of trophies earned from them.

            :param limit: Limit of titles returned, None means to return all trophy titles.
            :type limit: Optional[int]

            :returns: Generator object with TitleTrophySummary objects
            :rtype: Iterator[TrophyTitle]

            .. code-block:: Python

                client = psnawp.me()
                for trophy_title in client.trophy_titles(limit=None):
                    print(trophy_title)

            """
            return TrophyTitles(request_builder=self._request_builder, account_id="me").get_trophy_titles(limit=limit)

        def trophy_titles_for_title(self, title_ids: list[str]) -> Iterator[TrophyTitle]:
            """Retrieve a summary of the trophies earned by a user for specific titles.

            .. note::

                ``title_id`` can be obtained from https://andshrew.github.io/PlayStation-Titles/ or from :py:meth:`psnawp_api.models.search.Search.get_title_id`

            :param title_ids: Unique ID of the title
            :type title_ids: list[str]

            :returns: Generator object with TitleTrophySummary objects
            :rtype: Iterator[TrophyTitle]

            .. code-block:: Python

                client = psnawp.me()
                for trophy_title in client.trophy_titles_for_title(title_id='CUSA00265_00'):
                    print(trophy_title)

            """
            return TrophyTitles(request_builder=self._request_builder, account_id="me").get_trophy_summary_for_title(title_ids=title_ids)

        def trophies(
            self,
            np_communication_id: str,
            platform: Literal["PS Vita", "PS3", "PS4", "PS5"],
            trophy_group_id: str = "default",
            limit: Optional[int] = None,
            include_metadata: bool = False,
        ) -> Iterator[Trophy]:
            """Retrieves the earned status individual trophy detail of a single - or all - trophy groups for a title.

            :param np_communication_id: Unique ID of a game title used to request trophy information. This can be obtained from ``GameTitle`` class.
            :type np_communication_id: str
            :param platform: The platform this title belongs to.
            :type platform: Literal
            :param trophy_group_id: ID for the trophy group. Each game expansion is represented by a separate ID. all to return all trophies for the title, default
                for the game itself, and additional groups starting from 001 and so on return expansions trophies.
            :type trophy_group_id: str
            :param limit: Limit of trophies returned, None means to return all trophy titles.
            :type limit: Optional[int]
            :param include_metadata: If True, will fetch metadata for trophy such as name and detail
            :type include_metadata: bool

            .. warning::

                Setting ``include_metadata`` to ``True`` will use twice the amount of rate limit since the API wrapper has to obtain metadata from a separate
                endpoint.

            :returns: Returns the Trophy Generator object with all the information
            :rtype: Iterator[Trophy]

            """

            if not include_metadata:
                return TrophyBuilder(request_builder=self._request_builder, np_communication_id=np_communication_id,).earned_game_trophies(
                    account_id="me",
                    platform=platform,
                    trophy_group_id=trophy_group_id,
                    limit=limit,
                )
            else:
                return TrophyBuilder(request_builder=self._request_builder, np_communication_id=np_communication_id,).earned_game_trophies_with_metadata(
                    account_id="me",
                    platform=platform,
                    trophy_group_id=trophy_group_id,
                    limit=limit,
                )

        def trophy_groups_summary(
            self,
            np_communication_id: str,
            platform: Literal["PS Vita", "PS3", "PS4", "PS5"],
            include_metadata: bool = False,
        ) -> TrophyGroupsSummary:
            """Retrieves the trophy groups for a title and their respective trophy count.

            This is most commonly seen in games which have expansions where additional trophies are added.

            :param np_communication_id: Unique ID of a game title used to request trophy information. This can be obtained from ``GameTitle`` class.
            :type np_communication_id: str
            :param platform: The platform this title belongs to.
            :param platform: The platform this title belongs to.
            :type platform: Literal
            :param include_metadata: If True, will fetch results from another endpoint and include metadata for trophy group such as name and detail
            :type include_metadata: bool

            .. warning::

                Setting ``include_metadata`` to ``True`` will use twice the amount of rate limit since the API wrapper has to obtain metadata from a separate
                endpoint.

            :returns: TrophyGroupSummary object containing title and title groups trophy information.
            :rtype: TrophyGroupsSummary

            """
            if not include_metadata:
                return TrophyGroupsSummaryBuilder(
                    request_builder=self._request_builder,
                    np_communication_id=np_communication_id,
                ).user_trophy_groups_summary(account_id="me", platform=platform)
            else:
                return TrophyGroupsSummaryBuilder(
                    request_builder=self._request_builder,
                    np_communication_id=np_communication_id,
                ).user_trophy_groups_summary_with_metadata(account_id="me", platform=platform)

        def title_stats(self, limit: Optional[int] = 100) -> Iterator[TitleStats]:
            """Retrieve a list of title with their stats and basic meta-data

            :param limit: Limit of titles returned, will default to 100.
            :type limit: Optional[int]

            .. warning::

                Only returns data for PS4 games and above. Don't put a very high limit as the data returned includes a lot of extra meta-data which makes the
                payload large.

            :returns: List of Titles with their play times
            :rtype: Iterator[TitleStats]

            .. code-block:: Python

                client = psnawp.me()
                titles = client.title_stats()

            """
            return TitleStats.from_endpoint(request_builder=self._request_builder, account_id="me", limit=limit)

        def __repr__(self) -> str:
            return f"<User online_id:{self.online_id} account_id:{self.account_id}>"

        def __str__(self) -> str:
            return f"Online ID: {self.online_id} Account ID: {self.account_id}"