diff --git a/homeassistant/components/twitch/__init__.py b/homeassistant/components/twitch/__init__.py index 5882b1da74d..60c9dcabb36 100644 --- a/homeassistant/components/twitch/__init__.py +++ b/homeassistant/components/twitch/__init__.py @@ -17,7 +17,7 @@ from homeassistant.helpers.config_entry_oauth2_flow import ( async_get_config_entry_implementation, ) -from .const import DOMAIN, OAUTH_SCOPES, PLATFORMS +from .const import CLIENT, DOMAIN, OAUTH_SCOPES, PLATFORMS, SESSION async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: @@ -46,7 +46,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: client.auto_refresh_auth = False await client.set_user_authentication(access_token, scope=OAUTH_SCOPES) - hass.data.setdefault(DOMAIN, {})[entry.entry_id] = client + hass.data.setdefault(DOMAIN, {})[entry.entry_id] = { + CLIENT: client, + SESSION: session, + } await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) diff --git a/homeassistant/components/twitch/const.py b/homeassistant/components/twitch/const.py index fc7c2f73487..b46bf8113b4 100644 --- a/homeassistant/components/twitch/const.py +++ b/homeassistant/components/twitch/const.py @@ -17,5 +17,7 @@ CONF_REFRESH_TOKEN = "refresh_token" DOMAIN = "twitch" CONF_CHANNELS = "channels" +CLIENT = "client" +SESSION = "session" OAUTH_SCOPES = [AuthScope.USER_READ_SUBSCRIPTIONS, AuthScope.USER_READ_FOLLOWS] diff --git a/homeassistant/components/twitch/sensor.py b/homeassistant/components/twitch/sensor.py index 9a936981f24..1107513080a 100644 --- a/homeassistant/components/twitch/sensor.py +++ b/homeassistant/components/twitch/sensor.py @@ -20,12 +20,13 @@ from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_TOKEN from homeassistant.core import HomeAssistant +from homeassistant.helpers.config_entry_oauth2_flow import OAuth2Session import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType -from .const import CONF_CHANNELS, DOMAIN, LOGGER, OAUTH_SCOPES +from .const import CLIENT, CONF_CHANNELS, DOMAIN, LOGGER, OAUTH_SCOPES, SESSION PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { @@ -50,6 +51,8 @@ ATTR_VIEWS = "views" STATE_OFFLINE = "offline" STATE_STREAMING = "streaming" +PARALLEL_UPDATES = 1 + def chunk_list(lst: list, chunk_size: int) -> list[list]: """Split a list into chunks of chunk_size.""" @@ -96,7 +99,8 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Initialize entries.""" - client = hass.data[DOMAIN][entry.entry_id] + client = hass.data[DOMAIN][entry.entry_id][CLIENT] + session = hass.data[DOMAIN][entry.entry_id][SESSION] channels = entry.options[CONF_CHANNELS] @@ -106,7 +110,7 @@ async def async_setup_entry( for chunk in chunk_list(channels, 100): entities.extend( [ - TwitchSensor(channel, client) + TwitchSensor(channel, session, client) async for channel in client.get_users(logins=chunk) ] ) @@ -119,8 +123,11 @@ class TwitchSensor(SensorEntity): _attr_translation_key = "channel" - def __init__(self, channel: TwitchUser, client: Twitch) -> None: + def __init__( + self, channel: TwitchUser, session: OAuth2Session, client: Twitch + ) -> None: """Initialize the sensor.""" + self._session = session self._client = client self._channel = channel self._enable_user_auth = client.has_required_auth(AuthType.USER, OAUTH_SCOPES) @@ -129,9 +136,17 @@ class TwitchSensor(SensorEntity): async def async_update(self) -> None: """Update device state.""" - followers = (await self._client.get_channel_followers(self._channel.id)).total + await self._session.async_ensure_token_valid() + await self._client.set_user_authentication( + self._session.token["access_token"], + OAUTH_SCOPES, + self._session.token["refresh_token"], + False, + ) + followers = await self._client.get_channel_followers(self._channel.id) + self._attr_extra_state_attributes = { - ATTR_FOLLOWING: followers, + ATTR_FOLLOWING: followers.total, ATTR_VIEWS: self._channel.view_count, } if self._enable_user_auth: @@ -165,7 +180,7 @@ class TwitchSensor(SensorEntity): self._attr_extra_state_attributes[ATTR_SUBSCRIPTION] = True self._attr_extra_state_attributes[ATTR_SUBSCRIPTION_GIFTED] = sub.is_gift except TwitchResourceNotFound: - LOGGER.debug("User is not subscribed") + LOGGER.debug("User is not subscribed to %s", self._channel.display_name) except TwitchAPIException as exc: LOGGER.error("Error response on check_user_subscription: %s", exc) diff --git a/tests/components/twitch/__init__.py b/tests/components/twitch/__init__.py index ba49390ebdf..3fa7d96337e 100644 --- a/tests/components/twitch/__init__.py +++ b/tests/components/twitch/__init__.py @@ -153,6 +153,7 @@ class TwitchMock: self, token: str, scope: list[AuthScope], + refresh_token: str | None = None, validate: bool = True, ) -> None: """Set user authentication."""