diff --git a/homeassistant/components/ntfy/notify.py b/homeassistant/components/ntfy/notify.py index 23f923e10052..f0de43f8f9c8 100644 --- a/homeassistant/components/ntfy/notify.py +++ b/homeassistant/components/ntfy/notify.py @@ -11,7 +11,7 @@ from aiontfy.exceptions import ( NtfyUnauthorizedAuthenticationError, ) -from homeassistant.components import camera, image +from homeassistant.components import camera, image, tts from homeassistant.components.media_source import async_resolve_media from homeassistant.components.notify import ( NotifyEntity, @@ -99,6 +99,10 @@ class NtfyNotifyEntity(NtfyBaseEntity, NotifyEntity): elif media_content_id.startswith("media-source://image/"): entity_id = media_content_id.removeprefix("media-source://image/") attachment = (await image.async_get_image(self.hass, entity_id)).content + elif media_content_id.startswith("media-source://tts/"): + _, attachment = await tts.async_get_media_source_audio( + self.hass, media_content_id + ) else: media = await async_resolve_media( self.hass, file["media_content_id"], None diff --git a/homeassistant/components/ntfy/strings.json b/homeassistant/components/ntfy/strings.json index 69b27e28be64..0882860a327f 100644 --- a/homeassistant/components/ntfy/strings.json +++ b/homeassistant/components/ntfy/strings.json @@ -410,7 +410,7 @@ "name": "Attachment URL" }, "attach_file": { - "description": "Attach images or other files by uploading from a local file, camera, or image media source. When selecting a camera entity, a snapshot of the current view will be captured and attached to the notification.", + "description": "Attach images or other files by uploading from a local file, camera, text-to-speech, or image media source. When selecting a camera entity, a snapshot of the current view will be captured and attached to the notification.", "name": "Attach local file" }, "call": { diff --git a/tests/components/ntfy/test_services.py b/tests/components/ntfy/test_services.py index 09eceac06717..632c7ea71baf 100644 --- a/tests/components/ntfy/test_services.py +++ b/tests/components/ntfy/test_services.py @@ -399,7 +399,7 @@ async def test_ntfy_publish_upload_media_source_not_supported( patch( "homeassistant.components.ntfy.notify.async_resolve_media", return_value=media_source.PlayMedia( - url="/api/tts_proxy/WDyphPCh3sAoO3koDY87ew.mp3", + url="https://gameclipscontent-d2009.media.xboxlive.com/123456789", mime_type="audio/mpeg", path=None, ), @@ -415,8 +415,8 @@ async def test_ntfy_publish_upload_media_source_not_supported( { ATTR_ENTITY_ID: "notify.mytopic", ATTR_ATTACH_FILE: { - "media_content_id": "media-source://tts/demo?message=Hello+world%21&language=en", - "media_content_type": "audio/mp3", + "media_content_id": "media-source://xbox/123456789/", + "media_content_type": "video/mp4", }, }, blocking=True, @@ -455,6 +455,40 @@ async def test_ntfy_publish_upload_media_image_source( mock_aiontfy.publish.assert_called_once_with(Message(topic="mytopic"), b"\x89PNG") +@pytest.mark.usefixtures("mock_aiontfy") +async def test_ntfy_publish_upload_tts_source( + hass: HomeAssistant, + config_entry: MockConfigEntry, + mock_aiontfy: AsyncMock, +) -> None: + """Test publishing ntfy message with tts source.""" + config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert config_entry.state is ConfigEntryState.LOADED + with patch( + "homeassistant.components.tts.async_get_media_source_audio", + return_value=("mp3", b"Test"), + ) as mock_get_media_source_audio: + await hass.services.async_call( + DOMAIN, + SERVICE_PUBLISH, + { + ATTR_ENTITY_ID: "notify.mytopic", + ATTR_ATTACH_FILE: { + "media_content_id": "media-source://tts/demo?message=Test&language=en", + "media_content_type": "audio/mp3", + }, + }, + blocking=True, + ) + mock_get_media_source_audio.assert_called_once_with( + hass, "media-source://tts/demo?message=Test&language=en" + ) + mock_aiontfy.publish.assert_called_once_with(Message(topic="mytopic"), b"Test") + + async def test_ntfy_clear( hass: HomeAssistant, config_entry: MockConfigEntry,