mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Hide TTS filename behind random token (#131192)
* Hide TTS filename behind random token * Clean up and fix test snapshots * Fix tests * Fix cloud tests
This commit is contained in:
parent
cb4636ada1
commit
d4071e7123
@ -13,6 +13,7 @@ import logging
|
||||
import mimetypes
|
||||
import os
|
||||
import re
|
||||
import secrets
|
||||
import subprocess
|
||||
import tempfile
|
||||
from typing import Any, Final, TypedDict, final
|
||||
@ -540,6 +541,10 @@ class SpeechManager:
|
||||
self.file_cache: dict[str, str] = {}
|
||||
self.mem_cache: dict[str, TTSCache] = {}
|
||||
|
||||
# filename <-> token
|
||||
self.filename_to_token: dict[str, str] = {}
|
||||
self.token_to_filename: dict[str, str] = {}
|
||||
|
||||
def _init_cache(self) -> dict[str, str]:
|
||||
"""Init cache folder and fetch files."""
|
||||
try:
|
||||
@ -656,7 +661,17 @@ class SpeechManager:
|
||||
engine_instance, cache_key, message, use_cache, language, options
|
||||
)
|
||||
|
||||
return f"/api/tts_proxy/{filename}"
|
||||
# Use a randomly generated token instead of exposing the filename
|
||||
token = self.filename_to_token.get(filename)
|
||||
if not token:
|
||||
# Keep extension (.mp3, etc.)
|
||||
token = secrets.token_urlsafe(16) + os.path.splitext(filename)[1]
|
||||
|
||||
# Map token <-> filename
|
||||
self.filename_to_token[filename] = token
|
||||
self.token_to_filename[token] = filename
|
||||
|
||||
return f"/api/tts_proxy/{token}"
|
||||
|
||||
async def async_get_tts_audio(
|
||||
self,
|
||||
@ -910,11 +925,15 @@ class SpeechManager:
|
||||
),
|
||||
)
|
||||
|
||||
async def async_read_tts(self, filename: str) -> tuple[str | None, bytes]:
|
||||
async def async_read_tts(self, token: str) -> tuple[str | None, bytes]:
|
||||
"""Read a voice file and return binary.
|
||||
|
||||
This method is a coroutine.
|
||||
"""
|
||||
filename = self.token_to_filename.get(token)
|
||||
if not filename:
|
||||
raise HomeAssistantError(f"{token} was not recognized!")
|
||||
|
||||
if not (record := _RE_VOICE_FILE.match(filename.lower())) and not (
|
||||
record := _RE_LEGACY_VOICE_FILE.match(filename.lower())
|
||||
):
|
||||
@ -1076,6 +1095,7 @@ class TextToSpeechView(HomeAssistantView):
|
||||
async def get(self, request: web.Request, filename: str) -> web.Response:
|
||||
"""Start a get request."""
|
||||
try:
|
||||
# filename is actually token, but we keep its name for compatibility
|
||||
content, data = await self.tts.async_read_tts(filename)
|
||||
except HomeAssistantError as err:
|
||||
_LOGGER.error("Error on load tts: %s", err)
|
||||
|
@ -77,7 +77,7 @@
|
||||
'tts_output': dict({
|
||||
'media_id': "media-source://tts/test?message=Sorry,+I+couldn't+understand+that&language=en-US&tts_options=%7B%22voice%22:%22james_earl_jones%22%7D",
|
||||
'mime_type': 'audio/mpeg',
|
||||
'url': '/api/tts_proxy/dae2cdcb27a1d1c3b07ba2c7db91480f9d4bfd8f_en-us_031e2ec052_test.mp3',
|
||||
'url': '/api/tts_proxy/test_token.mp3',
|
||||
}),
|
||||
}),
|
||||
'type': <PipelineEventType.TTS_END: 'tts-end'>,
|
||||
@ -166,7 +166,7 @@
|
||||
'tts_output': dict({
|
||||
'media_id': "media-source://tts/test?message=Sorry,+I+couldn't+understand+that&language=en-US&tts_options=%7B%22voice%22:%22Arnold+Schwarzenegger%22%7D",
|
||||
'mime_type': 'audio/mpeg',
|
||||
'url': '/api/tts_proxy/dae2cdcb27a1d1c3b07ba2c7db91480f9d4bfd8f_en-us_2657c1a8ee_test.mp3',
|
||||
'url': '/api/tts_proxy/test_token.mp3',
|
||||
}),
|
||||
}),
|
||||
'type': <PipelineEventType.TTS_END: 'tts-end'>,
|
||||
@ -255,7 +255,7 @@
|
||||
'tts_output': dict({
|
||||
'media_id': "media-source://tts/test?message=Sorry,+I+couldn't+understand+that&language=en-US&tts_options=%7B%22voice%22:%22Arnold+Schwarzenegger%22%7D",
|
||||
'mime_type': 'audio/mpeg',
|
||||
'url': '/api/tts_proxy/dae2cdcb27a1d1c3b07ba2c7db91480f9d4bfd8f_en-us_2657c1a8ee_test.mp3',
|
||||
'url': '/api/tts_proxy/test_token.mp3',
|
||||
}),
|
||||
}),
|
||||
'type': <PipelineEventType.TTS_END: 'tts-end'>,
|
||||
@ -368,7 +368,7 @@
|
||||
'tts_output': dict({
|
||||
'media_id': "media-source://tts/test?message=Sorry,+I+couldn't+understand+that&language=en-US&tts_options=%7B%22voice%22:%22james_earl_jones%22%7D",
|
||||
'mime_type': 'audio/mpeg',
|
||||
'url': '/api/tts_proxy/dae2cdcb27a1d1c3b07ba2c7db91480f9d4bfd8f_en-us_031e2ec052_test.mp3',
|
||||
'url': '/api/tts_proxy/test_token.mp3',
|
||||
}),
|
||||
}),
|
||||
'type': <PipelineEventType.TTS_END: 'tts-end'>,
|
||||
|
@ -73,7 +73,7 @@
|
||||
'tts_output': dict({
|
||||
'media_id': "media-source://tts/test?message=Sorry,+I+couldn't+understand+that&language=en-US&tts_options=%7B%22voice%22:%22james_earl_jones%22%7D",
|
||||
'mime_type': 'audio/mpeg',
|
||||
'url': '/api/tts_proxy/dae2cdcb27a1d1c3b07ba2c7db91480f9d4bfd8f_en-us_031e2ec052_test.mp3',
|
||||
'url': '/api/tts_proxy/test_token.mp3',
|
||||
}),
|
||||
})
|
||||
# ---
|
||||
@ -154,7 +154,7 @@
|
||||
'tts_output': dict({
|
||||
'media_id': "media-source://tts/test?message=Sorry,+I+couldn't+understand+that&language=en-US&tts_options=%7B%22voice%22:%22james_earl_jones%22%7D",
|
||||
'mime_type': 'audio/mpeg',
|
||||
'url': '/api/tts_proxy/dae2cdcb27a1d1c3b07ba2c7db91480f9d4bfd8f_en-us_031e2ec052_test.mp3',
|
||||
'url': '/api/tts_proxy/test_token.mp3',
|
||||
}),
|
||||
})
|
||||
# ---
|
||||
@ -247,7 +247,7 @@
|
||||
'tts_output': dict({
|
||||
'media_id': "media-source://tts/test?message=Sorry,+I+couldn't+understand+that&language=en-US&tts_options=%7B%22voice%22:%22james_earl_jones%22%7D",
|
||||
'mime_type': 'audio/mpeg',
|
||||
'url': '/api/tts_proxy/dae2cdcb27a1d1c3b07ba2c7db91480f9d4bfd8f_en-us_031e2ec052_test.mp3',
|
||||
'url': '/api/tts_proxy/test_token.mp3',
|
||||
}),
|
||||
})
|
||||
# ---
|
||||
@ -350,7 +350,7 @@
|
||||
'tts_output': dict({
|
||||
'media_id': "media-source://tts/test?message=Sorry,+I+couldn't+understand+that&language=en-US&tts_options=%7B%22voice%22:%22james_earl_jones%22%7D",
|
||||
'mime_type': 'audio/mpeg',
|
||||
'url': '/api/tts_proxy/dae2cdcb27a1d1c3b07ba2c7db91480f9d4bfd8f_en-us_031e2ec052_test.mp3',
|
||||
'url': '/api/tts_proxy/test_token.mp3',
|
||||
}),
|
||||
})
|
||||
# ---
|
||||
|
@ -70,21 +70,24 @@ async def test_pipeline_from_audio_stream_auto(
|
||||
yield make_10ms_chunk(b"part2")
|
||||
yield b""
|
||||
|
||||
await assist_pipeline.async_pipeline_from_audio_stream(
|
||||
hass,
|
||||
context=Context(),
|
||||
event_callback=events.append,
|
||||
stt_metadata=stt.SpeechMetadata(
|
||||
language="",
|
||||
format=stt.AudioFormats.WAV,
|
||||
codec=stt.AudioCodecs.PCM,
|
||||
bit_rate=stt.AudioBitRates.BITRATE_16,
|
||||
sample_rate=stt.AudioSampleRates.SAMPLERATE_16000,
|
||||
channel=stt.AudioChannels.CHANNEL_MONO,
|
||||
),
|
||||
stt_stream=audio_data(),
|
||||
audio_settings=assist_pipeline.AudioSettings(is_vad_enabled=False),
|
||||
)
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
await assist_pipeline.async_pipeline_from_audio_stream(
|
||||
hass,
|
||||
context=Context(),
|
||||
event_callback=events.append,
|
||||
stt_metadata=stt.SpeechMetadata(
|
||||
language="",
|
||||
format=stt.AudioFormats.WAV,
|
||||
codec=stt.AudioCodecs.PCM,
|
||||
bit_rate=stt.AudioBitRates.BITRATE_16,
|
||||
sample_rate=stt.AudioSampleRates.SAMPLERATE_16000,
|
||||
channel=stt.AudioChannels.CHANNEL_MONO,
|
||||
),
|
||||
stt_stream=audio_data(),
|
||||
audio_settings=assist_pipeline.AudioSettings(is_vad_enabled=False),
|
||||
)
|
||||
|
||||
assert process_events(events) == snapshot
|
||||
assert len(mock_stt_provider_entity.received) == 2
|
||||
@ -133,23 +136,26 @@ async def test_pipeline_from_audio_stream_legacy(
|
||||
assert msg["success"]
|
||||
pipeline_id = msg["result"]["id"]
|
||||
|
||||
# Use the created pipeline
|
||||
await assist_pipeline.async_pipeline_from_audio_stream(
|
||||
hass,
|
||||
context=Context(),
|
||||
event_callback=events.append,
|
||||
stt_metadata=stt.SpeechMetadata(
|
||||
language="en-UK",
|
||||
format=stt.AudioFormats.WAV,
|
||||
codec=stt.AudioCodecs.PCM,
|
||||
bit_rate=stt.AudioBitRates.BITRATE_16,
|
||||
sample_rate=stt.AudioSampleRates.SAMPLERATE_16000,
|
||||
channel=stt.AudioChannels.CHANNEL_MONO,
|
||||
),
|
||||
stt_stream=audio_data(),
|
||||
pipeline_id=pipeline_id,
|
||||
audio_settings=assist_pipeline.AudioSettings(is_vad_enabled=False),
|
||||
)
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
# Use the created pipeline
|
||||
await assist_pipeline.async_pipeline_from_audio_stream(
|
||||
hass,
|
||||
context=Context(),
|
||||
event_callback=events.append,
|
||||
stt_metadata=stt.SpeechMetadata(
|
||||
language="en-UK",
|
||||
format=stt.AudioFormats.WAV,
|
||||
codec=stt.AudioCodecs.PCM,
|
||||
bit_rate=stt.AudioBitRates.BITRATE_16,
|
||||
sample_rate=stt.AudioSampleRates.SAMPLERATE_16000,
|
||||
channel=stt.AudioChannels.CHANNEL_MONO,
|
||||
),
|
||||
stt_stream=audio_data(),
|
||||
pipeline_id=pipeline_id,
|
||||
audio_settings=assist_pipeline.AudioSettings(is_vad_enabled=False),
|
||||
)
|
||||
|
||||
assert process_events(events) == snapshot
|
||||
assert len(mock_stt_provider.received) == 2
|
||||
@ -198,23 +204,26 @@ async def test_pipeline_from_audio_stream_entity(
|
||||
assert msg["success"]
|
||||
pipeline_id = msg["result"]["id"]
|
||||
|
||||
# Use the created pipeline
|
||||
await assist_pipeline.async_pipeline_from_audio_stream(
|
||||
hass,
|
||||
context=Context(),
|
||||
event_callback=events.append,
|
||||
stt_metadata=stt.SpeechMetadata(
|
||||
language="en-UK",
|
||||
format=stt.AudioFormats.WAV,
|
||||
codec=stt.AudioCodecs.PCM,
|
||||
bit_rate=stt.AudioBitRates.BITRATE_16,
|
||||
sample_rate=stt.AudioSampleRates.SAMPLERATE_16000,
|
||||
channel=stt.AudioChannels.CHANNEL_MONO,
|
||||
),
|
||||
stt_stream=audio_data(),
|
||||
pipeline_id=pipeline_id,
|
||||
audio_settings=assist_pipeline.AudioSettings(is_vad_enabled=False),
|
||||
)
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
# Use the created pipeline
|
||||
await assist_pipeline.async_pipeline_from_audio_stream(
|
||||
hass,
|
||||
context=Context(),
|
||||
event_callback=events.append,
|
||||
stt_metadata=stt.SpeechMetadata(
|
||||
language="en-UK",
|
||||
format=stt.AudioFormats.WAV,
|
||||
codec=stt.AudioCodecs.PCM,
|
||||
bit_rate=stt.AudioBitRates.BITRATE_16,
|
||||
sample_rate=stt.AudioSampleRates.SAMPLERATE_16000,
|
||||
channel=stt.AudioChannels.CHANNEL_MONO,
|
||||
),
|
||||
stt_stream=audio_data(),
|
||||
pipeline_id=pipeline_id,
|
||||
audio_settings=assist_pipeline.AudioSettings(is_vad_enabled=False),
|
||||
)
|
||||
|
||||
assert process_events(events) == snapshot
|
||||
assert len(mock_stt_provider_entity.received) == 2
|
||||
@ -362,25 +371,28 @@ async def test_pipeline_from_audio_stream_wake_word(
|
||||
|
||||
yield b""
|
||||
|
||||
await assist_pipeline.async_pipeline_from_audio_stream(
|
||||
hass,
|
||||
context=Context(),
|
||||
event_callback=events.append,
|
||||
stt_metadata=stt.SpeechMetadata(
|
||||
language="",
|
||||
format=stt.AudioFormats.WAV,
|
||||
codec=stt.AudioCodecs.PCM,
|
||||
bit_rate=stt.AudioBitRates.BITRATE_16,
|
||||
sample_rate=stt.AudioSampleRates.SAMPLERATE_16000,
|
||||
channel=stt.AudioChannels.CHANNEL_MONO,
|
||||
),
|
||||
stt_stream=audio_data(),
|
||||
start_stage=assist_pipeline.PipelineStage.WAKE_WORD,
|
||||
wake_word_settings=assist_pipeline.WakeWordSettings(
|
||||
audio_seconds_to_buffer=1.5
|
||||
),
|
||||
audio_settings=assist_pipeline.AudioSettings(is_vad_enabled=False),
|
||||
)
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
await assist_pipeline.async_pipeline_from_audio_stream(
|
||||
hass,
|
||||
context=Context(),
|
||||
event_callback=events.append,
|
||||
stt_metadata=stt.SpeechMetadata(
|
||||
language="",
|
||||
format=stt.AudioFormats.WAV,
|
||||
codec=stt.AudioCodecs.PCM,
|
||||
bit_rate=stt.AudioBitRates.BITRATE_16,
|
||||
sample_rate=stt.AudioSampleRates.SAMPLERATE_16000,
|
||||
channel=stt.AudioChannels.CHANNEL_MONO,
|
||||
),
|
||||
stt_stream=audio_data(),
|
||||
start_stage=assist_pipeline.PipelineStage.WAKE_WORD,
|
||||
wake_word_settings=assist_pipeline.WakeWordSettings(
|
||||
audio_seconds_to_buffer=1.5
|
||||
),
|
||||
audio_settings=assist_pipeline.AudioSettings(is_vad_enabled=False),
|
||||
)
|
||||
|
||||
assert process_events(events) == snapshot
|
||||
|
||||
|
@ -119,85 +119,88 @@ async def test_audio_pipeline(
|
||||
events = []
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/run",
|
||||
"start_stage": "stt",
|
||||
"end_stage": "tts",
|
||||
"input": {
|
||||
"sample_rate": 44100,
|
||||
},
|
||||
}
|
||||
)
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/run",
|
||||
"start_stage": "stt",
|
||||
"end_stage": "tts",
|
||||
"input": {
|
||||
"sample_rate": 44100,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# result
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
# result
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
|
||||
# run start
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-start"
|
||||
msg["event"]["data"]["pipeline"] = ANY
|
||||
assert msg["event"]["data"] == snapshot
|
||||
handler_id = msg["event"]["data"]["runner_data"]["stt_binary_handler_id"]
|
||||
events.append(msg["event"])
|
||||
# run start
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-start"
|
||||
msg["event"]["data"]["pipeline"] = ANY
|
||||
assert msg["event"]["data"] == snapshot
|
||||
handler_id = msg["event"]["data"]["runner_data"]["stt_binary_handler_id"]
|
||||
events.append(msg["event"])
|
||||
|
||||
# stt
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# stt
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# End of audio stream (handler id + empty payload)
|
||||
await client.send_bytes(bytes([handler_id]))
|
||||
# End of audio stream (handler id + empty payload)
|
||||
await client.send_bytes(bytes([handler_id]))
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# intent
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# intent
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# text-to-speech
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# text-to-speech
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# run end
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# run end
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
pipeline_data: PipelineData = hass.data[DOMAIN]
|
||||
pipeline_id = list(pipeline_data.pipeline_debug)[0]
|
||||
pipeline_run_id = list(pipeline_data.pipeline_debug[pipeline_id])[0]
|
||||
pipeline_data: PipelineData = hass.data[DOMAIN]
|
||||
pipeline_id = list(pipeline_data.pipeline_debug)[0]
|
||||
pipeline_run_id = list(pipeline_data.pipeline_debug[pipeline_id])[0]
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/pipeline_debug/get",
|
||||
"pipeline_id": pipeline_id,
|
||||
"pipeline_run_id": pipeline_run_id,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {"events": events}
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/pipeline_debug/get",
|
||||
"pipeline_id": pipeline_id,
|
||||
"pipeline_run_id": pipeline_run_id,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {"events": events}
|
||||
|
||||
|
||||
async def test_audio_pipeline_with_wake_word_timeout(
|
||||
@ -210,49 +213,52 @@ async def test_audio_pipeline_with_wake_word_timeout(
|
||||
events = []
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/run",
|
||||
"start_stage": "wake_word",
|
||||
"end_stage": "tts",
|
||||
"input": {
|
||||
"sample_rate": SAMPLE_RATE,
|
||||
"timeout": 1,
|
||||
},
|
||||
}
|
||||
)
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/run",
|
||||
"start_stage": "wake_word",
|
||||
"end_stage": "tts",
|
||||
"input": {
|
||||
"sample_rate": SAMPLE_RATE,
|
||||
"timeout": 1,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# result
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"], msg
|
||||
# result
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"], msg
|
||||
|
||||
# run start
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-start"
|
||||
msg["event"]["data"]["pipeline"] = ANY
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# run start
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-start"
|
||||
msg["event"]["data"]["pipeline"] = ANY
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# wake_word
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "wake_word-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# wake_word
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "wake_word-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# 2 seconds of silence
|
||||
await client.send_bytes(bytes([1]) + bytes(2 * BYTES_ONE_SECOND))
|
||||
# 2 seconds of silence
|
||||
await client.send_bytes(bytes([1]) + bytes(2 * BYTES_ONE_SECOND))
|
||||
|
||||
# Time out error
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "error"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# Time out error
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "error"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# run end
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# run end
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
|
||||
async def test_audio_pipeline_with_wake_word_no_timeout(
|
||||
@ -265,98 +271,101 @@ async def test_audio_pipeline_with_wake_word_no_timeout(
|
||||
events = []
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/run",
|
||||
"start_stage": "wake_word",
|
||||
"end_stage": "tts",
|
||||
"input": {"sample_rate": SAMPLE_RATE, "timeout": 0, "no_vad": True},
|
||||
}
|
||||
)
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/run",
|
||||
"start_stage": "wake_word",
|
||||
"end_stage": "tts",
|
||||
"input": {"sample_rate": SAMPLE_RATE, "timeout": 0, "no_vad": True},
|
||||
}
|
||||
)
|
||||
|
||||
# result
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"], msg
|
||||
|
||||
# run start
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-start"
|
||||
msg["event"]["data"]["pipeline"] = ANY
|
||||
assert msg["event"]["data"] == snapshot
|
||||
handler_id = msg["event"]["data"]["runner_data"]["stt_binary_handler_id"]
|
||||
events.append(msg["event"])
|
||||
|
||||
# wake_word
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "wake_word-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# "audio"
|
||||
await client.send_bytes(bytes([handler_id]) + make_10ms_chunk(b"wake word"))
|
||||
|
||||
async with asyncio.timeout(1):
|
||||
# result
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "wake_word-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
assert msg["success"], msg
|
||||
|
||||
# stt
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# run start
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-start"
|
||||
msg["event"]["data"]["pipeline"] = ANY
|
||||
assert msg["event"]["data"] == snapshot
|
||||
handler_id = msg["event"]["data"]["runner_data"]["stt_binary_handler_id"]
|
||||
events.append(msg["event"])
|
||||
|
||||
# End of audio stream (handler id + empty payload)
|
||||
await client.send_bytes(bytes([handler_id]))
|
||||
# wake_word
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "wake_word-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# "audio"
|
||||
await client.send_bytes(bytes([handler_id]) + make_10ms_chunk(b"wake word"))
|
||||
|
||||
# intent
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
async with asyncio.timeout(1):
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "wake_word-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# stt
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# text-to-speech
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# End of audio stream (handler id + empty payload)
|
||||
await client.send_bytes(bytes([handler_id]))
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# run end
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# intent
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
pipeline_data: PipelineData = hass.data[DOMAIN]
|
||||
pipeline_id = list(pipeline_data.pipeline_debug)[0]
|
||||
pipeline_run_id = list(pipeline_data.pipeline_debug[pipeline_id])[0]
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/pipeline_debug/get",
|
||||
"pipeline_id": pipeline_id,
|
||||
"pipeline_run_id": pipeline_run_id,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {"events": events}
|
||||
# text-to-speech
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# run end
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
pipeline_data: PipelineData = hass.data[DOMAIN]
|
||||
pipeline_id = list(pipeline_data.pipeline_debug)[0]
|
||||
pipeline_run_id = list(pipeline_data.pipeline_debug[pipeline_id])[0]
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/pipeline_debug/get",
|
||||
"pipeline_id": pipeline_id,
|
||||
"pipeline_run_id": pipeline_run_id,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {"events": events}
|
||||
|
||||
|
||||
async def test_audio_pipeline_no_wake_word_engine(
|
||||
@ -1540,99 +1549,102 @@ async def test_audio_pipeline_debug(
|
||||
events = []
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/run",
|
||||
"start_stage": "stt",
|
||||
"end_stage": "tts",
|
||||
"input": {
|
||||
"sample_rate": 44100,
|
||||
},
|
||||
}
|
||||
)
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/run",
|
||||
"start_stage": "stt",
|
||||
"end_stage": "tts",
|
||||
"input": {
|
||||
"sample_rate": 44100,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# result
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
# result
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
|
||||
# run start
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-start"
|
||||
msg["event"]["data"]["pipeline"] = ANY
|
||||
assert msg["event"]["data"] == snapshot
|
||||
handler_id = msg["event"]["data"]["runner_data"]["stt_binary_handler_id"]
|
||||
events.append(msg["event"])
|
||||
# run start
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-start"
|
||||
msg["event"]["data"]["pipeline"] = ANY
|
||||
assert msg["event"]["data"] == snapshot
|
||||
handler_id = msg["event"]["data"]["runner_data"]["stt_binary_handler_id"]
|
||||
events.append(msg["event"])
|
||||
|
||||
# stt
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# stt
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# End of audio stream (handler id + empty payload)
|
||||
await client.send_bytes(bytes([handler_id]))
|
||||
# End of audio stream (handler id + empty payload)
|
||||
await client.send_bytes(bytes([handler_id]))
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# intent
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# intent
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# text-to-speech
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# text-to-speech
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# run end
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# run end
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# Get the id of the pipeline
|
||||
await client.send_json_auto_id({"type": "assist_pipeline/pipeline/list"})
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert len(msg["result"]["pipelines"]) == 1
|
||||
# Get the id of the pipeline
|
||||
await client.send_json_auto_id({"type": "assist_pipeline/pipeline/list"})
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert len(msg["result"]["pipelines"]) == 1
|
||||
|
||||
pipeline_id = msg["result"]["pipelines"][0]["id"]
|
||||
pipeline_id = msg["result"]["pipelines"][0]["id"]
|
||||
|
||||
# Get the id for the run
|
||||
await client.send_json_auto_id(
|
||||
{"type": "assist_pipeline/pipeline_debug/list", "pipeline_id": pipeline_id}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {"pipeline_runs": [ANY]}
|
||||
# Get the id for the run
|
||||
await client.send_json_auto_id(
|
||||
{"type": "assist_pipeline/pipeline_debug/list", "pipeline_id": pipeline_id}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {"pipeline_runs": [ANY]}
|
||||
|
||||
pipeline_run_id = msg["result"]["pipeline_runs"][0]["pipeline_run_id"]
|
||||
pipeline_run_id = msg["result"]["pipeline_runs"][0]["pipeline_run_id"]
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/pipeline_debug/get",
|
||||
"pipeline_id": pipeline_id,
|
||||
"pipeline_run_id": pipeline_run_id,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {"events": events}
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/pipeline_debug/get",
|
||||
"pipeline_id": pipeline_id,
|
||||
"pipeline_run_id": pipeline_run_id,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {"events": events}
|
||||
|
||||
|
||||
async def test_pipeline_debug_list_runs_wrong_pipeline(
|
||||
@ -1787,94 +1799,97 @@ async def test_audio_pipeline_with_enhancements(
|
||||
events = []
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/run",
|
||||
"start_stage": "stt",
|
||||
"end_stage": "tts",
|
||||
"input": {
|
||||
"sample_rate": SAMPLE_RATE,
|
||||
# Enhancements
|
||||
"noise_suppression_level": 2,
|
||||
"auto_gain_dbfs": 15,
|
||||
"volume_multiplier": 2.0,
|
||||
},
|
||||
}
|
||||
)
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/run",
|
||||
"start_stage": "stt",
|
||||
"end_stage": "tts",
|
||||
"input": {
|
||||
"sample_rate": SAMPLE_RATE,
|
||||
# Enhancements
|
||||
"noise_suppression_level": 2,
|
||||
"auto_gain_dbfs": 15,
|
||||
"volume_multiplier": 2.0,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# result
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
# result
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
|
||||
# run start
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-start"
|
||||
msg["event"]["data"]["pipeline"] = ANY
|
||||
assert msg["event"]["data"] == snapshot
|
||||
handler_id = msg["event"]["data"]["runner_data"]["stt_binary_handler_id"]
|
||||
events.append(msg["event"])
|
||||
# run start
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-start"
|
||||
msg["event"]["data"]["pipeline"] = ANY
|
||||
assert msg["event"]["data"] == snapshot
|
||||
handler_id = msg["event"]["data"]["runner_data"]["stt_binary_handler_id"]
|
||||
events.append(msg["event"])
|
||||
|
||||
# stt
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# stt
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# One second of silence.
|
||||
# This will pass through the audio enhancement pipeline, but we don't test
|
||||
# the actual output.
|
||||
await client.send_bytes(bytes([handler_id]) + bytes(BYTES_ONE_SECOND))
|
||||
# One second of silence.
|
||||
# This will pass through the audio enhancement pipeline, but we don't test
|
||||
# the actual output.
|
||||
await client.send_bytes(bytes([handler_id]) + bytes(BYTES_ONE_SECOND))
|
||||
|
||||
# End of audio stream (handler id + empty payload)
|
||||
await client.send_bytes(bytes([handler_id]))
|
||||
# End of audio stream (handler id + empty payload)
|
||||
await client.send_bytes(bytes([handler_id]))
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "stt-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# intent
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# intent
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "intent-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# text-to-speech
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# text-to-speech
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-start"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "tts-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
# run end
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
# run end
|
||||
msg = await client.receive_json()
|
||||
assert msg["event"]["type"] == "run-end"
|
||||
assert msg["event"]["data"] == snapshot
|
||||
events.append(msg["event"])
|
||||
|
||||
pipeline_data: PipelineData = hass.data[DOMAIN]
|
||||
pipeline_id = list(pipeline_data.pipeline_debug)[0]
|
||||
pipeline_run_id = list(pipeline_data.pipeline_debug[pipeline_id])[0]
|
||||
pipeline_data: PipelineData = hass.data[DOMAIN]
|
||||
pipeline_id = list(pipeline_data.pipeline_debug)[0]
|
||||
pipeline_run_id = list(pipeline_data.pipeline_debug[pipeline_id])[0]
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/pipeline_debug/get",
|
||||
"pipeline_id": pipeline_id,
|
||||
"pipeline_run_id": pipeline_run_id,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {"events": events}
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "assist_pipeline/pipeline_debug/get",
|
||||
"pipeline_id": pipeline_id,
|
||||
"pipeline_run_id": pipeline_run_id,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {"events": events}
|
||||
|
||||
|
||||
async def test_wake_word_cooldown_same_id(
|
||||
|
@ -227,25 +227,21 @@ async def test_get_tts_audio(
|
||||
await on_start_callback()
|
||||
client = await hass_client()
|
||||
|
||||
url = "/api/tts_get_url"
|
||||
data |= {"message": "There is someone at the door."}
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
url = "/api/tts_get_url"
|
||||
data |= {"message": "There is someone at the door."}
|
||||
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
|
||||
assert response == {
|
||||
"url": (
|
||||
"http://example.local:8123/api/tts_proxy/"
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_6e8b81ac47_{expected_url_suffix}.mp3"
|
||||
),
|
||||
"path": (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_6e8b81ac47_{expected_url_suffix}.mp3"
|
||||
),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
assert response == {
|
||||
"url": ("http://example.local:8123/api/tts_proxy/test_token.mp3"),
|
||||
"path": ("/api/tts_proxy/test_token.mp3"),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_process_tts.call_count == 1
|
||||
assert mock_process_tts.call_args is not None
|
||||
@ -280,25 +276,21 @@ async def test_get_tts_audio_logged_out(
|
||||
await hass.async_block_till_done()
|
||||
client = await hass_client()
|
||||
|
||||
url = "/api/tts_get_url"
|
||||
data |= {"message": "There is someone at the door."}
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
url = "/api/tts_get_url"
|
||||
data |= {"message": "There is someone at the door."}
|
||||
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
|
||||
assert response == {
|
||||
"url": (
|
||||
"http://example.local:8123/api/tts_proxy/"
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_6e8b81ac47_{expected_url_suffix}.mp3"
|
||||
),
|
||||
"path": (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_6e8b81ac47_{expected_url_suffix}.mp3"
|
||||
),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
assert response == {
|
||||
"url": ("http://example.local:8123/api/tts_proxy/test_token.mp3"),
|
||||
"path": ("/api/tts_proxy/test_token.mp3"),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_process_tts.call_count == 1
|
||||
assert mock_process_tts.call_args is not None
|
||||
@ -342,28 +334,24 @@ async def test_tts_entity(
|
||||
assert state
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
url = "/api/tts_get_url"
|
||||
data = {
|
||||
"engine_id": entity_id,
|
||||
"message": "There is someone at the door.",
|
||||
}
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
url = "/api/tts_get_url"
|
||||
data = {
|
||||
"engine_id": entity_id,
|
||||
"message": "There is someone at the door.",
|
||||
}
|
||||
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
|
||||
assert response == {
|
||||
"url": (
|
||||
"http://example.local:8123/api/tts_proxy/"
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_6e8b81ac47_{entity_id}.mp3"
|
||||
),
|
||||
"path": (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_6e8b81ac47_{entity_id}.mp3"
|
||||
),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
assert response == {
|
||||
"url": ("http://example.local:8123/api/tts_proxy/test_token.mp3"),
|
||||
"path": ("/api/tts_proxy/test_token.mp3"),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_process_tts.call_count == 1
|
||||
assert mock_process_tts.call_args is not None
|
||||
@ -482,29 +470,25 @@ async def test_deprecated_voice(
|
||||
client = await hass_client()
|
||||
|
||||
# Test with non deprecated voice.
|
||||
url = "/api/tts_get_url"
|
||||
data |= {
|
||||
"message": "There is someone at the door.",
|
||||
"language": language,
|
||||
"options": {"voice": replacement_voice},
|
||||
}
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
url = "/api/tts_get_url"
|
||||
data |= {
|
||||
"message": "There is someone at the door.",
|
||||
"language": language,
|
||||
"options": {"voice": replacement_voice},
|
||||
}
|
||||
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
|
||||
assert response == {
|
||||
"url": (
|
||||
"http://example.local:8123/api/tts_proxy/"
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_{language.lower()}_87567e3e29_{expected_url_suffix}.mp3"
|
||||
),
|
||||
"path": (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_{language.lower()}_87567e3e29_{expected_url_suffix}.mp3"
|
||||
),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
assert response == {
|
||||
"url": ("http://example.local:8123/api/tts_proxy/test_token.mp3"),
|
||||
"path": ("/api/tts_proxy/test_token.mp3"),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_process_tts.call_count == 1
|
||||
assert mock_process_tts.call_args is not None
|
||||
@ -522,22 +506,18 @@ async def test_deprecated_voice(
|
||||
# Test with deprecated voice.
|
||||
data["options"] = {"voice": deprecated_voice}
|
||||
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
|
||||
assert response == {
|
||||
"url": (
|
||||
"http://example.local:8123/api/tts_proxy/"
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_{language.lower()}_13646b7d32_{expected_url_suffix}.mp3"
|
||||
),
|
||||
"path": (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_{language.lower()}_13646b7d32_{expected_url_suffix}.mp3"
|
||||
),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
assert response == {
|
||||
"url": ("http://example.local:8123/api/tts_proxy/test_token.mp3"),
|
||||
"path": ("/api/tts_proxy/test_token.mp3"),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_id = f"deprecated_voice_{deprecated_voice}"
|
||||
|
||||
@ -631,28 +611,24 @@ async def test_deprecated_gender(
|
||||
client = await hass_client()
|
||||
|
||||
# Test without deprecated gender option.
|
||||
url = "/api/tts_get_url"
|
||||
data |= {
|
||||
"message": "There is someone at the door.",
|
||||
"language": language,
|
||||
}
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
url = "/api/tts_get_url"
|
||||
data |= {
|
||||
"message": "There is someone at the door.",
|
||||
"language": language,
|
||||
}
|
||||
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
|
||||
assert response == {
|
||||
"url": (
|
||||
"http://example.local:8123/api/tts_proxy/"
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_{language.lower()}_6e8b81ac47_{expected_url_suffix}.mp3"
|
||||
),
|
||||
"path": (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_{language.lower()}_6e8b81ac47_{expected_url_suffix}.mp3"
|
||||
),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
assert response == {
|
||||
"url": ("http://example.local:8123/api/tts_proxy/test_token.mp3"),
|
||||
"path": ("/api/tts_proxy/test_token.mp3"),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_process_tts.call_count == 1
|
||||
assert mock_process_tts.call_args is not None
|
||||
@ -667,22 +643,18 @@ async def test_deprecated_gender(
|
||||
# Test with deprecated gender option.
|
||||
data["options"] = {"gender": gender_option}
|
||||
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
|
||||
assert response == {
|
||||
"url": (
|
||||
"http://example.local:8123/api/tts_proxy/"
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_{language.lower()}_dd0e95eb04_{expected_url_suffix}.mp3"
|
||||
),
|
||||
"path": (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_{language.lower()}_dd0e95eb04_{expected_url_suffix}.mp3"
|
||||
),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
assert response == {
|
||||
"url": ("http://example.local:8123/api/tts_proxy/test_token.mp3"),
|
||||
"path": ("/api/tts_proxy/test_token.mp3"),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_id = "deprecated_gender"
|
||||
|
||||
|
@ -204,18 +204,20 @@ async def test_service(
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data[ATTR_MEDIA_ANNOUNCE] is True
|
||||
assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MediaType.MUSIC
|
||||
assert await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]) == (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_-_{expected_url_suffix}.mp3"
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ f"42f18378fd4393d18c8dd11d03fa9563c1e54491_en-us_-_{expected_url_suffix}.mp3"
|
||||
).is_file()
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data[ATTR_MEDIA_ANNOUNCE] is True
|
||||
assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MediaType.MUSIC
|
||||
assert await get_media_source_url(
|
||||
hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]
|
||||
) == ("/api/tts_proxy/test_token.mp3")
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ f"42f18378fd4393d18c8dd11d03fa9563c1e54491_en-us_-_{expected_url_suffix}.mp3"
|
||||
).is_file()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -266,17 +268,20 @@ async def test_service_default_language(
|
||||
)
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MediaType.MUSIC
|
||||
assert await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]) == (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_de-de_-_{expected_url_suffix}.mp3"
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ (
|
||||
f"42f18378fd4393d18c8dd11d03fa9563c1e54491_de-de_-_{expected_url_suffix}.mp3"
|
||||
)
|
||||
).is_file()
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
assert await get_media_source_url(
|
||||
hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]
|
||||
) == ("/api/tts_proxy/test_token.mp3")
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ (
|
||||
f"42f18378fd4393d18c8dd11d03fa9563c1e54491_de-de_-_{expected_url_suffix}.mp3"
|
||||
)
|
||||
).is_file()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -327,15 +332,18 @@ async def test_service_default_special_language(
|
||||
)
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MediaType.MUSIC
|
||||
assert await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]) == (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_-_{expected_url_suffix}.mp3"
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ f"42f18378fd4393d18c8dd11d03fa9563c1e54491_en-us_-_{expected_url_suffix}.mp3"
|
||||
).is_file()
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
assert await get_media_source_url(
|
||||
hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]
|
||||
) == ("/api/tts_proxy/test_token.mp3")
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ f"42f18378fd4393d18c8dd11d03fa9563c1e54491_en-us_-_{expected_url_suffix}.mp3"
|
||||
).is_file()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -384,15 +392,18 @@ async def test_service_language(
|
||||
)
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MediaType.MUSIC
|
||||
assert await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]) == (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_de-de_-_{expected_url_suffix}.mp3"
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ f"42f18378fd4393d18c8dd11d03fa9563c1e54491_de-de_-_{expected_url_suffix}.mp3"
|
||||
).is_file()
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
assert await get_media_source_url(
|
||||
hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]
|
||||
) == ("/api/tts_proxy/test_token.mp3")
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ f"42f18378fd4393d18c8dd11d03fa9563c1e54491_de-de_-_{expected_url_suffix}.mp3"
|
||||
).is_file()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -497,18 +508,21 @@ async def test_service_options(
|
||||
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MediaType.MUSIC
|
||||
assert await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]) == (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_de-de_{opt_hash}_{expected_url_suffix}.mp3"
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ (
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_de-de_{opt_hash}_{expected_url_suffix}.mp3"
|
||||
)
|
||||
).is_file()
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
assert await get_media_source_url(
|
||||
hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]
|
||||
) == ("/api/tts_proxy/test_token.mp3")
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ (
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_de-de_{opt_hash}_{expected_url_suffix}.mp3"
|
||||
)
|
||||
).is_file()
|
||||
|
||||
|
||||
class MockProviderWithDefaults(MockTTSProvider):
|
||||
@ -578,18 +592,21 @@ async def test_service_default_options(
|
||||
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MediaType.MUSIC
|
||||
assert await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]) == (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_de-de_{opt_hash}_{expected_url_suffix}.mp3"
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ (
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_de-de_{opt_hash}_{expected_url_suffix}.mp3"
|
||||
)
|
||||
).is_file()
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
assert await get_media_source_url(
|
||||
hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]
|
||||
) == ("/api/tts_proxy/test_token.mp3")
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ (
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_de-de_{opt_hash}_{expected_url_suffix}.mp3"
|
||||
)
|
||||
).is_file()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -649,18 +666,21 @@ async def test_merge_default_service_options(
|
||||
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MediaType.MUSIC
|
||||
assert await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]) == (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_de-de_{opt_hash}_{expected_url_suffix}.mp3"
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ (
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_de-de_{opt_hash}_{expected_url_suffix}.mp3"
|
||||
)
|
||||
).is_file()
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
assert await get_media_source_url(
|
||||
hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]
|
||||
) == ("/api/tts_proxy/test_token.mp3")
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
mock_tts_cache_dir
|
||||
/ (
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_de-de_{opt_hash}_{expected_url_suffix}.mp3"
|
||||
)
|
||||
).is_file()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -1065,10 +1085,14 @@ async def test_setup_legacy_cache_dir(
|
||||
)
|
||||
|
||||
assert len(calls) == 1
|
||||
assert await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]) == (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491_en-us_-_test.mp3"
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
assert await get_media_source_url(
|
||||
hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]
|
||||
) == ("/api/tts_proxy/test_token.mp3")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_tts_entity", [MockEntityBoom(DEFAULT_LANG)])
|
||||
@ -1100,10 +1124,13 @@ async def test_setup_cache_dir(
|
||||
)
|
||||
|
||||
assert len(calls) == 1
|
||||
assert await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]) == (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491_en-us_-_tts.test.mp3"
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
assert await get_media_source_url(
|
||||
hass, calls[0].data[ATTR_MEDIA_CONTENT_ID]
|
||||
) == ("/api/tts_proxy/test_token.mp3")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
class MockProviderEmpty(MockTTSProvider):
|
||||
@ -1176,13 +1203,13 @@ async def test_service_get_tts_error(
|
||||
)
|
||||
|
||||
|
||||
async def test_load_cache_legacy_retrieve_without_mem_cache(
|
||||
async def test_legacy_cannot_retrieve_without_token(
|
||||
hass: HomeAssistant,
|
||||
mock_provider: MockTTSProvider,
|
||||
mock_tts_cache_dir: Path,
|
||||
hass_client: ClientSessionGenerator,
|
||||
) -> None:
|
||||
"""Set up component and load cache and get without mem cache."""
|
||||
"""Verify that a TTS cannot be retrieved by filename directly."""
|
||||
tts_data = b""
|
||||
cache_file = (
|
||||
mock_tts_cache_dir / "42f18378fd4393d18c8dd11d03fa9563c1e54491_en_-_test.mp3"
|
||||
@ -1196,17 +1223,16 @@ async def test_load_cache_legacy_retrieve_without_mem_cache(
|
||||
url = "/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491_en_-_test.mp3"
|
||||
|
||||
req = await client.get(url)
|
||||
assert req.status == HTTPStatus.OK
|
||||
assert await req.read() == tts_data
|
||||
assert req.status == HTTPStatus.NOT_FOUND
|
||||
|
||||
|
||||
async def test_load_cache_retrieve_without_mem_cache(
|
||||
async def test_cannot_retrieve_without_token(
|
||||
hass: HomeAssistant,
|
||||
mock_tts_entity: MockTTSEntity,
|
||||
mock_tts_cache_dir: Path,
|
||||
hass_client: ClientSessionGenerator,
|
||||
) -> None:
|
||||
"""Set up component and load cache and get without mem cache."""
|
||||
"""Verify that a TTS cannot be retrieved by filename directly."""
|
||||
tts_data = b""
|
||||
cache_file = mock_tts_cache_dir / (
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491_en-us_-_tts.test.mp3"
|
||||
@ -1220,45 +1246,37 @@ async def test_load_cache_retrieve_without_mem_cache(
|
||||
url = "/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491_en-us_-_tts.test.mp3"
|
||||
|
||||
req = await client.get(url)
|
||||
assert req.status == HTTPStatus.OK
|
||||
assert await req.read() == tts_data
|
||||
assert req.status == HTTPStatus.NOT_FOUND
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("setup", "data", "expected_url_suffix"),
|
||||
("setup", "data"),
|
||||
[
|
||||
("mock_setup", {"platform": "test"}, "test"),
|
||||
("mock_setup", {"engine_id": "test"}, "test"),
|
||||
("mock_config_entry_setup", {"engine_id": "tts.test"}, "tts.test"),
|
||||
("mock_setup", {"platform": "test"}),
|
||||
("mock_setup", {"engine_id": "test"}),
|
||||
("mock_config_entry_setup", {"engine_id": "tts.test"}),
|
||||
],
|
||||
indirect=["setup"],
|
||||
)
|
||||
async def test_web_get_url(
|
||||
hass_client: ClientSessionGenerator,
|
||||
setup: str,
|
||||
data: dict[str, Any],
|
||||
expected_url_suffix: str,
|
||||
hass_client: ClientSessionGenerator, setup: str, data: dict[str, Any]
|
||||
) -> None:
|
||||
"""Set up a TTS platform and receive file from web."""
|
||||
client = await hass_client()
|
||||
|
||||
url = "/api/tts_get_url"
|
||||
data |= {"message": "There is someone at the door."}
|
||||
with patch(
|
||||
"homeassistant.components.tts.secrets.token_urlsafe", return_value="test_token"
|
||||
):
|
||||
url = "/api/tts_get_url"
|
||||
data |= {"message": "There is someone at the door."}
|
||||
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
assert response == {
|
||||
"url": (
|
||||
"http://example.local:8123/api/tts_proxy/"
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_-_{expected_url_suffix}.mp3"
|
||||
),
|
||||
"path": (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_-_{expected_url_suffix}.mp3"
|
||||
),
|
||||
}
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
assert response == {
|
||||
"url": ("http://example.local:8123/api/tts_proxy/test_token.mp3"),
|
||||
"path": ("/api/tts_proxy/test_token.mp3"),
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
Loading…
x
Reference in New Issue
Block a user