Clean up Steam integration (#71091)

* Clean up Steam

* uno mas

* uno mas

* uno mas
This commit is contained in:
Robert Hillis 2022-04-30 11:40:57 -04:00 committed by GitHub
parent 00b5d30e24
commit f14bc1cece
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 58 additions and 91 deletions

View File

@ -13,7 +13,14 @@ from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import config_validation as cv, entity_registry as er
from homeassistant.helpers.typing import ConfigType
from .const import CONF_ACCOUNT, CONF_ACCOUNTS, DEFAULT_NAME, DOMAIN, LOGGER
from .const import (
CONF_ACCOUNT,
CONF_ACCOUNTS,
DEFAULT_NAME,
DOMAIN,
LOGGER,
PLACEHOLDERS,
)
def validate_input(user_input: dict[str, str | int]) -> list[dict[str, str | int]]:
@ -52,14 +59,14 @@ class SteamFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
if res[0] is not None:
name = str(res[0]["personaname"])
else:
errors = {"base": "invalid_account"}
errors["base"] = "invalid_account"
except (steam.api.HTTPError, steam.api.HTTPTimeoutError) as ex:
errors = {"base": "cannot_connect"}
errors["base"] = "cannot_connect"
if "403" in str(ex):
errors = {"base": "invalid_auth"}
errors["base"] = "invalid_auth"
except Exception as ex: # pylint:disable=broad-except
LOGGER.exception("Unknown exception: %s", ex)
errors = {"base": "unknown"}
errors["base"] = "unknown"
if not errors:
entry = await self.async_set_unique_id(user_input[CONF_ACCOUNT])
if entry and self.source == config_entries.SOURCE_REAUTH:
@ -70,20 +77,12 @@ class SteamFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
if self.source == config_entries.SOURCE_IMPORT:
accounts_data = {
CONF_ACCOUNTS: {
acc["steamid"]: {
"name": acc["personaname"],
"enabled": True,
}
for acc in res
acc["steamid"]: acc["personaname"] for acc in res
}
}
user_input.pop(CONF_ACCOUNTS)
else:
accounts_data = {
CONF_ACCOUNTS: {
user_input[CONF_ACCOUNT]: {"name": name, "enabled": True}
}
}
accounts_data = {CONF_ACCOUNTS: {user_input[CONF_ACCOUNT]: name}}
return self.async_create_entry(
title=name or DEFAULT_NAME,
data=user_input,
@ -103,6 +102,7 @@ class SteamFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
}
),
errors=errors,
description_placeholders=PLACEHOLDERS,
)
async def async_step_import(self, import_config: ConfigType) -> FlowResult:
@ -111,7 +111,7 @@ class SteamFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
if entry.data[CONF_API_KEY] == import_config[CONF_API_KEY]:
return self.async_abort(reason="already_configured")
LOGGER.warning(
"Steam yaml config in now deprecated and has been imported. "
"Steam yaml config is now deprecated and has been imported. "
"Please remove it from your config"
)
import_config[CONF_ACCOUNT] = import_config[CONF_ACCOUNTS][0]
@ -131,7 +131,9 @@ class SteamFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
return await self.async_step_user()
self._set_confirm_only()
return self.async_show_form(step_id="reauth_confirm")
return self.async_show_form(
step_id="reauth_confirm", description_placeholders=PLACEHOLDERS
)
class SteamOptionsFlowHandler(config_entries.OptionsFlow):
@ -148,56 +150,38 @@ class SteamOptionsFlowHandler(config_entries.OptionsFlow):
"""Manage Steam options."""
if user_input is not None:
await self.hass.config_entries.async_unload(self.entry.entry_id)
for k in self.options[CONF_ACCOUNTS]:
if (
self.options[CONF_ACCOUNTS][k]["enabled"]
and k not in user_input[CONF_ACCOUNTS]
and (
entity_id := er.async_get(self.hass).async_get_entity_id(
Platform.SENSOR, DOMAIN, f"sensor.steam_{k}"
)
for _id in self.options[CONF_ACCOUNTS]:
if _id not in user_input[CONF_ACCOUNTS] and (
entity_id := er.async_get(self.hass).async_get_entity_id(
Platform.SENSOR, DOMAIN, f"sensor.steam_{_id}"
)
):
er.async_get(self.hass).async_remove(entity_id)
channel_data = {
CONF_ACCOUNTS: {
k: {
"name": v["name"],
"enabled": k in user_input[CONF_ACCOUNTS],
}
for k, v in self.options[CONF_ACCOUNTS].items()
if k in user_input[CONF_ACCOUNTS]
_id: name
for _id, name in self.options[CONF_ACCOUNTS].items()
if _id in user_input[CONF_ACCOUNTS]
}
}
await self.hass.config_entries.async_reload(self.entry.entry_id)
return self.async_create_entry(title="", data=channel_data)
try:
users = {
name["steamid"]: {"name": name["personaname"], "enabled": False}
name["steamid"]: name["personaname"]
for name in await self.hass.async_add_executor_job(self.get_accounts)
}
except steam.api.HTTPTimeoutError:
users = self.options[CONF_ACCOUNTS]
_users = users | self.options[CONF_ACCOUNTS]
self.options[CONF_ACCOUNTS] = {
k: v
for k, v in _users.items()
if k in users or self.options[CONF_ACCOUNTS][k]["enabled"]
}
options = {
vol.Required(
CONF_ACCOUNTS,
default={
k
for k in self.options[CONF_ACCOUNTS]
if self.options[CONF_ACCOUNTS][k]["enabled"]
},
): cv.multi_select(
{k: v["name"] for k, v in self.options[CONF_ACCOUNTS].items()}
),
default=set(self.options[CONF_ACCOUNTS]),
): cv.multi_select(users | self.options[CONF_ACCOUNTS]),
}
self.options[CONF_ACCOUNTS] = users | self.options[CONF_ACCOUNTS]
return self.async_show_form(step_id="init", data_schema=vol.Schema(options))
@ -205,7 +189,6 @@ class SteamOptionsFlowHandler(config_entries.OptionsFlow):
"""Get accounts."""
interface = steam.api.interface("ISteamUser")
friends = interface.GetFriendList(steamid=self.entry.data[CONF_ACCOUNT])
friends = friends["friendslist"]["friends"]
_users_str = [user["steamid"] for user in friends]
_users_str = [user["steamid"] for user in friends["friendslist"]["friends"]]
names = interface.GetPlayerSummaries(steamids=_users_str)
return names["response"]["players"]["player"]

View File

@ -11,6 +11,11 @@ DOMAIN: Final = "steam_online"
LOGGER = logging.getLogger(__package__)
PLACEHOLDERS = {
"api_key_url": "https://steamcommunity.com/dev/apikey",
"account_id_url": "https://steamid.io",
}
STATE_OFFLINE = "offline"
STATE_ONLINE = "online"
STATE_BUSY = "busy"
@ -30,6 +35,4 @@ STEAM_STATUSES = {
STEAM_API_URL = "https://steamcdn-a.akamaihd.net/steam/apps/"
STEAM_HEADER_IMAGE_FILE = "header.jpg"
STEAM_MAIN_IMAGE_FILE = "capsule_616x353.jpg"
STEAM_ICON_URL = (
"https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/%d/%s.jpg"
)
STEAM_ICON_URL = "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/"

View File

@ -28,7 +28,7 @@ class SteamDataUpdateCoordinator(DataUpdateCoordinator):
name=DOMAIN,
update_interval=timedelta(seconds=30),
)
self.game_icons: dict = {}
self.game_icons: dict[int, str] = {}
self.player_interface: INTMethod = None
self.user_interface: INTMethod = None
steam.api.key.set(self.config_entry.data[CONF_API_KEY])
@ -36,7 +36,7 @@ class SteamDataUpdateCoordinator(DataUpdateCoordinator):
def _update(self) -> dict[str, dict[str, str | int]]:
"""Fetch data from API endpoint."""
accounts = self.config_entry.options[CONF_ACCOUNTS]
_ids = [k for k in accounts if accounts[k]["enabled"]]
_ids = list(accounts)
if not self.user_interface or not self.player_interface:
self.user_interface = steam.api.interface("ISteamUser")
self.player_interface = steam.api.interface("IPlayerService")
@ -46,7 +46,7 @@ class SteamDataUpdateCoordinator(DataUpdateCoordinator):
steamid=_id, include_appinfo=1
)["response"]
self.game_icons = self.game_icons | {
game["appid"]: game["img_icon_url"] for game in res.get("games", {})
game["appid"]: game["img_icon_url"] for game in res.get("games", [])
}
response = self.user_interface.GetPlayerSummaries(steamids=_ids)
players = {
@ -56,8 +56,7 @@ class SteamDataUpdateCoordinator(DataUpdateCoordinator):
}
for k in players:
data = self.player_interface.GetSteamLevel(steamid=players[k]["steamid"])
data = data["response"]
players[k]["level"] = data["player_level"]
players[k]["level"] = data["response"]["player_level"]
return players
async def _async_update_data(self) -> dict[str, dict[str, str | int]]:

View File

@ -65,7 +65,6 @@ async def async_setup_entry(
async_add_entities(
SteamSensor(hass.data[DOMAIN][entry.entry_id], account)
for account in entry.options[CONF_ACCOUNTS]
if entry.options[CONF_ACCOUNTS][account]["enabled"]
)
@ -106,10 +105,7 @@ class SteamSensor(SteamEntity, SensorEntity):
attrs["game_image_header"] = f"{game_url}{STEAM_HEADER_IMAGE_FILE}"
attrs["game_image_main"] = f"{game_url}{STEAM_MAIN_IMAGE_FILE}"
if info := self._get_game_icon(player):
attrs["game_icon"] = STEAM_ICON_URL % (
game_id,
info,
)
attrs["game_icon"] = f"{STEAM_ICON_URL}{game_id}/{info}.jpg"
self._attr_name = player["personaname"]
self._attr_entity_picture = player["avatarmedium"]
if last_online := player.get("lastlogoff"):

View File

@ -2,7 +2,7 @@
"config": {
"step": {
"user": {
"description": "Use https://steamid.io to find your Steam account ID",
"description": "Use {account_id_url} to find your Steam account ID",
"data": {
"api_key": "[%key:common::config_flow::data::api_key%]",
"account": "Steam account ID"
@ -10,7 +10,7 @@
},
"reauth_confirm": {
"title": "[%key:common::config_flow::title::reauth%]",
"description": "The Steam integration needs to be manually re-authenticated\n\nYou can find your key here: https://steamcommunity.com/dev/apikey"
"description": "The Steam integration needs to be manually re-authenticated\n\nYou can find your key here: {api_key_url}"
}
},
"error": {

View File

@ -12,7 +12,7 @@
},
"step": {
"reauth_confirm": {
"description": "The Steam integration needs to be manually re-authenticated\n\nYou can find your key here: https://steamcommunity.com/dev/apikey",
"description": "The Steam integration needs to be manually re-authenticated\n\nYou can find your key here: {api_key_url}",
"title": "Reauthenticate Integration"
},
"user": {
@ -20,7 +20,7 @@
"account": "Steam account ID",
"api_key": "API Key"
},
"description": "Use https://steamid.io to find your Steam account ID"
"description": "Use {account_id_url} to find your Steam account ID"
}
}
},

View File

@ -3,7 +3,7 @@ from unittest.mock import patch
from homeassistant.components.steam_online import DOMAIN
from homeassistant.components.steam_online.const import CONF_ACCOUNT, CONF_ACCOUNTS
from homeassistant.const import CONF_API_KEY, CONF_NAME
from homeassistant.const import CONF_API_KEY
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
@ -19,38 +19,19 @@ CONF_DATA = {
CONF_ACCOUNT: ACCOUNT_1,
}
CONF_OPTIONS = {
CONF_ACCOUNTS: {
ACCOUNT_1: {
CONF_NAME: ACCOUNT_NAME_1,
"enabled": True,
}
}
}
CONF_OPTIONS = {CONF_ACCOUNTS: {ACCOUNT_1: ACCOUNT_NAME_1}}
CONF_OPTIONS_2 = {
CONF_ACCOUNTS: {
ACCOUNT_1: {
CONF_NAME: ACCOUNT_NAME_1,
"enabled": True,
},
ACCOUNT_2: {
CONF_NAME: ACCOUNT_NAME_2,
"enabled": True,
},
ACCOUNT_1: ACCOUNT_NAME_1,
ACCOUNT_2: ACCOUNT_NAME_2,
}
}
CONF_IMPORT_OPTIONS = {
CONF_ACCOUNTS: {
ACCOUNT_1: {
CONF_NAME: ACCOUNT_NAME_1,
"enabled": True,
},
ACCOUNT_2: {
CONF_NAME: ACCOUNT_NAME_2,
"enabled": True,
},
ACCOUNT_1: ACCOUNT_NAME_1,
ACCOUNT_2: ACCOUNT_NAME_2,
}
}

View File

@ -1,4 +1,6 @@
"""Test Steam config flow."""
from unittest.mock import patch
import steam
from homeassistant import data_entry_flow
@ -25,7 +27,10 @@ from . import (
async def test_flow_user(hass: HomeAssistant) -> None:
"""Test user initialized flow."""
with patch_interface():
with patch_interface(), patch(
"homeassistant.components.steam_online.async_setup_entry",
return_value=True,
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_USER},