mirror of
https://github.com/home-assistant/core.git
synced 2025-05-13 18:39:14 +00:00

* add complete item intent * fix error and add tests * fix merge conflict * improve error tests * improve error tests * add response_key * add check for non completed --------- Co-authored-by: Michael Hansen <mike@rhasspy.org>
155 lines
5.1 KiB
Python
155 lines
5.1 KiB
Python
"""Intents for the todo integration."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers import intent
|
|
|
|
from . import TodoItem, TodoItemStatus, TodoListEntity
|
|
from .const import DATA_COMPONENT, DOMAIN
|
|
|
|
INTENT_LIST_ADD_ITEM = "HassListAddItem"
|
|
INTENT_LIST_COMPLETE_ITEM = "HassListCompleteItem"
|
|
|
|
|
|
async def async_setup_intents(hass: HomeAssistant) -> None:
|
|
"""Set up the todo intents."""
|
|
intent.async_register(hass, ListAddItemIntent())
|
|
intent.async_register(hass, ListCompleteItemIntent())
|
|
|
|
|
|
class ListAddItemIntent(intent.IntentHandler):
|
|
"""Handle ListAddItem intents."""
|
|
|
|
intent_type = INTENT_LIST_ADD_ITEM
|
|
description = "Add item to a todo list"
|
|
slot_schema = {
|
|
vol.Required("item"): intent.non_empty_string,
|
|
vol.Required("name"): intent.non_empty_string,
|
|
}
|
|
platforms = {DOMAIN}
|
|
|
|
async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
|
|
"""Handle the intent."""
|
|
hass = intent_obj.hass
|
|
|
|
slots = self.async_validate_slots(intent_obj.slots)
|
|
item = slots["item"]["value"].strip()
|
|
list_name = slots["name"]["value"]
|
|
|
|
target_list: TodoListEntity | None = None
|
|
|
|
# Find matching list
|
|
match_constraints = intent.MatchTargetsConstraints(
|
|
name=list_name, domains=[DOMAIN], assistant=intent_obj.assistant
|
|
)
|
|
match_result = intent.async_match_targets(hass, match_constraints)
|
|
if not match_result.is_match:
|
|
raise intent.MatchFailedError(
|
|
result=match_result, constraints=match_constraints
|
|
)
|
|
|
|
target_list = hass.data[DATA_COMPONENT].get_entity(
|
|
match_result.states[0].entity_id
|
|
)
|
|
if target_list is None:
|
|
raise intent.IntentHandleError(
|
|
f"No to-do list: {list_name}", "list_not_found"
|
|
)
|
|
|
|
# Add to list
|
|
await target_list.async_create_todo_item(
|
|
TodoItem(summary=item, status=TodoItemStatus.NEEDS_ACTION)
|
|
)
|
|
|
|
response: intent.IntentResponse = intent_obj.create_response()
|
|
response.response_type = intent.IntentResponseType.ACTION_DONE
|
|
response.async_set_results(
|
|
[
|
|
intent.IntentResponseTarget(
|
|
type=intent.IntentResponseTargetType.ENTITY,
|
|
name=list_name,
|
|
id=match_result.states[0].entity_id,
|
|
)
|
|
]
|
|
)
|
|
return response
|
|
|
|
|
|
class ListCompleteItemIntent(intent.IntentHandler):
|
|
"""Handle ListCompleteItem intents."""
|
|
|
|
intent_type = INTENT_LIST_COMPLETE_ITEM
|
|
description = "Complete item on a todo list"
|
|
slot_schema = {
|
|
vol.Required("item"): intent.non_empty_string,
|
|
vol.Required("name"): intent.non_empty_string,
|
|
}
|
|
platforms = {DOMAIN}
|
|
|
|
async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
|
|
"""Handle the intent."""
|
|
hass = intent_obj.hass
|
|
|
|
slots = self.async_validate_slots(intent_obj.slots)
|
|
item = slots["item"]["value"]
|
|
list_name = slots["name"]["value"]
|
|
|
|
target_list: TodoListEntity | None = None
|
|
|
|
# Find matching list
|
|
match_constraints = intent.MatchTargetsConstraints(
|
|
name=list_name, domains=[DOMAIN], assistant=intent_obj.assistant
|
|
)
|
|
match_result = intent.async_match_targets(hass, match_constraints)
|
|
if not match_result.is_match:
|
|
raise intent.MatchFailedError(
|
|
result=match_result, constraints=match_constraints
|
|
)
|
|
|
|
target_list = hass.data[DATA_COMPONENT].get_entity(
|
|
match_result.states[0].entity_id
|
|
)
|
|
if target_list is None:
|
|
raise intent.IntentHandleError(
|
|
f"No to-do list: {list_name}", "list_not_found"
|
|
)
|
|
|
|
# Find item in list
|
|
matching_item = None
|
|
for todo_item in target_list.todo_items or ():
|
|
if (
|
|
item in (todo_item.uid, todo_item.summary)
|
|
and todo_item.status == TodoItemStatus.NEEDS_ACTION
|
|
):
|
|
matching_item = todo_item
|
|
break
|
|
if not matching_item or not matching_item.uid:
|
|
raise intent.IntentHandleError(
|
|
f"Item '{item}' not found on list", "item_not_found"
|
|
)
|
|
|
|
# Mark as completed
|
|
await target_list.async_update_todo_item(
|
|
TodoItem(
|
|
uid=matching_item.uid,
|
|
summary=matching_item.summary,
|
|
status=TodoItemStatus.COMPLETED,
|
|
)
|
|
)
|
|
|
|
response: intent.IntentResponse = intent_obj.create_response()
|
|
response.response_type = intent.IntentResponseType.ACTION_DONE
|
|
response.async_set_results(
|
|
[
|
|
intent.IntentResponseTarget(
|
|
type=intent.IntentResponseTargetType.ENTITY,
|
|
name=list_name,
|
|
id=match_result.states[0].entity_id,
|
|
)
|
|
]
|
|
)
|
|
return response
|