add upload_file action

This commit is contained in:
mib1185
2025-06-22 09:43:12 +00:00
parent 9ee45518e9
commit b38fcf3100
8 changed files with 180 additions and 3 deletions

View File

@@ -16,13 +16,25 @@ from homeassistant.const import (
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.typing import ConfigType
from .const import DOMAIN
from .coordinator import ImmichConfigEntry, ImmichDataUpdateCoordinator from .coordinator import ImmichConfigEntry, ImmichDataUpdateCoordinator
from .services import async_setup_services
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
PLATFORMS: list[Platform] = [Platform.SENSOR] PLATFORMS: list[Platform] = [Platform.SENSOR]
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up immich integration."""
await async_setup_services(hass)
return True
async def async_setup_entry(hass: HomeAssistant, entry: ImmichConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ImmichConfigEntry) -> bool:
"""Set up Immich from a config entry.""" """Set up Immich from a config entry."""
@@ -33,6 +45,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ImmichConfigEntry) -> bo
entry.data[CONF_HOST], entry.data[CONF_HOST],
entry.data[CONF_PORT], entry.data[CONF_PORT],
entry.data[CONF_SSL], entry.data[CONF_SSL],
"home-assistant",
) )
try: try:

View File

@@ -11,5 +11,10 @@
"default": "mdi:file-video" "default": "mdi:file-video"
} }
} }
},
"services": {
"upload_file": {
"service": "mdi:upload"
}
} }
} }

View File

@@ -8,5 +8,5 @@
"iot_class": "local_polling", "iot_class": "local_polling",
"loggers": ["aioimmich"], "loggers": ["aioimmich"],
"quality_scale": "silver", "quality_scale": "silver",
"requirements": ["aioimmich==0.9.1"] "requirements": ["aioimmich==0.10.1"]
} }

View File

@@ -0,0 +1,107 @@
"""Services for the Immich integration."""
import logging
import os.path
from aioimmich.exceptions import ImmichError
import voluptuous as vol
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import ServiceValidationError
from .const import DOMAIN
from .coordinator import ImmichDataUpdateCoordinator
_LOGGER = logging.getLogger(__name__)
SERVICE_UPLOAD_FILE = "upload_file"
SERVICE_SCHEMA_UPLOAD_FILE = vol.Schema(
{
vol.Required("config_entry_id"): str,
vol.Required("file"): str,
vol.Optional("album_id"): str,
}
)
async def _async_upload_file(service_call: ServiceCall) -> None:
"""Call immich upload file service."""
_LOGGER.debug(
"Executing service %s with arguments %s",
service_call.service,
service_call.data,
)
hass = service_call.hass
target_entry = hass.config_entries.async_get_entry(
service_call.data["config_entry_id"]
)
target_file = service_call.data["file"]
if not target_entry:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="config_entry_not_found",
translation_placeholders={"service": service_call.service},
)
if target_entry.state is not ConfigEntryState.LOADED:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="config_entry_not_loaded",
translation_placeholders={"service": service_call.service},
)
if not os.path.isfile(target_file):
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="file_not_found",
translation_placeholders={
"service": service_call.service,
"file": target_file,
},
)
coordinator: ImmichDataUpdateCoordinator = target_entry.runtime_data
if target_album := service_call.data.get("album_id"):
try:
await coordinator.api.albums.async_get_album_info(target_album, True)
except ImmichError as ex:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="album_not_found",
translation_placeholders={
"service": service_call.service,
"album_id": target_album,
"error": str(ex),
},
) from ex
try:
upload_result = await coordinator.api.assets.async_upload_asset(target_file)
if target_album:
await coordinator.api.albums.async_add_assets_to_album(
target_album, [upload_result.asset_id]
)
except ImmichError as ex:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="upload_failed",
translation_placeholders={
"service": service_call.service,
"file": target_file,
"error": str(ex),
},
) from ex
async def async_setup_services(hass: HomeAssistant) -> None:
"""Set up services for immich integration."""
hass.services.async_register(
DOMAIN,
SERVICE_UPLOAD_FILE,
_async_upload_file,
SERVICE_SCHEMA_UPLOAD_FILE,
)

View File

@@ -0,0 +1,15 @@
upload_file:
fields:
config_entry_id:
required: true
selector:
config_entry:
integration: immich
file:
required: true
selector:
text:
album_id:
required: false
selector:
text:

View File

@@ -69,5 +69,42 @@
"name": "Disk used by videos" "name": "Disk used by videos"
} }
} }
},
"services": {
"upload_file": {
"name": "Upload file",
"description": "Upload a file to your Immich instance.",
"fields": {
"config_entry_id": {
"name": "Immich instance",
"description": "Select the Immich instance where to upload the file."
},
"file": {
"name": "File",
"description": "The path to the file to be uploaded."
},
"album_id": {
"name": "Album id",
"description": "The album where to put the file in after upload."
}
}
}
},
"exceptions": {
"config_entry_not_found": {
"message": "Failed to perform action \"{service}\". Config entry not found"
},
"config_entry_not_loaded": {
"message": "Failed to perform action \"{service}\". Config entry not loaded."
},
"file_not_found": {
"message": "Failed to perform action \"{service}\". File `{file}` not found."
},
"album_not_found": {
"message": "Failed to perform action \"{service}\". Album with id `{album_id}` not found ({error})."
},
"upload_failed": {
"message": "Failed to perform action \"{service}\". Upload of file `{file}` failed ({error})."
}
} }
} }

2
requirements_all.txt generated
View File

@@ -280,7 +280,7 @@ aiohue==4.7.4
aioimaplib==2.0.1 aioimaplib==2.0.1
# homeassistant.components.immich # homeassistant.components.immich
aioimmich==0.9.1 aioimmich==0.10.1
# homeassistant.components.apache_kafka # homeassistant.components.apache_kafka
aiokafka==0.10.0 aiokafka==0.10.0

View File

@@ -265,7 +265,7 @@ aiohue==4.7.4
aioimaplib==2.0.1 aioimaplib==2.0.1
# homeassistant.components.immich # homeassistant.components.immich
aioimmich==0.9.1 aioimmich==0.10.1
# homeassistant.components.apache_kafka # homeassistant.components.apache_kafka
aiokafka==0.10.0 aiokafka==0.10.0