Basic Usage
Note
These steps assume you have already obtained spartan and clearance tokens as described here.
Initializing the HaloInfiniteClient
Now that we have the spartan and clearance tokens, we are ready to create a HaloInfiniteClient object. The initializer takes a aiohttp.ClientSession
instance and the tokens as arguments. An example is shown below.
import asyncio
from aiohttp import ClientSession
from spnkr import HaloInfiniteClient
async def main() -> None:
async with ClientSession() as session:
client = HaloInfiniteClient(
session=session,
spartan_token="SPARTAN_TOKEN",
clearance_token="CLEARANCE_TOKEN",
# Optional, default rate is 5.
requests_per_second=5,
)
if __name__ == "__main__":
asyncio.run(main())
Requesting Data
Now that we have the HaloInfiniteClient initialized, we can begin retrieving data. A simple continuation of the above script is shown below.
import asyncio
from aiohttp import ClientSession
from spnkr import HaloInfiniteClient
# Any of the following are acceptable for the below request.
PLAYER = "xuid(1234567890123456)" # AuthenticatedPlayer.player_id
PLAYER = "1234567890123456"
PLAYER = 1234567890123456
PLAYER = "MyGamertag" # AuthenticatedPlayer.gamertag
async def main() -> None:
async with ClientSession() as session:
client = HaloInfiniteClient(...)
# Request the 25 most recent matches for the player.
resp = await client.stats.get_match_history(PLAYER)
# Parse the response JSON into a Pydantic model
history = await resp.parse()
# Get the most recent match played and print the start time.
last_match_info = history.results[0].match_info
print(f"Last match played on {last_match_info.start_time:%Y-%m-%d}")
if __name__ == "__main__":
asyncio.run(main())
Calls to HaloInfiniteClient services return aiohttp.ClientResponse
wrappers to provide access to the raw response, if needed, while also providing a convenient parse()
method to more cleanly access data from the payload as Pydantic models. You can browse the information available in those response models here.
Of course, there are additional methods for retrieving stats, CSR/MMR, and metadata information.
Caching
Caching is supported via the aiohttp-client-cache
package, which provides a drop-in replacement for aiohttp.ClientSession
as aiohttp_client_cache.CachedSession
and reduces the number of repeat requests. Below is an example backend configuration, which relies on the "Cache-Control" header available on certain responses. A SQLite backend is used here, but any backend should work.
from aiohttp_client_cache import CachedSession, SQLiteBackend
from spnkr import HaloInfiniteClient
async def filter_by_cache_control(response):
"""Only cache responses with a cache-control header."""
return "Cache-Control" in response.headers
async def main() -> None:
cache = SQLiteBackend(
"cache.sqlite",
cache_control=True,
filter_fn=filter_by_cache_control,
)
async with CachedSession(cache=cache) as session:
client = HaloInfiniteClient(...)
if __name__ == "__main__":
asyncio.run(main())
Here are the cached response max ages as obtained from sample responses on 1/2/2024:
Service | Method | Max-Age |
---|---|---|
discovery_ugc | get_map | 5 hours |
discovery_ugc | get_ugc_game_variant | 5 hours |
discovery_ugc | get_playlist | 5 hours |
discovery_ugc | get_map_mode_pair | 5 hours |
gamecms_hacs | get_medal_metadata | 1 day |
gamecms_hacs | get_csr_season_calendar | 1 day |
gamecms_hacs | get_season_calendar | 1 day |
gamecms_hacs | get_career_reward_track | 1 day |
gamecms_hacs | get_image | 1 day |
stats | get_match_stats | 1 day |