@@ -154,14 +154,16 @@ class PhotoLibrary(object):
154154 },
155155 }
156156
157- def __init__ (self , service : "PhotosService" , zone_id : Dict [str , Any ]):
157+ def __init__ (self , service : "PhotosService" , zone_id : Dict [str , Any ], library_type : str ):
158158 self .service = service
159159 self .zone_id = zone_id
160+ self .library_type = library_type
161+ self .service_endpoint = self .service .get_service_endpoint (library_type )
160162
161163 self ._albums : Optional [Dict [str , PhotoAlbum ]] = None
162164
163165 url = ('%s/records/query?%s' %
164- (self .service . _service_endpoint , urlencode (self .service .params )))
166+ (self .service_endpoint , urlencode (self .service .params )))
165167 json_data = json .dumps ({
166168 "query" : {"recordType" :"CheckIndexingState" },
167169 "zoneID" : self .zone_id ,
@@ -183,7 +185,7 @@ def __init__(self, service: "PhotosService", zone_id: Dict[str, Any]):
183185 def albums (self ) -> Dict [str , "PhotoAlbum" ]:
184186 if not self ._albums :
185187 self ._albums = {
186- name : PhotoAlbum (self .service , name , zone_id = self .zone_id , ** props ) # type: ignore[arg-type] # dynamically builing params
188+ name : PhotoAlbum (self .service , self . service_endpoint , name , zone_id = self .zone_id , ** props ) # type: ignore[arg-type] # dynamically builing params
187189 for (name , props ) in self .SMART_FOLDERS .items ()
188190 }
189191
@@ -209,7 +211,7 @@ def albums(self) -> Dict[str, "PhotoAlbum"]:
209211 }
210212 }]
211213
212- album = PhotoAlbum (self .service , folder_name ,
214+ album = PhotoAlbum (self .service , self . service_endpoint , folder_name ,
213215 'CPLContainerRelationLiveByAssetDate' ,
214216 folder_obj_type , 'ASCENDING' , query_filter ,
215217 zone_id = self .zone_id )
@@ -218,8 +220,10 @@ def albums(self) -> Dict[str, "PhotoAlbum"]:
218220 return self ._albums
219221
220222 def _fetch_folders (self ) -> Sequence [Dict [str , Any ]]:
223+ if self .library_type == "shared" :
224+ return []
221225 url = ('%s/records/query?%s' %
222- (self .service . _service_endpoint , urlencode (self .service .params )))
226+ (self .service_endpoint , urlencode (self .service .params )))
223227 json_data = json .dumps ({
224228 "query" : {"recordType" :"CPLAlbumByPositionLive" },
225229 "zoneID" : self .zone_id ,
@@ -256,11 +260,9 @@ def __init__(
256260 self .session = session
257261 self .params = dict (params )
258262 self ._service_root = service_root
259- self ._service_endpoint = \
260- ('%s/database/1/com.apple.photos.cloud/production/private'
261- % self ._service_root )
262263
263- self ._libraries : Optional [Dict [str , PhotoLibrary ]] = None
264+ self ._private_libraries : Optional [Dict [str , PhotoLibrary ]] = None
265+ self ._shared_libraries : Optional [Dict [str , PhotoLibrary ]] = None
264266
265267 self .filename_cleaner = filename_cleaner
266268 self .lp_filename_generator = lp_filename_generator
@@ -281,46 +283,59 @@ def __init__(
281283 # self._photo_assets = {}
282284
283285 super (PhotosService , self ).__init__ (
284- service = self , zone_id = {u'zoneName' : u'PrimarySync' })
286+ service = self , zone_id = {u'zoneName' : u'PrimarySync' }, library_type = "private" )
285287
286288 @property
287- def libraries (self ) -> Dict [str , PhotoLibrary ]:
288- if not self ._libraries :
289- try :
290- url = ('%s/zones/list' %
291- (self ._service_endpoint , ))
292- request = self .session .post (
293- url ,
294- data = '{}' ,
295- headers = {'Content-type' : 'text/plain' }
296- )
297- response = request .json ()
298- zones = response ['zones' ]
299- except Exception as e :
300- logger .error ("library exception: %s" % str (e ))
289+ def private_libraries (self ) -> Dict [str , PhotoLibrary ]:
290+ if not self ._private_libraries :
291+ self ._private_libraries = self ._fetch_libraries ("private" )
292+
293+ return self ._private_libraries
294+
295+ @property
296+ def shared_libraries (self ) -> Dict [str , PhotoLibrary ]:
297+ if not self ._shared_libraries :
298+ self ._shared_libraries = self ._fetch_libraries ("shared" )
299+
300+ return self ._shared_libraries
301301
302+ def _fetch_libraries (self , library_type : str ) -> Dict [str , PhotoLibrary ]:
303+ try :
302304 libraries = {}
303- for zone in zones :
305+ service_endpoint = self .get_service_endpoint (library_type )
306+ url = ('%s/zones/list' %
307+ (service_endpoint , ))
308+ request = self .session .post (
309+ url ,
310+ data = '{}' ,
311+ headers = {'Content-type' : 'text/plain' }
312+ )
313+ response = request .json ()
314+ for zone in response ['zones' ]:
304315 if not zone .get ('deleted' ):
305316 zone_name = zone ['zoneID' ]['zoneName' ]
306317 libraries [zone_name ] = PhotoLibrary (
307- self , zone_id = zone ['zoneID' ])
318+ self , zone_id = zone ['zoneID' ], library_type = library_type )
308319 # obj_type='CPLAssetByAssetDateWithoutHiddenOrDeleted',
309320 # list_type="CPLAssetAndMasterByAssetDateWithoutHiddenOrDeleted",
310321 # direction="ASCENDING", query_filter=None,
311322 # zone_id=zone['zoneID'])
323+ except Exception as e :
324+ logger .error ("library exception: %s" % str (e ))
325+ return libraries
312326
313- self . _libraries = libraries
314-
315- return self ._libraries
327+ def get_service_endpoint ( self , library_type : str ) -> str :
328+ return ( '%s/database/1/com.apple.photos.cloud/production/%s'
329+ % ( self ._service_root , library_type ))
316330
317331
318332class PhotoAlbum (object ):
319333
320- def __init__ (self , service :PhotosService , name : str , list_type : str , obj_type : str , direction : str ,
334+ def __init__ (self , service :PhotosService , service_endpoint : str , name : str , list_type : str , obj_type : str , direction : str ,
321335 query_filter :Optional [Sequence [Dict [str , Any ]]]= None , page_size :int = 100 , zone_id :Optional [Dict [str , Any ]]= None ):
322336 self .name = name
323337 self .service = service
338+ self .service_endpoint = service_endpoint
324339 self .list_type = list_type
325340 self .obj_type = obj_type
326341 self .direction = direction
@@ -345,7 +360,7 @@ def __iter__(self) -> Generator["PhotoAsset", Any, None]:
345360 def __len__ (self ) -> int :
346361 if self ._len is None :
347362 url = ('%s/internal/records/query/batch?%s' %
348- (self .service . _service_endpoint ,
363+ (self .service_endpoint ,
349364 urlencode (self .service .params )))
350365 request = self .service .session .post (
351366 url ,
@@ -362,7 +377,7 @@ def __len__(self) -> int:
362377 # Perform the request in a separate method so that we
363378 # can mock it to test session errors.
364379 def photos_request (self , offset : int ) -> Response :
365- url = ('%s/records/query?' % self .service . _service_endpoint ) + \
380+ url = ('%s/records/query?' % self .service_endpoint ) + \
366381 urlencode (self .service .params )
367382 return self .service .session .post (
368383 url ,
@@ -397,7 +412,7 @@ def photos(self) -> Generator["PhotoAsset", Any, None]:
397412
398413 exception_retries = 0
399414
400- # url = ('%s/records/query?' % self.service._service_endpoint ) + \
415+ # url = ('%s/records/query?' % self.service_endpoint ) + \
401416# urlencode(self.service.params)
402417# request = self.service.session.post(
403418# url,
0 commit comments