Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make YouTube select lower quality thumbnails #94652

Merged
merged 10 commits into from
Jun 18, 2023
Merged
9 changes: 8 additions & 1 deletion homeassistant/components/youtube/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,16 @@ def _get_channel_data(
ATTR_PUBLISHED_AT: video["snippet"]["publishedAt"],
ATTR_TITLE: video["snippet"]["title"],
ATTR_DESCRIPTION: video["snippet"]["description"],
ATTR_THUMBNAIL: video["snippet"]["thumbnails"]["standard"]["url"],
ATTR_THUMBNAIL: self._get_thumbnail(video),
ATTR_VIDEO_ID: video["contentDetails"]["videoId"],
},
ATTR_SUBSCRIBER_COUNT: int(channel["statistics"]["subscriberCount"]),
}
return data

def _get_thumbnail(self, video: dict[str, Any]) -> str | None:
thumbnails = video["snippet"]["thumbnails"]
for size in ("standard", "high", "medium", "default"):
if size in thumbnails:
return thumbnails[size]["url"]
return None
4 changes: 2 additions & 2 deletions homeassistant/components/youtube/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class YouTubeMixin:
"""Mixin for required keys."""

value_fn: Callable[[Any], StateType]
entity_picture_fn: Callable[[Any], str]
entity_picture_fn: Callable[[Any], str | None]
attributes_fn: Callable[[Any], dict[str, Any]] | None


Expand Down Expand Up @@ -87,7 +87,7 @@ def native_value(self) -> StateType:
return self.entity_description.value_fn(self.coordinator.data[self._channel_id])

@property
def entity_picture(self) -> str:
def entity_picture(self) -> str | None:
"""Return the value reported by the sensor."""
return self.entity_description.entity_picture_fn(
self.coordinator.data[self._channel_id]
Expand Down
42 changes: 42 additions & 0 deletions tests/components/youtube/fixtures/thumbnail/default.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"kind": "youtube#playlistItemListResponse",
"etag": "O0Ah8Wd5pUD2Gsv-n0A42RDRcX8",
"nextPageToken": "EAAaBlBUOkNBVQ",
"items": [
{
"kind": "youtube#playlistItem",
"etag": "qgpoAJRNskzLhD99njC8e2kPB0M",
"id": "VVVfeDVYRzFPVjJQNnVaWjVGU005VHR3Lnd5c3VrRHJNZHFV",
"snippet": {
"publishedAt": "2023-05-11T00:20:46Z",
"channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
"title": "What's new in Google Home in less than 1 minute",
"description": "Discover how your connected devices can do more with Google Home using Matter and Automations at Google I/O 2023.\n\nTo learn more about what's new in Google Home, check out the keynote → https://goo.gle/IO23_homekey\n\nSubscribe to Google Developers → https://goo.gle/developers \n\n#GoogleIO #GoogleHome",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/wysukDrMdqU/default.jpg",
"width": 120,
"height": 90
}
},
"channelTitle": "Google for Developers",
"playlistId": "UU_x5XG1OV2P6uZZ5FSM9Ttw",
"position": 0,
"resourceId": {
"kind": "youtube#video",
"videoId": "wysukDrMdqU"
},
"videoOwnerChannelTitle": "Google for Developers",
"videoOwnerChannelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw"
},
"contentDetails": {
"videoId": "wysukDrMdqU",
"videoPublishedAt": "2023-05-11T00:20:46Z"
}
}
],
"pageInfo": {
"totalResults": 5798,
"resultsPerPage": 1
}
}
52 changes: 52 additions & 0 deletions tests/components/youtube/fixtures/thumbnail/high.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"kind": "youtube#playlistItemListResponse",
"etag": "O0Ah8Wd5pUD2Gsv-n0A42RDRcX8",
"nextPageToken": "EAAaBlBUOkNBVQ",
"items": [
{
"kind": "youtube#playlistItem",
"etag": "qgpoAJRNskzLhD99njC8e2kPB0M",
"id": "VVVfeDVYRzFPVjJQNnVaWjVGU005VHR3Lnd5c3VrRHJNZHFV",
"snippet": {
"publishedAt": "2023-05-11T00:20:46Z",
"channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
"title": "What's new in Google Home in less than 1 minute",
"description": "Discover how your connected devices can do more with Google Home using Matter and Automations at Google I/O 2023.\n\nTo learn more about what's new in Google Home, check out the keynote → https://goo.gle/IO23_homekey\n\nSubscribe to Google Developers → https://goo.gle/developers \n\n#GoogleIO #GoogleHome",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/wysukDrMdqU/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/wysukDrMdqU/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/wysukDrMdqU/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "Google for Developers",
"playlistId": "UU_x5XG1OV2P6uZZ5FSM9Ttw",
"position": 0,
"resourceId": {
"kind": "youtube#video",
"videoId": "wysukDrMdqU"
},
"videoOwnerChannelTitle": "Google for Developers",
"videoOwnerChannelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw"
},
"contentDetails": {
"videoId": "wysukDrMdqU",
"videoPublishedAt": "2023-05-11T00:20:46Z"
}
}
],
"pageInfo": {
"totalResults": 5798,
"resultsPerPage": 1
}
}
47 changes: 47 additions & 0 deletions tests/components/youtube/fixtures/thumbnail/medium.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"kind": "youtube#playlistItemListResponse",
"etag": "O0Ah8Wd5pUD2Gsv-n0A42RDRcX8",
"nextPageToken": "EAAaBlBUOkNBVQ",
"items": [
{
"kind": "youtube#playlistItem",
"etag": "qgpoAJRNskzLhD99njC8e2kPB0M",
"id": "VVVfeDVYRzFPVjJQNnVaWjVGU005VHR3Lnd5c3VrRHJNZHFV",
"snippet": {
"publishedAt": "2023-05-11T00:20:46Z",
"channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
"title": "What's new in Google Home in less than 1 minute",
"description": "Discover how your connected devices can do more with Google Home using Matter and Automations at Google I/O 2023.\n\nTo learn more about what's new in Google Home, check out the keynote → https://goo.gle/IO23_homekey\n\nSubscribe to Google Developers → https://goo.gle/developers \n\n#GoogleIO #GoogleHome",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/wysukDrMdqU/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/wysukDrMdqU/mqdefault.jpg",
"width": 320,
"height": 180
}
},
"channelTitle": "Google for Developers",
"playlistId": "UU_x5XG1OV2P6uZZ5FSM9Ttw",
"position": 0,
"resourceId": {
"kind": "youtube#video",
"videoId": "wysukDrMdqU"
},
"videoOwnerChannelTitle": "Google for Developers",
"videoOwnerChannelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw"
},
"contentDetails": {
"videoId": "wysukDrMdqU",
"videoPublishedAt": "2023-05-11T00:20:46Z"
}
}
],
"pageInfo": {
"totalResults": 5798,
"resultsPerPage": 1
}
}
36 changes: 36 additions & 0 deletions tests/components/youtube/fixtures/thumbnail/none.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"kind": "youtube#playlistItemListResponse",
"etag": "O0Ah8Wd5pUD2Gsv-n0A42RDRcX8",
"nextPageToken": "EAAaBlBUOkNBVQ",
"items": [
{
"kind": "youtube#playlistItem",
"etag": "qgpoAJRNskzLhD99njC8e2kPB0M",
"id": "VVVfeDVYRzFPVjJQNnVaWjVGU005VHR3Lnd5c3VrRHJNZHFV",
"snippet": {
"publishedAt": "2023-05-11T00:20:46Z",
"channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
"title": "What's new in Google Home in less than 1 minute",
"description": "Discover how your connected devices can do more with Google Home using Matter and Automations at Google I/O 2023.\n\nTo learn more about what's new in Google Home, check out the keynote → https://goo.gle/IO23_homekey\n\nSubscribe to Google Developers → https://goo.gle/developers \n\n#GoogleIO #GoogleHome",
"thumbnails": {},
"channelTitle": "Google for Developers",
"playlistId": "UU_x5XG1OV2P6uZZ5FSM9Ttw",
"position": 0,
"resourceId": {
"kind": "youtube#video",
"videoId": "wysukDrMdqU"
},
"videoOwnerChannelTitle": "Google for Developers",
"videoOwnerChannelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw"
},
"contentDetails": {
"videoId": "wysukDrMdqU",
"videoPublishedAt": "2023-05-11T00:20:46Z"
}
}
],
"pageInfo": {
"totalResults": 5798,
"resultsPerPage": 1
}
}
57 changes: 57 additions & 0 deletions tests/components/youtube/fixtures/thumbnail/standard.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"kind": "youtube#playlistItemListResponse",
"etag": "O0Ah8Wd5pUD2Gsv-n0A42RDRcX8",
"nextPageToken": "EAAaBlBUOkNBVQ",
"items": [
{
"kind": "youtube#playlistItem",
"etag": "qgpoAJRNskzLhD99njC8e2kPB0M",
"id": "VVVfeDVYRzFPVjJQNnVaWjVGU005VHR3Lnd5c3VrRHJNZHFV",
"snippet": {
"publishedAt": "2023-05-11T00:20:46Z",
"channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
"title": "What's new in Google Home in less than 1 minute",
"description": "Discover how your connected devices can do more with Google Home using Matter and Automations at Google I/O 2023.\n\nTo learn more about what's new in Google Home, check out the keynote → https://goo.gle/IO23_homekey\n\nSubscribe to Google Developers → https://goo.gle/developers \n\n#GoogleIO #GoogleHome",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/wysukDrMdqU/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/wysukDrMdqU/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/wysukDrMdqU/hqdefault.jpg",
"width": 480,
"height": 360
},
"standard": {
"url": "https://i.ytimg.com/vi/wysukDrMdqU/sddefault.jpg",
"width": 640,
"height": 480
}
},
"channelTitle": "Google for Developers",
"playlistId": "UU_x5XG1OV2P6uZZ5FSM9Ttw",
"position": 0,
"resourceId": {
"kind": "youtube#video",
"videoId": "wysukDrMdqU"
},
"videoOwnerChannelTitle": "Google for Developers",
"videoOwnerChannelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw"
},
"contentDetails": {
"videoId": "wysukDrMdqU",
"videoPublishedAt": "2023-05-11T00:20:46Z"
}
}
],
"pageInfo": {
"totalResults": 5798,
"resultsPerPage": 1
}
}
36 changes: 36 additions & 0 deletions tests/components/youtube/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from unittest.mock import patch

from google.auth.exceptions import RefreshError
import pytest

from homeassistant import config_entries
from homeassistant.components.youtube import DOMAIN
Expand Down Expand Up @@ -87,3 +88,38 @@ async def test_sensor_reauth_trigger(
assert flow["step_id"] == "reauth_confirm"
assert flow["handler"] == DOMAIN
assert flow["context"]["source"] == config_entries.SOURCE_REAUTH


@pytest.mark.parametrize(
("fixture", "url", "has_entity_picture"),
[
("standard", "https://i.ytimg.com/vi/wysukDrMdqU/sddefault.jpg", True),
("high", "https://i.ytimg.com/vi/wysukDrMdqU/hqdefault.jpg", True),
("medium", "https://i.ytimg.com/vi/wysukDrMdqU/mqdefault.jpg", True),
("default", "https://i.ytimg.com/vi/wysukDrMdqU/default.jpg", True),
("none", None, False),
],
)
async def test_thumbnail(
hass: HomeAssistant,
setup_integration: ComponentSetup,
fixture: str,
url: str | None,
has_entity_picture: bool,
) -> None:
"""Test if right thumbnail is selected."""
await setup_integration()

with patch(
"homeassistant.components.youtube.api.build",
return_value=MockService(
playlist_items_fixture=f"youtube/thumbnail/{fixture}.json"
),
):
future = dt_util.utcnow() + timedelta(minutes=15)
async_fire_time_changed(hass, future)
await hass.async_block_till_done()
state = hass.states.get("sensor.google_for_developers_latest_upload")
assert state
assert ("entity_picture" in state.attributes) is has_entity_picture
assert state.attributes.get("entity_picture") == url