Reduce the number of API calls in Twitch integration (#128996)

This commit is contained in:
Jason Parker 2024-10-24 13:51:19 -04:00 committed by GitHub
parent f91a1363cb
commit bf63b0993d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 27 additions and 15 deletions

View file

@ -4,7 +4,7 @@ from dataclasses import dataclass
from datetime import datetime, timedelta from datetime import datetime, timedelta
from twitchAPI.helper import first from twitchAPI.helper import first
from twitchAPI.object.api import FollowedChannelsResult, TwitchUser, UserSubscription from twitchAPI.object.api import FollowedChannel, Stream, TwitchUser, UserSubscription
from twitchAPI.twitch import Twitch from twitchAPI.twitch import Twitch
from twitchAPI.type import TwitchAPIException, TwitchResourceNotFound from twitchAPI.type import TwitchAPIException, TwitchResourceNotFound
@ -81,12 +81,24 @@ class TwitchCoordinator(DataUpdateCoordinator[dict[str, TwitchUpdate]]):
self.session.token["refresh_token"], self.session.token["refresh_token"],
False, False,
) )
data = {} data: dict[str, TwitchUpdate] = {}
streams: dict[str, Stream] = {
s.user_id: s
async for s in self.twitch.get_followed_streams(
user_id=self.current_user.id, first=100
)
}
follows: dict[str, FollowedChannel] = {
f.broadcaster_id: f
async for f in await self.twitch.get_followed_channels(
user_id=self.current_user.id, first=100
)
}
for channel in self.users: for channel in self.users:
followers = await self.twitch.get_channel_followers(channel.id) followers = await self.twitch.get_channel_followers(channel.id)
stream = await first(self.twitch.get_streams(user_id=[channel.id], first=1)) stream = streams.get(channel.id)
follow = follows.get(channel.id)
sub: UserSubscription | None = None sub: UserSubscription | None = None
follows: FollowedChannelsResult | None = None
try: try:
sub = await self.twitch.check_user_subscription( sub = await self.twitch.check_user_subscription(
user_id=self.current_user.id, broadcaster_id=channel.id user_id=self.current_user.id, broadcaster_id=channel.id
@ -95,10 +107,7 @@ class TwitchCoordinator(DataUpdateCoordinator[dict[str, TwitchUpdate]]):
LOGGER.debug("User is not subscribed to %s", channel.display_name) LOGGER.debug("User is not subscribed to %s", channel.display_name)
except TwitchAPIException as exc: except TwitchAPIException as exc:
LOGGER.error("Error response on check_user_subscription: %s", exc) LOGGER.error("Error response on check_user_subscription: %s", exc)
else:
follows = await self.twitch.get_followed_channels(
self.current_user.id, broadcaster_id=channel.id
)
data[channel.id] = TwitchUpdate( data[channel.id] = TwitchUpdate(
channel.display_name, channel.display_name,
followers.total, followers.total,
@ -108,11 +117,11 @@ class TwitchCoordinator(DataUpdateCoordinator[dict[str, TwitchUpdate]]):
stream.started_at if stream else None, stream.started_at if stream else None,
stream.thumbnail_url if stream else None, stream.thumbnail_url if stream else None,
channel.profile_image_url, channel.profile_image_url,
sub is not None if sub else None, bool(sub),
sub.is_gift if sub else None, sub.is_gift if sub else None,
{"1000": 1, "2000": 2, "3000": 3}.get(sub.tier) if sub else None, {"1000": 1, "2000": 2, "3000": 3}.get(sub.tier) if sub else None,
follows is not None and follows.total > 0, bool(follow),
follows.data[0].followed_at if follows and follows.total else None, follow.followed_at if follow else None,
stream.viewer_count if stream else None, stream.viewer_count if stream else None,
) )
return data return data

View file

@ -111,8 +111,8 @@ def twitch_mock() -> Generator[AsyncMock]:
mock_client.return_value.get_followed_channels.return_value = TwitchIterObject( mock_client.return_value.get_followed_channels.return_value = TwitchIterObject(
"get_followed_channels.json", FollowedChannel "get_followed_channels.json", FollowedChannel
) )
mock_client.return_value.get_streams.return_value = get_generator( mock_client.return_value.get_followed_streams.return_value = get_generator(
"get_streams.json", Stream "get_followed_streams.json", Stream
) )
mock_client.return_value.check_user_subscription.return_value = ( mock_client.return_value.check_user_subscription.return_value = (
UserSubscription( UserSubscription(

View file

@ -1,9 +1,11 @@
[ [
{ {
"broadcaster_id": 123,
"broadcaster_login": "internetofthings", "broadcaster_login": "internetofthings",
"followed_at": "2023-08-01" "followed_at": "2023-08-01"
}, },
{ {
"broadcaster_id": 456,
"broadcaster_login": "homeassistant", "broadcaster_login": "homeassistant",
"followed_at": "2023-08-01" "followed_at": "2023-08-01"
} }

View file

@ -1,5 +1,6 @@
[ [
{ {
"user_id": 123,
"game_name": "Good game", "game_name": "Good game",
"title": "Title", "title": "Title",
"thumbnail_url": "stream-medium.png", "thumbnail_url": "stream-medium.png",

View file

@ -21,8 +21,8 @@ async def test_offline(
hass: HomeAssistant, twitch_mock: AsyncMock, config_entry: MockConfigEntry hass: HomeAssistant, twitch_mock: AsyncMock, config_entry: MockConfigEntry
) -> None: ) -> None:
"""Test offline state.""" """Test offline state."""
twitch_mock.return_value.get_streams.return_value = get_generator_from_data( twitch_mock.return_value.get_followed_streams.return_value = (
[], Stream get_generator_from_data([], Stream)
) )
await setup_integration(hass, config_entry) await setup_integration(hass, config_entry)