Skip to content

Userstats provider

Userstats - Get game statistics

pythonxbox.api.provider.userstats.UserStatsProvider(client)

Bases: RateLimitedProvider

Source code in src/pythonxbox/api/provider/ratelimitedprovider.py
def __init__(self, client: "XboxLiveClient") -> None:
    """
    Initialize Baseclass

    Args:
        client (:class:`XboxLiveClient`): Instance of XboxLiveClient
    """
    super().__init__(client)

    # Check that RATE_LIMITS set defined in the child class
    if hasattr(self, "RATE_LIMITS"):
        # Note: we cannot check (type(self.RATE_LIMITS) == dict) as the type hints have already defined it as such
        if "burst" and "sustain" in self.RATE_LIMITS:
            # We have the required keys, attempt to parse.
            # (type-checking for the values is performed in __parse_rate_limit_key)
            self.__handle_rate_limit_setup()
        else:
            raise XboxException(
                "RATE_LIMITS object missing required keys 'burst', 'sustain'"
            )
    else:
        raise XboxException(
            "RateLimitedProvider as parent class but RATE_LIMITS not set!"
        )

USERSTATS_URL = 'https://userstats.xboxlive.com' class-attribute instance-attribute

HEADERS_USERSTATS = {'x-xbl-contract-version': '2'} class-attribute instance-attribute

HEADERS_USERSTATS_WITH_METADATA = {'x-xbl-contract-version': '3'} class-attribute instance-attribute

SEPERATOR = ',' class-attribute instance-attribute

RATE_LIMITS = {'burst': 100, 'sustain': 300} class-attribute instance-attribute

get_stats(xuid, service_config_id, stats_fields=None, **kwargs) async

Get userstats

Parameters:

Name Type Description Default
xuid str

Xbox User Id

required
service_config_id str

Service Config Id of Game (scid)

required
stats_fields list[GeneralStatsField] | None

List of stats fields to acquire

None

Returns:

Type Description
UserStatsResponse

class:UserStatsResponse: User Stats Response

Source code in src/pythonxbox/api/provider/userstats/__init__.py
async def get_stats(
    self,
    xuid: str,
    service_config_id: str,
    stats_fields: list[GeneralStatsField] | None = None,
    **kwargs,
) -> UserStatsResponse:
    """
    Get userstats

    Args:
        xuid: Xbox User Id
        service_config_id: Service Config Id of Game (scid)
        stats_fields: List of stats fields to acquire

    Returns:
        :class:`UserStatsResponse`: User Stats Response
    """
    if not stats_fields:
        stats_fields = [GeneralStatsField.MINUTES_PLAYED]
    stats = self.SEPERATOR.join(stats_fields)

    url = f"{self.USERSTATS_URL}/users/xuid({xuid})/scids/{service_config_id}/stats/{stats}"
    resp = await self.client.session.get(
        url,
        headers=self.HEADERS_USERSTATS,
        rate_limits=self.rate_limit_read,
        **kwargs,
    )
    resp.raise_for_status()
    return UserStatsResponse.model_validate_json(resp.text)

get_stats_with_metadata(xuid, service_config_id, stats_fields=None, **kwargs) async

Get userstats including metadata for each stat (if available)

Parameters:

Name Type Description Default
xuid str

Xbox User Id

required
service_config_id str

Service Config Id of Game (scid)

required
stats_fields list[GeneralStatsField] | None

List of stats fields to acquire

None

Returns:

Type Description
UserStatsResponse

class:UserStatsResponse: User Stats Response

Source code in src/pythonxbox/api/provider/userstats/__init__.py
async def get_stats_with_metadata(
    self,
    xuid: str,
    service_config_id: str,
    stats_fields: list[GeneralStatsField] | None = None,
    **kwargs,
) -> UserStatsResponse:
    """
    Get userstats including metadata for each stat (if available)

    Args:
        xuid: Xbox User Id
        service_config_id: Service Config Id of Game (scid)
        stats_fields: List of stats fields to acquire

    Returns:
        :class:`UserStatsResponse`: User Stats Response
    """
    if not stats_fields:
        stats_fields = [GeneralStatsField.MINUTES_PLAYED]
    stats = self.SEPERATOR.join(stats_fields)

    url = f"{self.USERSTATS_URL}/users/xuid({xuid})/scids/{service_config_id}/stats/{stats}"
    params = {"include": "valuemetadata"}
    resp = await self.client.session.get(
        url,
        params=params,
        headers=self.HEADERS_USERSTATS_WITH_METADATA,
        rate_limits=self.rate_limit_read,
        **kwargs,
    )
    resp.raise_for_status()
    return UserStatsResponse.model_validate_json(resp.text)

get_stats_batch(xuids, title_id, stats_fields=None, **kwargs) async

Get userstats in batch mode

Parameters:

Name Type Description Default
xuids list[str]

List of XUIDs to get stats for

required
title_id str

Game Title Id

required
stats_fields list[GeneralStatsField] | None

List of stats fields to acquire

None

Returns:

Type Description
UserStatsResponse

class:UserStatsResponse: User Stats Response

Source code in src/pythonxbox/api/provider/userstats/__init__.py
async def get_stats_batch(
    self,
    xuids: list[str],
    title_id: str,
    stats_fields: list[GeneralStatsField] | None = None,
    **kwargs,
) -> UserStatsResponse:
    """
    Get userstats in batch mode

    Args:
        xuids: List of XUIDs to get stats for
        title_id: Game Title Id
        stats_fields: List of stats fields to acquire

    Returns:
        :class:`UserStatsResponse`: User Stats Response
    """
    if not stats_fields:
        stats_fields = [GeneralStatsField.MINUTES_PLAYED]

    url = self.USERSTATS_URL + "/batch"
    post_data = {
        "arrangebyfield": "xuid",
        "groups": [{"name": "Hero", "titleId": title_id}],
        "stats": [{"name": stat, "titleId": title_id} for stat in stats_fields],
        "xuids": xuids,
    }
    resp = await self.client.session.post(
        url,
        json=post_data,
        headers=self.HEADERS_USERSTATS,
        rate_limits=self.rate_limit_read,
        **kwargs,
    )
    resp.raise_for_status()
    return UserStatsResponse.model_validate_json(resp.text)

get_stats_batch_by_scid(xuids, service_config_id, stats_fields=None, **kwargs) async

Get userstats in batch mode, via scid

Parameters:

Name Type Description Default
xuids list[str]

List of XUIDs to get stats for

required
service_config_id str

Service Config Id of Game (scid)

required
stats_fields list[GeneralStatsField] | None

List of stats fields to acquire

None

Returns:

Type Description
UserStatsResponse

class:UserStatsResponse: User Stats Response

Source code in src/pythonxbox/api/provider/userstats/__init__.py
async def get_stats_batch_by_scid(
    self,
    xuids: list[str],
    service_config_id: str,
    stats_fields: list[GeneralStatsField] | None = None,
    **kwargs,
) -> UserStatsResponse:
    """
    Get userstats in batch mode, via scid

    Args:
        xuids: List of XUIDs to get stats for
        service_config_id: Service Config Id of Game (scid)
        stats_fields: List of stats fields to acquire

    Returns:
        :class:`UserStatsResponse`: User Stats Response
    """
    if not stats_fields:
        stats_fields = [GeneralStatsField.MINUTES_PLAYED]

    url = self.USERSTATS_URL + "/batch"

    post_data = {
        "arrangebyfield": "xuid",
        "groups": [{"name": "Hero", "scid": service_config_id}],
        "stats": [
            {"name": stat, "scid": service_config_id} for stat in stats_fields
        ],
        "xuids": xuids,
    }
    resp = await self.client.session.post(
        url,
        json=post_data,
        headers=self.HEADERS_USERSTATS,
        rate_limits=self.rate_limit_read,
        **kwargs,
    )
    resp.raise_for_status()
    return UserStatsResponse.model_validate_json(resp.text)