Add support to reprompt user (#65256)

pull/65328/head
w35l3y 2022-01-31 15:23:26 -03:00 committed by GitHub
parent 0cfc7112fa
commit 076faaa4a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 121 additions and 7 deletions

View File

@ -166,7 +166,10 @@ async def async_handle_intent(hass, message):
alexa_response.add_speech(
alexa_speech, intent_response.speech[intent_speech]["speech"]
)
break
if intent_speech in intent_response.reprompt:
alexa_response.add_reprompt(
alexa_speech, intent_response.reprompt[intent_speech]["reprompt"]
)
if "simple" in intent_response.card:
alexa_response.add_card(
@ -267,10 +270,9 @@ class AlexaResponse:
key = "ssml" if speech_type == SpeechType.ssml else "text"
self.reprompt = {
"type": speech_type.value,
key: text.async_render(self.variables, parse_result=False),
}
self.should_end_session = False
self.reprompt = {"type": speech_type.value, key: text}
def as_dict(self):
"""Return response in an Alexa valid dict."""

View File

@ -12,6 +12,7 @@ DOMAIN = "intent_script"
CONF_INTENTS = "intents"
CONF_SPEECH = "speech"
CONF_REPROMPT = "reprompt"
CONF_ACTION = "action"
CONF_CARD = "card"
@ -39,6 +40,10 @@ CONFIG_SCHEMA = vol.Schema(
vol.Optional(CONF_TYPE, default="plain"): cv.string,
vol.Required(CONF_TEXT): cv.template,
},
vol.Optional(CONF_REPROMPT): {
vol.Optional(CONF_TYPE, default="plain"): cv.string,
vol.Required(CONF_TEXT): cv.template,
},
}
}
},
@ -72,6 +77,7 @@ class ScriptIntentHandler(intent.IntentHandler):
async def async_handle(self, intent_obj):
"""Handle the intent."""
speech = self.config.get(CONF_SPEECH)
reprompt = self.config.get(CONF_REPROMPT)
card = self.config.get(CONF_CARD)
action = self.config.get(CONF_ACTION)
is_async_action = self.config.get(CONF_ASYNC_ACTION)
@ -93,6 +99,12 @@ class ScriptIntentHandler(intent.IntentHandler):
speech[CONF_TYPE],
)
if reprompt is not None and reprompt[CONF_TEXT].template:
response.async_set_reprompt(
reprompt[CONF_TEXT].async_render(slots, parse_result=False),
reprompt[CONF_TYPE],
)
if card is not None:
response.async_set_card(
card[CONF_TITLE].async_render(slots, parse_result=False),

View File

@ -249,6 +249,7 @@ class IntentResponse:
"""Initialize an IntentResponse."""
self.intent = intent
self.speech: dict[str, dict[str, Any]] = {}
self.reprompt: dict[str, dict[str, Any]] = {}
self.card: dict[str, dict[str, str]] = {}
@callback
@ -258,14 +259,25 @@ class IntentResponse:
"""Set speech response."""
self.speech[speech_type] = {"speech": speech, "extra_data": extra_data}
@callback
def async_set_reprompt(
self, speech: str, speech_type: str = "plain", extra_data: Any | None = None
) -> None:
"""Set reprompt response."""
self.reprompt[speech_type] = {"reprompt": speech, "extra_data": extra_data}
@callback
def async_set_card(
self, title: str, content: str, card_type: str = "simple"
) -> None:
"""Set speech response."""
"""Set card response."""
self.card[card_type] = {"title": title, "content": content}
@callback
def as_dict(self) -> dict[str, dict[str, dict[str, Any]]]:
"""Return a dictionary representation of an intent response."""
return {"speech": self.speech, "card": self.card}
return (
{"speech": self.speech, "reprompt": self.reprompt, "card": self.card}
if self.reprompt
else {"speech": self.speech, "card": self.card}
)

View File

@ -13,6 +13,9 @@ from homeassistant.setup import async_setup_component
SESSION_ID = "amzn1.echo-api.session.0000000-0000-0000-0000-00000000000"
APPLICATION_ID = "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
APPLICATION_ID_SESSION_OPEN = (
"amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebf"
)
REQUEST_ID = "amzn1.echo-api.request.0000000-0000-0000-0000-00000000000"
AUTHORITY_ID = "amzn1.er-authority.000000-d0ed-0000-ad00-000000d00ebe.ZODIAC"
BUILTIN_AUTH_ID = "amzn1.er-authority.000000-d0ed-0000-ad00-000000d00ebe.TEST"
@ -102,6 +105,16 @@ def alexa_client(loop, hass, hass_client):
"text": "LaunchRequest has been received.",
}
},
APPLICATION_ID_SESSION_OPEN: {
"speech": {
"type": "plain",
"text": "LaunchRequest has been received.",
},
"reprompt": {
"type": "plain",
"text": "LaunchRequest has been received.",
},
},
}
},
)
@ -139,6 +152,36 @@ async def test_intent_launch_request(alexa_client):
data = await req.json()
text = data.get("response", {}).get("outputSpeech", {}).get("text")
assert text == "LaunchRequest has been received."
assert data.get("response", {}).get("shouldEndSession")
async def test_intent_launch_request_with_session_open(alexa_client):
"""Test the launch of a request."""
data = {
"version": "1.0",
"session": {
"new": True,
"sessionId": SESSION_ID,
"application": {"applicationId": APPLICATION_ID_SESSION_OPEN},
"attributes": {},
"user": {"userId": "amzn1.account.AM3B00000000000000000000000"},
},
"request": {
"type": "LaunchRequest",
"requestId": REQUEST_ID,
"timestamp": "2015-05-13T12:34:56Z",
},
}
req = await _intent_req(alexa_client, data)
assert req.status == HTTPStatus.OK
data = await req.json()
text = data.get("response", {}).get("outputSpeech", {}).get("text")
assert text == "LaunchRequest has been received."
text = (
data.get("response", {}).get("reprompt", {}).get("outputSpeech", {}).get("text")
)
assert text == "LaunchRequest has been received."
assert not data.get("response", {}).get("shouldEndSession")
async def test_intent_launch_request_not_configured(alexa_client):

View File

@ -40,3 +40,48 @@ async def test_intent_script(hass):
assert response.card["simple"]["title"] == "Hello Paulus"
assert response.card["simple"]["content"] == "Content for Paulus"
async def test_intent_script_wait_response(hass):
"""Test intent scripts work."""
calls = async_mock_service(hass, "test", "service")
await async_setup_component(
hass,
"intent_script",
{
"intent_script": {
"HelloWorldWaitResponse": {
"action": {
"service": "test.service",
"data_template": {"hello": "{{ name }}"},
},
"card": {
"title": "Hello {{ name }}",
"content": "Content for {{ name }}",
},
"speech": {"text": "Good morning {{ name }}"},
"reprompt": {
"text": "I didn't hear you, {{ name }}... I said good morning!"
},
}
}
},
)
response = await intent.async_handle(
hass, "test", "HelloWorldWaitResponse", {"name": {"value": "Paulus"}}
)
assert len(calls) == 1
assert calls[0].data["hello"] == "Paulus"
assert response.speech["plain"]["speech"] == "Good morning Paulus"
assert (
response.reprompt["plain"]["reprompt"]
== "I didn't hear you, Paulus... I said good morning!"
)
assert response.card["simple"]["title"] == "Hello Paulus"
assert response.card["simple"]["content"] == "Content for Paulus"