Closed DocGun812 closed 3 weeks ago
I like to live dangerously too and update Immich asap. Can confirm that the Immich integration now complains about a (500) internal server error.
See here. In short hub.py needs updating (and HA restarting). https://github.com/outadoc/immich-home-assistant/issues/8
Pending pull request if you wish to update the files yourself. https://github.com/outadoc/immich-home-assistant/pull/9
Edit: After another go around, and restarted HA and reloaded Integration a few times, I've managed to get specific album to start showing up, in my case an album called 2023. However, my random "Favorite" is still not showing up.
@LZStealth Thank you for the tip and I have followed your instructions and was able to get pass the internal 500 error and able to reconfigure Immich however, it's not showing any photos. Here's my edited version of the hub.py and I think it's identical to yours
"""Hub for Immich integration."""
from __future__ import annotations
import logging
from urllib.parse import urljoin
import aiohttp
from homeassistant.exceptions import HomeAssistantError
_HEADER_API_KEY = "x-api-key"
_LOGGER = logging.getLogger(__name__)
_ALLOWED_MIME_TYPES = ["image/png", "image/jpeg"]
class ImmichHub:
"""Immich API hub."""
def __init__(self, host: str, api_key: str) -> None:
"""Initialize."""
self.host = host
self.api_key = api_key
async def authenticate(self) -> bool:
"""Test if we can authenticate with the host."""
try:
async with aiohttp.ClientSession() as session:
url = urljoin(self.host, "/api/auth/validateToken")
headers = {"Accept": "application/json", _HEADER_API_KEY: self.api_key}
async with session.post(url=url, headers=headers) as response:
if response.status != 200:
raw_result = await response.text()
_LOGGER.error("Error from API: body=%s", raw_result)
return False
auth_result = await response.json()
if not auth_result.get("authStatus"):
raw_result = await response.text()
_LOGGER.error("Error from API: body=%s", raw_result)
return False
return True
except aiohttp.ClientError as exception:
_LOGGER.error("Error connecting to the API: %s", exception)
raise CannotConnect from exception
async def get_my_user_info(self) -> dict:
"""Get user info."""
try:
async with aiohttp.ClientSession() as session:
url = urljoin(self.host, "/api/users/me")
headers = {"Accept": "application/json", _HEADER_API_KEY: self.api_key}
async with session.get(url=url, headers=headers) as response:
if response.status != 200:
raw_result = await response.text()
_LOGGER.error("Error from API: body=%s", raw_result)
raise ApiError()
user_info: dict = await response.json()
return user_info
except aiohttp.ClientError as exception:
_LOGGER.error("Error connecting to the API: %s", exception)
raise CannotConnect from exception
async def download_asset(self, asset_id: str) -> bytes | None:
"""Download the asset."""
try:
async with aiohttp.ClientSession() as session:
url = urljoin(self.host, f"/api/assets/{asset_id}/original")
headers = {_HEADER_API_KEY: self.api_key}
async with session.get(url=url, headers=headers) as response:
if response.status != 200:
_LOGGER.error("Error from API: status=%d", response.status)
return None
if response.content_type not in _ALLOWED_MIME_TYPES:
_LOGGER.error(
"MIME type is not supported: %s", response.content_type
)
return None
return await response.read()
except aiohttp.ClientError as exception:
_LOGGER.error("Error connecting to the API: %s", exception)
raise CannotConnect from exception
async def list_favorite_images(self) -> list[dict]:
"""List all favorite images."""
try:
async with aiohttp.ClientSession() as session:
url = urljoin(self.host, "/api/search/metadata")
headers = {"Accept": "application/json", _HEADER_API_KEY: self.api_key}
data = {"isFavorite": "true"}
async with session.post(url=url, headers=headers, data=data) as response:
if response.status != 200:
raw_result = await response.text()
_LOGGER.error("Error from API: body=%s", raw_result)
raise ApiError()
assets: list[dict] = await response.json()
filtered_assets: list[dict] = [
asset for asset in assets if asset["type"] == "IMAGE"
]
return filtered_assets
except aiohttp.ClientError as exception:
_LOGGER.error("Error connecting to the API: %s", exception)
raise CannotConnect from exception
async def list_all_albums(self) -> list[dict]:
"""List all albums."""
try:
async with aiohttp.ClientSession() as session:
url = urljoin(self.host, "/api/albums")
headers = {"Accept": "application/json", _HEADER_API_KEY: self.api_key}
async with session.get(url=url, headers=headers) as response:
if response.status != 200:
raw_result = await response.text()
_LOGGER.error("Error from API: body=%s", raw_result)
raise ApiError()
album_list: list[dict] = await response.json()
return album_list
except aiohttp.ClientError as exception:
_LOGGER.error("Error connecting to the API: %s", exception)
raise CannotConnect from exception
async def list_album_images(self, album_id: str) -> list[dict]:
"""List all images in an album."""
try:
async with aiohttp.ClientSession() as session:
url = urljoin(self.host, f"/api/albums/{album_id}")
headers = {"Accept": "application/json", _HEADER_API_KEY: self.api_key}
async with session.get(url=url, headers=headers) as response:
if response.status != 200:
raw_result = await response.text()
_LOGGER.error("Error from API: body=%s", raw_result)
raise ApiError()
album_info: dict = await response.json()
assets: list[dict] = album_info["assets"]
filtered_assets: list[dict] = [
asset for asset in assets if asset["type"] == "IMAGE"
]
return filtered_assets
except aiohttp.ClientError as exception:
_LOGGER.error("Error connecting to the API: %s", exception)
raise CannotConnect from exception
class CannotConnect(HomeAssistantError):
"""Error to indicate we cannot connect."""
class InvalidAuth(HomeAssistantError):
"""Error to indicate there is invalid auth."""
class ApiError(HomeAssistantError):
"""Error to indicate that the API returned an error."""
Images also needed this section changing (should be around like 107)
assets: list[dict] = await response.json()
to this
favorites = await response.json()
assets: list[dict] = favorites["assets"]["items"]
File is here with the changes if that helps. https://github.com/LZStealth/immich-home-assistant/blob/API-Changes-v1.160.1/custom_components/immich/hub.py
as the format of the response has changed. Mainly due to the old query no longer responding. This is because favourites don't appear to be callable in the same way that albums are.
Otherwise on a quick glance that looks fine to me.
@LZStealth you're awesome, that solved it.
Should be fixed by #9 and the new update (check HACS). Thanks again @LZStealth! And thank you all for your reports, sorry I noticed the issue a bit late.
Since the new Immich v1.106.4 the changes to underlying API changes, the integration can no longer access Immich server with API key.