1 """Expose Synology DSM as a media source."""
3 from __future__
import annotations
7 from aiohttp
import web
8 from synology_dsm.api.photos
import SynoPhotosAlbum, SynoPhotosItem
9 from synology_dsm.exceptions
import SynologyDSMException
24 from .const
import DOMAIN, SHARED_SUFFIX
25 from .models
import SynologyDSMData
29 """Set up Synology media source."""
30 entries = hass.config_entries.async_entries(
31 DOMAIN, include_disabled=
False, include_ignore=
False
38 """Synology Photos item identifier."""
41 """Split identifier into parts."""
42 parts = identifier.split(
"/")
54 album_parts = parts[1].split(
"_")
55 self.
album_idalbum_id = album_parts[0]
56 if len(album_parts) > 1:
57 self.
passphrasepassphrase = parts[1].replace(f
"{self.album_id}_",
"")
64 if self.
file_namefile_name.endswith(SHARED_SUFFIX):
70 """Provide Synology Photos as media sources."""
72 name =
"Synology Photos"
74 def __init__(self, hass: HomeAssistant, entries: list[ConfigEntry]) ->
None:
75 """Initialize Synology source."""
82 item: MediaSourceItem,
83 ) -> BrowseMediaSource:
85 if not self.
hasshass.data.get(DOMAIN):
90 media_class=MediaClass.DIRECTORY,
91 media_content_type=MediaClass.IMAGE,
92 title=
"Synology Photos",
95 children_media_class=MediaClass.DIRECTORY,
102 self, item: MediaSourceItem
103 ) -> list[BrowseMediaSource]:
104 """Handle browsing different diskstations."""
105 if not item.identifier:
109 identifier=entry.unique_id,
110 media_class=MediaClass.DIRECTORY,
111 media_content_type=MediaClass.IMAGE,
112 title=f
"{entry.title} - {entry.unique_id}",
116 for entry
in self.
entriesentries
119 diskstation: SynologyDSMData = self.
hasshass.data[DOMAIN][identifier.unique_id]
120 assert diskstation.api.photos
is not None
122 if identifier.album_id
is None:
125 albums = await diskstation.api.photos.get_albums()
126 except SynologyDSMException:
128 assert albums
is not None
133 identifier=f
"{item.identifier}/0",
134 media_class=MediaClass.DIRECTORY,
135 media_content_type=MediaClass.IMAGE,
144 identifier=f
"{item.identifier}/{album.album_id}_{album.passphrase}",
145 media_class=MediaClass.DIRECTORY,
146 media_content_type=MediaClass.IMAGE,
158 album = SynoPhotosAlbum(
int(identifier.album_id),
"", 0, identifier.passphrase)
160 album_items = await diskstation.api.photos.get_items_from_album(
163 except SynologyDSMException:
165 assert album_items
is not None
168 for album_item
in album_items:
169 mime_type, _ = mimetypes.guess_type(album_item.file_name)
170 if isinstance(mime_type, str)
and mime_type.startswith(
"image/"):
172 album_item.thumbnail_size =
"sm"
174 if album_item.is_shared:
175 suffix = SHARED_SUFFIX
180 f
"{identifier.unique_id}/"
181 f
"{identifier.album_id}_{identifier.passphrase}/"
182 f
"{album_item.thumbnail_cache_key}/"
183 f
"{album_item.file_name}{suffix}"
185 media_class=MediaClass.IMAGE,
186 media_content_type=mime_type,
187 title=album_item.file_name,
191 album_item, diskstation
198 """Resolve media to a url."""
200 if identifier.album_id
is None:
202 if identifier.file_name
is None:
204 mime_type, _ = mimetypes.guess_type(identifier.file_name)
205 if not isinstance(mime_type, str):
208 if identifier.is_shared:
209 suffix = SHARED_SUFFIX
212 f
"/synology_dsm/{identifier.unique_id}/"
213 f
"{identifier.cache_key}/"
214 f
"{identifier.file_name}{suffix}/"
215 f
"{identifier.passphrase}"
221 self, item: SynoPhotosItem, diskstation: SynologyDSMData
224 assert diskstation.api.photos
is not None
227 thumbnail = await diskstation.api.photos.get_item_thumbnail_url(item)
228 except SynologyDSMException:
230 return str(thumbnail)
234 """Synology Media Finder View."""
236 url =
"/synology_dsm/{source_dir_id}/{location:.*}"
237 name =
"synology_dsm"
240 """Initialize the media view."""
244 self, request: web.Request, source_dir_id: str, location: str
246 """Start a GET request."""
247 if not self.
hasshass.data.get(DOMAIN):
248 raise web.HTTPNotFound
250 cache_key, file_name, passphrase = location.split(
"/")
251 image_id =
int(cache_key.split(
"_")[0])
253 if shared := file_name.endswith(SHARED_SUFFIX):
254 file_name = file_name.removesuffix(SHARED_SUFFIX)
256 mime_type, _ = mimetypes.guess_type(file_name)
257 if not isinstance(mime_type, str):
258 raise web.HTTPNotFound
260 diskstation: SynologyDSMData = self.
hasshass.data[DOMAIN][source_dir_id]
261 assert diskstation.api.photos
is not None
262 item = SynoPhotosItem(image_id,
"",
"",
"", cache_key,
"xl", shared, passphrase)
265 image = await diskstation.api.photos.download_item_thumbnail(item)
267 image = await diskstation.api.photos.download_item(item)
268 except SynologyDSMException
as exc:
269 raise web.HTTPNotFound
from exc
270 return web.Response(body=image, content_type=mime_type)