diff --git a/homeassistant/components/steam_online/config_flow.py b/homeassistant/components/steam_online/config_flow.py index 8356ad8bbc6..094db9ba207 100644 --- a/homeassistant/components/steam_online/config_flow.py +++ b/homeassistant/components/steam_online/config_flow.py @@ -1,7 +1,7 @@ """Config flow for Steam integration.""" from __future__ import annotations -from collections.abc import Mapping +from collections.abc import Iterator, Mapping from typing import Any import steam @@ -15,6 +15,9 @@ from homeassistant.helpers import config_validation as cv, entity_registry as er from .const import CONF_ACCOUNT, CONF_ACCOUNTS, DOMAIN, LOGGER, PLACEHOLDERS +# To avoid too long request URIs, the amount of ids to request is limited +MAX_IDS_TO_REQUEST = 275 + def validate_input(user_input: dict[str, str]) -> dict[str, str | int]: """Handle common flow input validation.""" @@ -108,6 +111,11 @@ class SteamFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): ) +def _batch_ids(ids: list[str]) -> Iterator[list[str]]: + for i in range(0, len(ids), MAX_IDS_TO_REQUEST): + yield ids[i : i + MAX_IDS_TO_REQUEST] + + class SteamOptionsFlowHandler(config_entries.OptionsFlow): """Handle Steam client options.""" @@ -170,5 +178,11 @@ class SteamOptionsFlowHandler(config_entries.OptionsFlow): _users_str = [user["steamid"] for user in friends["friendslist"]["friends"]] except steam.api.HTTPError: return [] - names = interface.GetPlayerSummaries(steamids=_users_str) - return names["response"]["players"]["player"] + names = [] + for id_batch in _batch_ids(_users_str): + names.extend( + interface.GetPlayerSummaries(steamids=id_batch)["response"]["players"][ + "player" + ] + ) + return names diff --git a/tests/components/steam_online/__init__.py b/tests/components/steam_online/__init__.py index d41554e4d04..786c5d67782 100644 --- a/tests/components/steam_online/__init__.py +++ b/tests/components/steam_online/__init__.py @@ -1,5 +1,8 @@ """Tests for Steam integration.""" +import random +import string from unittest.mock import patch +import urllib.parse import steam @@ -11,8 +14,8 @@ from homeassistant.core import HomeAssistant from tests.common import MockConfigEntry API_KEY = "abc123" -ACCOUNT_1 = "1234567890" -ACCOUNT_2 = "1234567891" +ACCOUNT_1 = "12345678901234567" +ACCOUNT_2 = "12345678912345678" ACCOUNT_NAME_1 = "testaccount1" ACCOUNT_NAME_2 = "testaccount2" @@ -30,6 +33,8 @@ CONF_OPTIONS_2 = { } } +MAX_LENGTH_STEAM_IDS = 30 + def create_entry(hass: HomeAssistant) -> MockConfigEntry: """Add config entry in Home Assistant.""" @@ -62,16 +67,32 @@ class MockedInterface(dict): def GetFriendList(self, steamid: str) -> dict: """Get friend list.""" - return {"friendslist": {"friends": [{"steamid": ACCOUNT_2}]}} + fake_friends = [{"steamid": ACCOUNT_2}] + for _i in range(0, 4): + fake_friends.append( + {"steamid": "".join(random.choices(string.digits, k=len(ACCOUNT_1)))} + ) + return {"friendslist": {"friends": fake_friends}} - def GetPlayerSummaries(self, steamids: str) -> dict: + def GetPlayerSummaries(self, steamids: str | list[str]) -> dict: """Get player summaries.""" + assert len(urllib.parse.quote(str(steamids))) <= MAX_LENGTH_STEAM_IDS return { "response": { "players": { "player": [ - {"steamid": ACCOUNT_1, "personaname": ACCOUNT_NAME_1}, - {"steamid": ACCOUNT_2, "personaname": ACCOUNT_NAME_2}, + { + "steamid": ACCOUNT_1, + "personaname": ACCOUNT_NAME_1, + "personastate": 1, + "avatarmedium": "", + }, + { + "steamid": ACCOUNT_2, + "personaname": ACCOUNT_NAME_2, + "personastate": 2, + "avatarmedium": "", + }, ] } } diff --git a/tests/components/steam_online/test_config_flow.py b/tests/components/steam_online/test_config_flow.py index a9d81a16fba..a62adb18776 100644 --- a/tests/components/steam_online/test_config_flow.py +++ b/tests/components/steam_online/test_config_flow.py @@ -138,7 +138,10 @@ async def test_flow_reauth(hass: HomeAssistant) -> None: async def test_options_flow(hass: HomeAssistant) -> None: """Test updating options.""" entry = create_entry(hass) - with patch_interface(): + with patch_interface(), patch( + "homeassistant.components.steam_online.config_flow.MAX_IDS_TO_REQUEST", + return_value=2, + ): await hass.config_entries.async_setup(entry.entry_id) result = await hass.config_entries.options.async_init(entry.entry_id) await hass.async_block_till_done() @@ -159,7 +162,10 @@ async def test_options_flow(hass: HomeAssistant) -> None: async def test_options_flow_deselect(hass: HomeAssistant) -> None: """Test deselecting user.""" entry = create_entry(hass) - with patch_interface(): + with patch_interface(), patch( + "homeassistant.components.steam_online.config_flow.MAX_IDS_TO_REQUEST", + return_value=2, + ): await hass.config_entries.async_setup(entry.entry_id) result = await hass.config_entries.options.async_init(entry.entry_id) await hass.async_block_till_done()