1
mirror of https://github.com/home-assistant/core synced 2024-08-28 03:36:46 +02:00
ha-core/homeassistant/components/picnic/services.py
2023-11-27 13:13:02 +01:00

96 lines
2.9 KiB
Python

"""Services for the Picnic integration."""
from __future__ import annotations
from typing import cast
from python_picnic_api import PicnicAPI
import voluptuous as vol
from homeassistant.core import HomeAssistant, ServiceCall
import homeassistant.helpers.config_validation as cv
from .const import (
ATTR_AMOUNT,
ATTR_CONFIG_ENTRY_ID,
ATTR_PRODUCT_ID,
ATTR_PRODUCT_IDENTIFIERS,
ATTR_PRODUCT_NAME,
CONF_API,
DOMAIN,
SERVICE_ADD_PRODUCT_TO_CART,
)
class PicnicServiceException(Exception):
"""Exception for Picnic services."""
async def async_register_services(hass: HomeAssistant) -> None:
"""Register services for the Picnic integration, if not registered yet."""
if hass.services.has_service(DOMAIN, SERVICE_ADD_PRODUCT_TO_CART):
return
async def async_add_product_service(call: ServiceCall):
api_client = await get_api_client(hass, call.data[ATTR_CONFIG_ENTRY_ID])
await handle_add_product(hass, api_client, call)
hass.services.async_register(
DOMAIN,
SERVICE_ADD_PRODUCT_TO_CART,
async_add_product_service,
schema=vol.Schema(
{
vol.Required(ATTR_CONFIG_ENTRY_ID): cv.string,
vol.Exclusive(
ATTR_PRODUCT_ID, ATTR_PRODUCT_IDENTIFIERS
): cv.positive_int,
vol.Exclusive(ATTR_PRODUCT_NAME, ATTR_PRODUCT_IDENTIFIERS): cv.string,
vol.Optional(ATTR_AMOUNT): vol.All(vol.Coerce(int), vol.Range(min=1)),
}
),
)
async def get_api_client(hass: HomeAssistant, config_entry_id: str) -> PicnicAPI:
"""Get the right Picnic API client based on the device id, else get the default one."""
if config_entry_id not in hass.data[DOMAIN]:
raise ValueError(f"Config entry with id {config_entry_id} not found!")
return hass.data[DOMAIN][config_entry_id][CONF_API]
async def handle_add_product(
hass: HomeAssistant, api_client: PicnicAPI, call: ServiceCall
) -> None:
"""Handle the call for the add_product service."""
product_id = call.data.get("product_id")
if not product_id:
product_id = await hass.async_add_executor_job(
product_search, api_client, cast(str, call.data["product_name"])
)
if not product_id:
raise PicnicServiceException("No product found or no product ID given!")
await hass.async_add_executor_job(
api_client.add_product, str(product_id), call.data.get("amount", 1)
)
def product_search(api_client: PicnicAPI, product_name: str | None) -> None | str:
"""Query the api client for the product name."""
if product_name is None:
return None
search_result = api_client.search(product_name)
if not search_result or "items" not in search_result[0]:
return None
# Return the first valid result
for item in search_result[0]["items"]:
if "name" in item:
return str(item["id"])
return None