o
    l>jC                    @  s  d Z ddlmZ ddlZddlZddlZddlmZmZ ddl	m	Z	m
Z
 ddlmZmZmZmZmZmZ ddlmZ ddlmZ dd	lmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z" dd
l#m$Z$ ddl%m&Z&m'Z' ddl(m)Z)m*Z*m+Z+ ddl,m-Z- ddl.m/Z/ ddl0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7 ddl8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@ ddlAmBZBmCZCmDZDmEZEmFZF ddlGmHZHmIZImJZJmKZKmLZLmMZM ddlNmOZOmPZPmQZQmRZR eSeTZUdZVdKddZWdLddZXdddddMd+d,ZYg d-ZZdNd1d2Z[dOd4d5Z\dPd7d8Z]G d9d: d:eZ^G d;d< d<eZ_G d=d> d>e_Z`G d?d@ d@eeZaG dAdB dBeaZbG dCdD dDebZcG dEdF dFebZdG dGdH dHZeG dIdJ dJe-ZfdS )Qz.Modern Photos CloudKit service implementation.    )annotationsN)ABCabstractmethod)datetimetimezone)Any	GeneratorIterableIteratorOptionalcast)Mock)	urlencode)CKErrorItem
CKFVStringCKModifyOperationCKQueryFilterByCKQueryObjectCKQueryRequestCKRecordCKTombstoneRecordCKWriteRecordCKZoneChangesZoneReqCKZoneIDCKZoneIDReq)CloudKitApiError)CONTENT_TYPECONTENT_TYPE_TEXT)PyiCloudAPIResponseExceptionPyiCloudException$PyiCloudServiceNotActivatedException)BaseService   )PhotosCloudKitClient)PRIMARY_ZONE%SUPPORTED_SHARED_LIBRARY_SMART_ALBUMSAlbumTypeEnumDirectionEnumListTypeEnumObjectTypeEnumSmartAlbumEnum)build_photo_resourcedecode_encrypted_textmaster_asset_pairsrecord_change_tagrecord_field_valuerecord_namerecord_record_typerecord_zone)PhotoChangeEventPhotoResourcePhotosServiceExceptionPhotosUploadResponseSmartAlbumSpec)album_querycheck_indexing_state_query
list_queryparent_filterphoto_lookup_querysmart_album_filter)PhotoSyncOptionsPhotoSyncResultrun_photo_syncwatch_photo_synczSharedSync-returnintc                   C  s   t tjtjd d S )zAReturn a fresh positive position for newly created album records.)tzi  )rC   r   nowr   utc	timestamp rH   rH   ^/home/thesage/.local/lib/python3.10/site-packages/pyicloud/services/photos_cloudkit/service.py_new_album_positionO   s   rJ   record_name_valuestrr   c                 C  s   t ddtd| ddS )z+Return a typed record-name equality filter.EQUALS
recordNameSTRINGtypevalue)
comparator	fieldName
fieldValue)r   r   )rK   rH   rH   rI   _record_name_filterU   s
   
rV   )desired_keysresults_limitcontinuationqueryr   zone_iddict[str, str]rW   list[str] | NonerX   
int | NonerY   
str | Nonedict[str, Any]c                 C  s&   t | tdi ||||djdddS )z@Serialize a typed CloudKit query request for legacy/raw callers.)rZ   zoneIDdesiredKeysresultsLimitcontinuationMarkerjsonTmodeexclude_noneNrH   )r   r   
model_dump)rZ   r[   rW   rX   rY   rH   rH   rI   _query_request_payload_   s   
rj   )aresJPEGFullWidthresJPEGFullHeightresJPEGFullFileTyperesJPEGFullFingerprintresJPEGFullResresJPEGLargeWidthresJPEGLargeHeightresJPEGLargeFileTyperesJPEGLargeFingerprintresJPEGLargeResresJPEGMedWidthresJPEGMedHeightresJPEGMedFileTyperesJPEGMedFingerprintresJPEGMedResresJPEGThumbWidthresJPEGThumbHeightresJPEGThumbFileTyperesJPEGThumbFingerprintresJPEGThumbResresVidFullWidthresVidFullHeightresVidFullFileTyperesVidFullFingerprintresVidFullResresVidMedWidthresVidMedHeightresVidMedFileTyperesVidMedFingerprintresVidMedResresVidSmallWidthresVidSmallHeightresVidSmallFileTyperesVidSmallFingerprintresVidSmallResresSidecarWidthresSidecarHeightresSidecarFileTyperesSidecarFingerprintresSidecarResitemTypedataClassTypefilenameEncoriginalOrientationresOriginalWidthresOriginalHeightresOriginalFileTyperesOriginalFingerprintresOriginalResresOriginalAltWidthresOriginalAltHeightresOriginalAltFileTyperesOriginalAltFingerprintresOriginalAltResresOriginalVidComplWidthresOriginalVidComplHeightresOriginalVidComplFileTyperesOriginalVidComplFingerprintresOriginalVidComplRes	isDeleted
isExpungeddateExpungedremappedRefrN   
recordTyperecordChangeTag	masterRefadjustmentRenderType	assetDate	addedDate
isFavoriteisHiddenorientationdurationassetSubtypeassetSubtypeV2assetHDRType
burstFlagsburstFlagsExtburstId
captionEnclocationEnclocationV2EnclocationLatitudelocationLongitudeadjustmentTypetimeZoneOffsetvidComplDurValuevidComplDurScalevidComplDispValuevidComplDispScalevidComplVisibilityStatecustomRenderedValuecontainerIditemIdposition
isKeyAssetrR   r   boolc                 C  s
   t | tS N)
isinstancer   )rR   rH   rH   rI   _is_mock_like      
r   sessionc                 C  s
   t |  S r   )r   )r   rH   rH   rI   _can_use_typed_cloudkit   r   r   	zone_namec                 C  s   t | o| tS r   )r   
startswithSHARED_LIBRARY_ZONE_PREFIX)r   rH   rH   rI   _is_shared_library_zone_name   s   r   c                   @  sz   e Zd ZdZd)d*ddZd+d
dZd,ddZd-ddZd.ddZd/ddZ		d)d0ddZ
d1d!d"Zd2d$d%Zd3d'd(ZdS )4AlbumContainerzContainer for photo albums.Nalbumslist['BasePhotoAlbum'] | NonerB   Nonec                 C  s4   i | _ |r|D ]}|| j |j< qt| j  | _d S r   _albumsidlistkeys_indexselfr   albumrH   rH   rI   __init__   s
   zAlbumContainer.__init__rC   c                 C  
   t | jS r   )lenr   r   rH   rH   rI   __len__   r   zAlbumContainer.__len__key	str | int'BasePhotoAlbum'c                 C  sR   t |tr| j| j|  S || jv r| j| S | |}|d ur"|S td| )NzPhoto album does not exist: )r   rC   r   r   findKeyError)r   r   r   rH   rH   rI   __getitem__   s   



zAlbumContainer.__getitem__Iterator['BasePhotoAlbum']c                 C  s   t | j S r   )iterr   valuesr   rH   rH   rI   __iter__      zAlbumContainer.__iter__namerL   r   c                 C     |  |d uS r   )r   )r   r   rH   rH   rI   __contains__   r   zAlbumContainer.__contains__Optional['BasePhotoAlbum']c                 C  s0   | j  D ]}||jks||jkr|  S qd S r   )r   r   fullnamer   )r   r   r   rH   rH   rI   r      s
   zAlbumContainer.finddefault'BasePhotoAlbum | None'c                 C     | j ||S r   )r   get)r   r   r   rH   rH   rI   r        zAlbumContainer.getr   c                 C  s    || j |j< t| j  | _d S r   r   r   r   rH   rH   rI   append  s   zAlbumContainer.appendalbum_idc                 C  s"   | j |d  t| j  | _d S r   )r   popr   r   r   r   r   rH   rH   rI   remove  s   zAlbumContainer.removeidxc                 C  s.   |dk s|t | jkrtd| j| j|  S )Nr   zPhoto album index out of range)r   r   
IndexErrorr   )r   r  rH   rH   rI   index  s   zAlbumContainer.indexr   )r   r   rB   r   rB   rC   )r   r   rB   r   )rB   r   )r   rL   rB   r   )r   rL   rB   r   )r   rL   r   r   rB   r   )r   r   rB   r   r   rL   rB   r   )r  rC   rB   r   )__name__
__module____qualname____doc__r   r   r   r   r   r   r   r   r  r  rH   rH   rH   rI   r      s    





	

r   c                   @  s   e Zd ZdZddddddd8ddZd9ddZed:ddZed:ddZed;ddZ	d;ddZ
d<d"d#Zd=d%d&Zd>d(d)Zed;d*d+Zd?d/d0Zdd1d@d4d5ZdAd6d7ZdS )BBasePhotoLibraryz1Represents a single Photos CloudKit zone/library.Nprivate)
asset_typer[   client
upload_urlscopeservice'PhotosService'r  type['PhotoAsset'] | Noner[   dict[str, str] | Noner  PhotosCloudKitClient | Noner  r_   r  rL   rB   r   c                C  s   || _ |pt| _|pt| _|| _| jd u r.t|dr.tt|dd r.t	|j
|j|j|d| _d | _i | _|| _|| _d | _d | _t| j drS| j j
 dt| j j nd| _t|rft| jdkrfd| _d S |   d S )Nservice_endpointr   base_urlr   base_paramsr  /records/query? PhotoLibraryFINISHED)r  
PhotoAssetr  r$   r[   _clienthasattrr   getattrr#   r  r   paramsr   _pending_albums_upload_urlr  _indexing_state_current_sync_tokenr   urlr   rQ   r  _ensure_indexing_ready)r   r  r  r[   r  r  r  rH   rH   rI   r     s:   




zBasePhotoLibrary.__init__c                 C  s"  | j d ur@t| jjr@| j jt tdi | jdd}|j| _	d }|j
D ]}t|tr3|jd} nq$|d ur<t|nd | _nF| jjj| jddi| jdttid}| }t|r_d| _n|d	i gd
 di di d| _| jd u s~t| jrt| jrd| _| jdkrtdd S )Nr"   rZ   r[   rX   stater   CheckIndexingState)rZ   ra   r(  re   headersr  recordsr   fieldsrR   zNiCloud Photo Library not finished indexing. Please try again in a few minutes.rH   )r   r   r  r   rZ   r9   r   r[   	syncTokenr'  r/  r   r   r0  	get_valuerL   r&  postr(  r   r   re   r   r   r    )r   responser+  recordrequestrH   rH   rI   r)  G  sN   



z'BasePhotoLibrary._ensure_indexing_readyc                 C     | j S r   )r&  r   rH   rH   rI   indexing_states     zBasePhotoLibrary.indexing_statec                 C  r7  r   )r'  r   rH   rH   rI   current_sync_tokenw  r9  z#BasePhotoLibrary.current_sync_tokenr   c                 C  s    | j d u r| |  | _ | j S r   )r   _merge_pending_albums_get_albumsr   rH   rH   rI   r   {  s   
zBasePhotoLibrary.albumsc                 C  s   |  |  | _| jS r   )r;  r<  r   r   rH   rH   rI   refresh_albums  s   zBasePhotoLibrary.refresh_albumsr   'PhotoAlbum'c                 C  s*   || j |j< | jd ur| j| d S d S r   )r$  r   r   r   r   rH   rH   rI   _cache_created_album  s   
z%BasePhotoLibrary._cache_created_albumr   c                 C  s,   | j |d  | jd ur| j| d S d S r   )r$  r   r   r  r  rH   rH   rI   _remove_cached_album  s   
z%BasePhotoLibrary._remove_cached_albumr   c                 C  s.   | j  D ]}||jd u r|| q|S r   )r$  r   r   r   r   r   rH   rH   rI   r;    s
   
z&BasePhotoLibrary._merge_pending_albumsc                 C     t r   NotImplementedErrorr   rH   rH   rI   r<       zBasePhotoLibrary._get_albumsr4  dict[str, list[dict[str, Any]]]6tuple[dict[str, dict[str, Any]], list[dict[str, Any]]]c                 C  s^   i }g }|d D ]"}|d dkr|d d d d }|||< q|d dkr*| | q||fS )	z4Legacy helper preserved for older callers and tests.r/  r   CPLAssetr0  r   rR   rN   	CPLMaster)r   )r   r4  asset_recordsmaster_recordsr5  
master_refrH   rH   rI   parse_asset_response  s   

z%BasePhotoLibrary.parse_asset_responsesincerN  Iterator[PhotoChangeEvent]c             	   c  s    t tdi | j|dd}| jj|dD ]8}|j| _|jD ].}t|t	r1t
d|jd dd dV  qt|trLt
d|j|jt|j|jrG|jjnd dV  qqd S )	NF)ra   r1  reverse)zone_reqdeletedT)kindr0   record_typerR  modifiedupdatedrH   )r   r   r[   r   iter_changesr1  r'  r/  r   r   r3   rN   r   r   r   rR  rU  rG   )r   rN  rQ  zoner5  rH   rH   rI   rW    s8   



zBasePhotoLibrary.iter_changesc                 C  s   | j r| j S | jd ur,t| jjr,| j }|jD ]}|jj| j	d kr*|j
| _  nqn@| jj}t| jj}| d| }| jjj|i ttid }|dg D ]}|di }|d| j	d krk|d| _  nqQ| j sstd| j S )NzoneName/zones/list?re   r.  zonesra   r1  z)No sync token available for photo library)r'  r   r   r  r   
zones_listr\  ra   rY  r[   r1  r  r   r#  r3  r   r   re   r   r5   )r   r\  rX  endpointr#  r(  r4  r[   rH   rH   rI   sync_cursor  s:   

zBasePhotoLibrary.sync_cursor)r  r  r  r  r[   r  r  r  r  r_   r  rL   rB   r   )rB   r   )rB   r_   rB   r   )r   r>  rB   r   r  )r   r   rB   r   )r4  rE  rB   rF  rN  r_   rB   rO  rB   rL   )r  r	  r
  r  r   r)  propertyr8  r:  r   r=  r?  r@  r;  r   r<  rL  rW  r_  rH   rH   rH   rI   r    s0    
),




r  c                   @  s  e Zd ZU dZejeeje	j
ejdejeeje	jejedfdejeeje	jejedfdejeeje	jejedfdejeeje	jejdejeeje	jejedfdejeeje	jejedfdejeeje	jejed	fdejeeje	jejed
fdej eej!e	j!ejdej"eej"e	j"ejdiZ#de$d< d,d-ddZ%d.ddZ&d/ddZ'e(j)fd0d!d"Z*d1d%d&Z+e,d2d(d)Z-d2d*d+Z.dS )3r  z6Represents a private or shared CloudKit photo library.)obj_type	list_type	direction	TIMELAPSE)rd  re  rf  query_filtersVIDEOSLOMOFAVORITEPANORAMA
SCREENSHOTLIVEz$dict[SmartAlbumEnum, SmartAlbumSpec]SMART_ALBUMSN	parent_idr_   rB   list[CKRecord]c                 C  s  | j d u st| jjst|}t|| jd}| jjj| j|t	t
id}| }t|dg }d|v r[t|| j|d d}| jjj| j|t	t
id}| }||dg  d|v s3g }t|D ] }|di di d}	|	tjjkr|| |d	 qa|| S g }d }
	 | j jt|tdi | j|
d}|jp| j| _|jD ]}t|tr|| q|j}
|
snqg }|D ]}|jdtjjkr|| |j q|| S )N)rZ   r[   r-  r/  rd   )rZ   r[   rY   r0  	albumTyperR   rN   TrH   )r   r   r  r   r8   rj   r[   r3  r(  r   r   re   r   r   extendr&   FOLDERrR   _fetch_album_recordsrZ   r   r1  r'  r/  r   r   r   rd   r0  r2  rN   )r   rp  rZ   payloadr6  r4  r/  nested_recordsr5  
album_typerY   rH   rH   rI   ru  #  sp   


z!PhotoLibrary._fetch_album_recordsr5  CKRecord | dict[str, Any]BasePhotoAlbum | Nonec                 C  sZ  t |d}|d u rd S tt|drd S t|d}ztt|}W n ty-   tj}Y nw t}tj	}t
j	}tj}dddt|ddg}	tt|g}
t|d	}|d ur^t|d
kr^tj}|tju ret}|tu r|| |t|||||	| j| j|
ttt t|dt|t|ddS || |t|||||	| j| j|
ttt t|dt|t|ddS )NalbumNameEncr   rr  parentIdrM   rO   rP   rT   rS   rU   sortAscendingr"   recordModificationDate)libraryr   	record_idrd  re  rf  query_filterr  r[   rh  rp  r.   record_modification_date)r,   r   r/   r&   rC   	ExceptionALBUM
PhotoAlbumr)   	CONTAINERr(   r'   	ASCENDINGr0   r;   
DESCENDINGrt  PhotoAlbumFolderr   r[   r   r   rL   r.   )r   r5  
album_namealbum_type_valuerx  clsrd  re  rf  r  typed_query_filterssort_ascendingrH   rH   rI   _convert_record_to_albumZ  sz   




z%PhotoLibrary._convert_record_to_albumr   c                   s   t  } j } jdkrt fddtD }|D ],\}}|j} jdkr.|tjkr.t	j
}|t ||j|j| j jt|jpBd d q jdkrN|S   D ]} |}|d urb|| qR|S )Nshared-libraryc                 3  s    | ]
}| j | fV  qd S r   )ro  ).0smart_albumr   rH   rI   	<genexpr>  s
    
z+PhotoLibrary._get_albums.<locals>.<genexpr>)r  r   rd  re  rf  r  r[   rh  )r   ro  itemsr  tupler%   rf  r*   	FAVORITESr'   r  r   SmartPhotoAlbumrd  re  r   r[   r   rh  ru  r  )r   r   smart_albumsr  metarf  r5  r   rH   r   rI   r<    s>   






zPhotoLibrary._get_albumsr   rL   rx  r&   Optional['PhotoAlbum']c                 C  s  t |dd}t }| jd ur{t| jjr{t	dt
td  dd|ddt|jdddddddd|ddd	ddd	dd
dd}| jj|gtdi | jdd}|jD ]}t|trx| |}t|trx| | |  S q^d S | jj}	t| jj}
|	 d|
 }| jjj|ddd|id|jiddiddid|idd	idd	id
ddg| jddttid}|  }|!dg }|r| |d }t|tr| | |S d S )Nutf-8create   CPLAlbumENCRYPTED_BYTESrP   INT64r   r"   )r{  rr  r   r   r   sortTyper~  rN   r   r0  operationTyper5  T
operationsr[   atomic/records/modify?rR   )r   r0  r  ra   r  r[  r/  rH   )"base64	b64encodeencodedecoderJ   r   r   r  r   r   r   osurandomhexupperrC   rR   modifyr   r[   r/  r   r   r  r  r?  r  r   r#  r3  r   r   re   r   )r   r   rx  encodedr   oprespr5  r   r^  r#  r(  r4  rv  r/  rH   rH   rI   create_album  s   




%

zPhotoLibrary.create_albumpathOptional['PhotoAsset']c              
   C  s  | j dur/t| jjr/z| j j|t| jjd d}W nO ty. } ztt||d}~ww t	j
|}t| jj}||d< | j dt| }t|d}| jjj||d}W d   n1 sbw   Y  | }t|trr|nt|}	|	jrtdd	d
 |	jD t|	j}
dd |
D }|d}|d}| j duo|duo|duot|du pt|du pt|ddu pt|ddu }|r| j jt|t|gtdi | jtd}dd |jD }d|vsd|vrdS |  | j|d |d }t!|d|  |S )z<Upload a file into the library and return the created asset.Ndsid)r  filenamez/upload?rb)r(  datar  c                 S  s   g | ]	}|j d ddqS )re   Trf   )ri   )r  errorrH   rH   rI   
<listcomp>,  s    z,PhotoLibrary.upload_file.<locals>.<listcomp>c                 S  ,   i | ]}t |trt|d v rt||qS >   rG  rH  r   r   r1   r  r5  rH   rH   rI   
<dictcomp>4      z,PhotoLibrary.upload_file.<locals>.<dictcomp>rH  rG  r   r   )record_namesr[   rW   c                 S  r  r  r  r  rH   rH   rI   r  S  r  _libraryrH   )"r   r   r  r   upload_filerL   r#  r   r   r  r  basenamedictr%  r   openr3  re   r   r6   model_validateerrorsr   r/  r   r.   r/   lookupr0   r   r[   PHOTO_DESIRED_KEYSr  setattr)r   r  rv  excr  r#  r  file_objr4  upload_payloadr/  records_by_typemaster_recordasset_recordneeds_lookupr  photorH   rH   rI   r    s   





zPhotoLibrary.upload_filer>  c                 C  s   t t| jtjj S r   )r   r  r   r*   
ALL_PHOTOSrR   r   rH   rH   rI   alld     zPhotoLibrary.allc              
   C  s"   t | ddtjtjtj| j| jdS )NzRecently Added)r  r   r  rd  re  rf  r  r[   )	r  r)   ALLr(   ADDEDr'   r  r   r[   r   rH   rH   rI   recently_addedh  s   zPhotoLibrary.recently_addedr   )rp  r_   rB   rq  )r5  ry  rB   rz  r`  )r   rL   rx  r&   rB   r  r  rL   rB   r  )rB   r>  )/r  r	  r
  r  r*   r  r7   r)   r  r(   DEFAULTr'   r  
TIME_LAPSErg  SMART_ALBUMr  r=   VIDEOSri  SLO_MOrj  BURSTSBURSTSTACKr  rk  	PANORAMASrl  SCREENSHOTSrm  rn  RECENTLY_DELETEDDELETEDHIDDENro  __annotations__ru  r  r<  r&   r  r  r  rc  r  r  rH   rH   rH   rI   r    s   
 A
7
E&
LVr  c                   @  s  e Zd ZdZddejddeddZeedfddZ	edfddZ
edfddZejdgddZedhddZedid d!Zeedfd"d#Zdjd&d'Zedhd(d)Zdkd,d-Zdld0d1Zdhd2d3Zdmd6d7Zdnd8d9Zednd:d;Zdod<d=Zdgd>d?ZdpdAdBZdndCdDZdhdEdFZdpdGdHZdfdIdJZdfdKdLZdqdOdPZ drdRdSZ!dsdTdUZ"dtdWdXZ#dudYdZZ$dfd[d\Z%ddd]dvdcddZ&dS )wBasePhotoAlbumzAbstract photo album.Nd   )r  	page_sizerf  r  r  r   rL   re  r(   r  r  r  rC   rf  r'   rB   r   c                C  s:   || _ || _|pt|dd | _|| _|| _|| _d | _d S )Nr   )_namer  r"  r   
_page_size
_direction
_list_type_len)r   r  r   re  r  r  rf  rH   rH   rI   r   x  s   

zBasePhotoAlbum.__init__c                 C  rA  r   rB  r   rH   rH   rI   r        zBasePhotoAlbum.fullnamec                 C  r7  r   )r   r   rH   rH   rI   title  r9  zBasePhotoAlbum.titlec                 C  r7  r   )r  r   rH   rH   rI   r     r9  zBasePhotoAlbum.namerR   c                 C  s   | j |kr| | d S d S r   )r  renamer   rR   rH   rH   rI   r     s   
c                 C  s   | j dk r| j S dS )Nr  )r  r   rH   rH   rI   r    r  zBasePhotoAlbum.page_sizer  c                 C  s   t | jd| jS )Nr  )r"  r  r   rH   rH   rI   r       zBasePhotoAlbum.servicec                 C  rA  r   rB  r   rH   rH   rI   r     r  zBasePhotoAlbum.idoffsetlist[CKQueryFilterBy]c                C  s   ||f}g S r   rH   r   r  rf  _rH   rH   rI   _query_filters  s   zBasePhotoAlbum._query_filtersc                 C  rA  r   rB  r   rH   rH   rI   _get_len  rD  zBasePhotoAlbum._get_lenr  #Generator['PhotoAsset', None, None]c                 c  s    t | j|td|| jtd||dd}| jd u s t| jjsPt| jdrPt| drP| jjj	| 
 | jtd||d |dttid}| | E d H  d S | jj|td
i | jj|d d	}|jph| jj| j_| |jE d H  d S )Nr   r  rf  re  rf  r  extra_filtersr   _get_url   )r  r  rf  r-  r*  rH   )r:   r  maxr  r   r   r  r   r!  r3  r  _get_payloadr   r   _process_photo_list_responsere   rZ   r   r  r[   r1  r'  r/  )r   r  rf  r  rZ   r4  rH   rH   rI   _get_photos_at  sB   
	
	zBasePhotoAlbum._get_photos_atphoto_id'PhotoAsset'c                 C  sT  t | j|d}| jdtjd}|r|j| | jd u s"t| j	j
sgt| j	drgt| drg| j	j
j|  | |ttid}| | D ]}|j|krP|  S qE| jD ]}|j|kr_|  S qTtd| | jj|td	i | jj|  d}|jp| jj| j_| |jD ]}|j|kr|  S q| jD ]}|j|kr|  S qtd| )
N)re  r  r   r  r   r  r-  Photo does not exist: r*  rH   )r<   r  r  r'   r  filterByrs  r   r   r  r   r!  r3  r  _get_photo_payloadr   r   r	  re   r   photosr   rZ   r   r  r[   _photo_lookup_results_limitr1  r'  r/  )r   r  rZ   filtersr4  r  rH   rH   rI   
_get_photo  sN   






zBasePhotoAlbum._get_photoc                 C  s   | j tjkrdS dS )zFReturn the minimum CloudKit result size for direct list-index lookups.   r  )r  r(   r  r   rH   rH   rI   r    s   z*BasePhotoAlbum._photo_lookup_results_limitr/  9list[CKRecord | CKTombstoneRecord | Any] | dict[str, Any]c                 c  s4   t |trh|}t| jdr| j|\}}n+i }g }|d D ]"}|d dkr6|d d d d }|||< q|d d	krA|| q|D ]!}||d }|d u rRqD| j| j||}	t	|	d
| j |	V  qDd S dd |D }
t
|
\}}|D ] }||j}|d u rqw| j| j||}	t	|	d
| j |	V  qwd S )NrL  r/  r   rG  r0  r   rR   rN   rH  r  c                 S  s   g | ]	}t |tr|qS rH   )r   r   r  rH   rH   rI   r  %      z?BasePhotoAlbum._process_photo_list_response.<locals>.<listcomp>)r   r  r!  r  rL  r   r   r  r  r  r-   rN   )r   r/  raw_responserI  mastersr5  rK  masterassetr  typed_recordsassets_by_masterr  r  rH   rH   rI   r	    sH   



z+BasePhotoAlbum._process_photo_list_responsec                 c  s    t  }| j}t|d d}	 g }| || j|D ]}|j|v r!q||j || q|s1dS t|D ]}|V  q5t	||k rCdS |t	|7 }q)a  
        Iterate the recently-added index newest-first.

        The ``ADDED`` index uses a trailing ``startRank`` window instead of the
        forward paging used by the other Photos indexes. A request at rank ``n``
        returns the newest items up to ``n`` and the window itself arrives
        oldest-to-newest. The generic descending pager therefore under-fetches
        recent assets when the count endpoint is unavailable and would yield the
        wrong order even when a count exists.
        r"   r   TN)
setr  r  r
  r  r   addr   reversedr   )r   seenr  r  windowr  rH   rH   rI   _iter_added_desc_photos/  s&   
z&BasePhotoAlbum._iter_added_desc_photosc                 c  s    d | _ | jtjkr| jtjkr|  E d H  d S | jtjkr%t| d nd}t	 }	 d}| 
|| j| jD ]}|d7 }|j|v rBq6||j |V  q6|| jd k rUd S | jtjkr`||8 }n||7 }q+)Nr"   r   Tr  )r  r  r(   r  r  r'   r  r"  r   r  r
  r  r   r  )r   r  r   num_resultsr  rH   rH   rI   r  M  s,   

zBasePhotoAlbum.photosc                 C  s   t | || jdS )Nr"   )nextr
  r  )r   r  rH   rH   rI   r  g  s   zBasePhotoAlbum.photoc                 C     t d)NzAlbum name is read-onlyrB  r  rH   rH   rI   r  j     zBasePhotoAlbum.renamer   c                 C  r%  )NzAlbum delete is not implementedrB  r   rH   rH   rI   deletem  r&  zBasePhotoAlbum.deletec                 C  r7  r   )r  r   rH   rH   rI   r   p     zBasePhotoAlbum.__iter__c                 C  s   | j d u r
|  | _ | j S r   )r  r   r   rH   rH   rI   r   s  s   

zBasePhotoAlbum.__len__c                 C  s   dS NTrH   r   rH   rH   rI   __bool__x     zBasePhotoAlbum.__bool__c                 C  r7  r   )r  r   rH   rH   rI   __str__{  r(  zBasePhotoAlbum.__str__c                 C  s   dt | j d|  dS )N<z: 'z'>)rQ   r  r   rH   rH   rI   __repr__~  s   zBasePhotoAlbum.__repr__r   'PhotoAsset | None'c                 C  s"   z|  |W S  ty   Y d S w r   )r  r   r   r   rH   rH   rI   r     s
   zBasePhotoAlbum.get	int | strc              
   C  s|   t |tr,|dk rt| | }zt| || jdW S  ty+ } ztd|d }~ww | |}|d ur7|S t	d| )Nr   r"   zPhoto index out of ranger  )
r   rC   r   r$  r
  r  StopIterationr  r   r   )r   r   r  r  rH   rH   rI   r     s   


zBasePhotoAlbum.__getitem__c                 C  r   r   )r   r0  rH   rH   rI   r     r   zBasePhotoAlbum.__contains__r`   c              	   C  s    | j || j||| j||ddS )Nr  r  re  rf  r#  rh  )_list_query_genr  r  )r   r  r  rf  rH   rH   rI   r    s   zBasePhotoAlbum._get_payloadc                 C  s6   | j dtjd}|t| | jd| jtjd|dS )Nr   r  r"   r3  )r  r'   r  r   rV   r4  r  )r   r  r  rH   rH   rI   r    s   z!BasePhotoAlbum._get_photo_payloadc                 C  s.   t | jdr| jj dt| jj S td)Nr  r  )r!  r  r  r   r#  AttributeErrorr   rH   rH   rI   r    s   zBasePhotoAlbum._get_urlr  rh  r#  r  list[dict[str, Any]] | Nonerh  list[CKQueryFilterBy] | Nonec             	   C  sP   |d u r|d urdd |D }t ||||d}t|t| dt| jdtt|dS )Nc                 S     g | ]}t |qS rH   r   r  r  itemrH   rH   rI   r    s    
z2BasePhotoAlbum._list_query_gen.<locals>.<listcomp>r  _zone_idr[   )rZ   r[   rW   rX   )r:   rj   r"  r  r$   r  )r   r  re  rf  r#  r  rh  rZ   rH   rH   rI   r4    s$   
zBasePhotoAlbum._list_query_gen)r  r  r   rL   re  r(   r  r  r  rC   rf  r'   rB   r   rb  rR   rL   rB   r   r  )rB   r  r  rC   rf  r'   rB   r  )r  rC   rf  r'   r  rC   rB   r  )r  rL   rB   r  )r/  r  rB   r  )rB   r  )r  rC   rB   r  rB   r   )r   rL   rB   r/  )r   r1  rB   r  )r   rL   rB   r   )r  rC   r  rC   rf  r'   rB   r`   r  rL   rB   r`   )r  rC   re  r(   rf  r'   r#  rC   r  r7  rh  r8  rB   r`   )'r  r	  r
  r  r'   r  r   rc  r   r   r  r   setterr  r  r   r  r   r
  r  r  r	  r"  r  r  r  r'  r   r   r*  r,  r.  r   r   r   r  r  r  r4  rH   rH   rH   rI   r  u  sb    


(
&

'













r  c                
      s   e Zd ZdZdddddddddd	dN fd"d#ZedOd$d%ZedOd&d'ZdPd*d+ZdQd-d.Z	dRd0d1Z
dSd4d5ZdTd8d9ZedOd:d;ZedOd<d=ZdUd>d?ZdVdBdCZdWdFdGZdOdHdIZedXdJdKZedYdLdMZ  ZS )Zr  zA user or virtual photo album.Nr  )	r(  r  r  r[   rh  r  rp  r.   r  r  r  r   rL   r  rd  r)   re  r(   rf  r'   r(  r_   r  r7  r  r  r[   r  rh  r8  r  rC   rp  r.   r  
Any | NonerB   r   c                  s   t  j||||	||d || _|| _| ||| _|p/t| jdr.| jj dt	| jj
 nd| _|
p4t| _|| _|| _|| _d S )N)r  r   re  r  r  rf  r  r  r  )superr   
_record_id	_obj_type_coerce_query_filters_extra_filtersr!  r  r  r   r#  _urlr$   r=  
_parent_id_record_change_tag_record_modification_date)r   r  r   r  rd  re  rf  r(  r  r  r[   rh  r  rp  r.   r  	__class__rH   rI   r     s(   


zPhotoAlbum.__init__c                 C  r7  r   )rE  r   rH   rH   rI   r     r9  zPhotoAlbum.idc                 C  s   | j t dS )Nr   )	_fullnamer  r   rH   rH   rI   r     s   zPhotoAlbum.fullnamer   set[str]c                C  s   | j |v s
| jd u r| jS || j  | jj| j}|d u s$|j |v r'| jS t|tr3|j	|d}n|j
}|r@| d| j S | jS )NrO  /)r   rJ  r   r  r  r   r   r   r  rP  r   )r   r   parentparent_fullnamerH   rH   rI   rP    s   
zPhotoAlbum._fullnamerR   c                 C  s  | j |krd S t|dd}| jd urbt| jjrbt	dt
| jd| jdd|didd}| jj|gtdi | jd	d
}|jD ]}t|tr`|jpO| j| _|jdp\|jd| _ nqCnc| jj}t| jj}| d| }| jjj|d	| jd| jd| jdd|iiddgdttid}| }	|	dpi gd }
|
d| j| _|
di di d|
di di d| j| _|| _ d S )Nr  updater  r{  r  rP   rN   r   r   r0  r  Tr  r  userModificationDater  rR   r  ra   r  r[  r/  r   r   r0  rH   )r  r  r  r  r  r   r   r  r   r   r   rE  rK  r  r   r=  r/  r   r   r   r0  r2  rL  r  r   r#  r3  r   r   re   r   )r   rR   r  r  r4  r5  r^  r#  r(  rv  latestrH   rH   rI   r    s   





	




zPhotoAlbum.renamer   c                 C  s   | j d ur/t| jjr/tdt| jd| jddddidd}| j j|gt	di | j
d	d
 n1| jj}t| jj}| d| }| jjj|d	| j
d| jd| jdddiiddgdttid | j| j d	S )NrU  r  r   r  r"   rP   rV  r  Tr  r  rR   rX  r[  rH   )r   r   r  r   r   r   rE  rK  r  r   r=  r  r   r#  r3  r   r   r  r@  )r   r  r^  r#  r(  rH   rH   rI   r'  ^  sF   	
zPhotoAlbum.deleter  r  c                 C  s   |  |}| jd urAt| jjrAtdt| d| j dd|ddddd| jddd	d
}| jj|gt	di | j
dd dS | jj}t| jj}| d| }| jjj|d| j
d| d| j dd|iddid| jidd	d
gdttid dS )Nr  z-IN-CPLContainerRelationrO   rP   r  i   )r   r   r   r  r  Tr  r  rR   rX  r[  rH   )_relation_item_idr   r   r  r   r   r   rE  r  r   r=  r  r   r#  r3  r   r   )r   r  item_idr  r^  r#  r(  rH   rH   rI   	add_photo  sP   

zPhotoAlbum.add_photor  r  c                 C  sX   t | jdd }t|sd S ||}|d u rd S | jtjjkr*| |s*td| |d|S )Nr  zFailed to add photo to album)r   r  )	r"  r  callabler   r*   r  rR   r]  r5   )r   r  r  r  rH   rH   rI   upload  s   zPhotoAlbum.uploadc                 C  s   | j j d| j S )N:)rF  rR   rE  r   rH   rH   rI   _get_container_id  r  zPhotoAlbum._get_container_idc                 C  r7  r   )ra  r   rH   rH   rI   _container_id  r9  zPhotoAlbum._container_idc                 C  s  | j d u st| jjsyt| jdryt| jdry| jj}t| jj}| d| }| jjj|dddddd	| j	gd
ddd| j
dgittid}| }zt|d d d d d d d W S  ttttfyx   tjd| j|dd Y dS w | j j| j| j
dS )Nr   r  z/internal/records/query/batch?batchr"   HyperionIndexCountLookupindexCountIDINSTRING_LISTrP   r}  )r   r  T)rc   rZ   zoneWidera   r[  r   r/  r0  	itemCountrR   z+Unexpected Photos count response for %s: %rexc_info)container_idr[   )r   r   r  r   r!  r  r   r#  r3  rb  r=  r   r   re   rC   r  r   	TypeError
ValueErrorLOGGERdebugra  batch_count)r   r^  r#  r(  r6  r4  rH   rH   rI   r     sZ   

zPhotoAlbum._get_lenr  r  c                C  s   ||f}t | jS r   )r   rH  r  rH   rH   rI   r    s   
zPhotoAlbum._query_filtersr  r`   c                 C  s:   | j dtjd}|t| | jd| jtj|  |dS )Nr   r  r3  )r  r'   r  r   rV   r4  r  r  )r   r  rh  rH   rH   rI   r    s   zPhotoAlbum._get_photo_payloadc                 C  r7  r   )rI  r   rH   rH   rI   r    r(  zPhotoAlbum._get_urlc                 C  s$   t | dd }t|tr|r|S | jS )Nasset_id)r"  r   rL   r   )r  rr  rH   rH   rI   r[    s   zPhotoAlbum._relation_item_idc                 C  s"   | d urdd | D S t |pg S )Nc                 S  r9  rH   r:  r;  rH   rH   rI   r  '  s    z4PhotoAlbum._coerce_query_filters.<locals>.<listcomp>)r   r6  rH   rH   rI   rG  !  s   z PhotoAlbum._coerce_query_filters) r  r  r   rL   r  rL   rd  r)   re  r(   rf  r'   r(  r_   r  r7  r  r  r[   r  rh  r8  r  rC   rp  r_   r.   r_   r  rC  rB   r   rb  )r   rQ  rB   rL   r>  r@  )r  r  rB   r   r  r  r?  rA  )r  r  rB   rL   )r  r7  rh  r8  rB   r  )r  r	  r
  r  r   rc  r   r   rP  r  r'  r]  r_  ra  rb  r   r  r  r  staticmethodr[  rG  __classcell__rH   rH   rM  rI   r    sB    (


K
*
0

3
	
r  c                   @  s   e Zd ZdZd	ddZdS )
r  zA folder album.r  rL   rB   r  c                 C  s   d S r   rH   r   r  rH   rH   rI   r_  .  r+  zPhotoAlbumFolder.uploadNr  )r  r	  r
  r  r_  rH   rH   rH   rI   r  +  s    r  c                      sF   e Zd ZdZdddd" fddZed#ddZd$ fd d!Z  ZS )%r  zA well-known smart album.Nr  )rh  r  r  r  r   r*   rd  r)   re  r(   rf  r'   r  r#   r[   r\   rh  r8  r  rC   rB   r   c          
        s(   t  j||j|j|||||||	d
 d S )N)
r  r   r  rd  re  rf  r  r[   rh  r  )rD  r   rR   )
r   r  r   rd  re  rf  r  r[   rh  r  rM  rH   rI   r   5  s   
zSmartPhotoAlbum.__init__rL   c                 C  s
   | j j S r   )rF  rR   r   rH   rH   rI   ra  O     
z!SmartPhotoAlbum._get_container_idr  r  c                   s   | j tjjkrt |S d S r   )r   r*   r  rR   rD  r_  ru  rM  rH   rI   r_  S  s   zSmartPhotoAlbum.upload)r  r  r   r*   rd  r)   re  r(   rf  r'   r  r#   r[   r\   rh  r8  r  rC   rB   r   rb  r  )	r  r	  r
  r  r   rc  ra  r_  rt  rH   rH   rM  rI   r  2  s    r  c                	   @  st  e Zd ZU dZi ddddddddddd	dd
ddddddddddddddddddddddddZded< i ddddddddddd	dd
ddddd dd!dd"dd#dd$dd%dd&dd&dd'd(d)dZded*< d+d,d-d.d/d0d1d2d3Zded4< d+d0d1d.d-d5Zded6< dd>d?Z	e
ddAdBZe
ddCdDZe
ddEdFZe
ddGdHZe
ddJdKZe
ddMdNZe
ddOdPZe
ddQdRZe
ddTdUZe
ddVdWZe
ddYdZZe
dd\d]Ze
dd_d`ZdddddeZdddgdhZdididjddpdqZddrdsZeddvdwZddydzZdd{d|Zdd}d~Z dddZ!dddZ"diS )r  zEA logical photo asset built from a ``CPLMaster`` + ``CPLAsset`` pair.zpublic.heicimagezpublic.heifzpublic.jpegz
public.pngzcom.apple.quicktime-moviemoviezpublic.mpeg-4zcom.apple.m4v-videozcom.adobe.raw-imagezcom.canon.cr2-raw-imagezcom.canon.cr3-raw-imagezcom.canon.crw-raw-imagezcom.fuji.raw-imagezcom.nikon.nrw-raw-imagezcom.nikon.raw-imagezcom.olympus.or-raw-imagezcom.olympus.raw-imagezcom.panasonic.rw2-raw-image)zcom.pentax.raw-imagezcom.sony.arw-raw-imager\   
ITEM_TYPESz.HEICz.HEIFz.JPGz.PNGz.MOVz.MP4z.M4Vz.DNGz.CR2z.CR3z.CRWz.RAFz.NRFz.NEFz.ORFz.RW2z.PEFz.ARWFILE_TYPE_EXTENSIONSresOriginalresOriginalAlt
resJPEGMedresJPEGThumbresOriginalVidCompl	resVidMedresVidSmall
resSidecar)originalalternativemediumthumboriginal_videomedium_videothumb_videosidecarPHOTO_VERSION_LOOKUP)r  r  r  thumb_imagemedium_imageVIDEO_VERSION_LOOKUPr  r  r  r   r  rB   r   c                 C  s"   || _ || _|| _d | _d | _d S r   )_service_master_record_asset_record
_resourcesr  )r   r  r  r  rH   rH   rI   r     s
   
zPhotoAsset.__init__rL   c                 C  r   r   r0   r  r   rH   rH   rI   r     rv  zPhotoAsset.idc                 C  r   r   )r0   r  r   rH   rH   rI   	master_id  rv  zPhotoAsset.master_idc                 C  r   r   r  r   rH   rH   rI   rr    rv  zPhotoAsset.asset_idc                 C  s   t | jdp| jS )Nr   )r,   r  r   r   rH   rH   rI   r    s   zPhotoAsset.filenamer^   c                 C  s6   t | jd}t|trttt |dS t|dd S )Nr   size)	r/   r  r   r  r   r   rC   r   r"  )r   tokenrH   rH   rI   r    s   
zPhotoAsset.sizer   c                 C  r7  r   )
asset_dater   rH   rH   rI   created  r9  zPhotoAsset.createdc                 C  H   t | jd}t|tr|S t|ttfrt|d tjS tdtjS )Nr        @@r   	r/   r  r   r   rC   floatfromtimestampr   rF   r  rH   rH   rI   r       
zPhotoAsset.asset_datec                 C  r  )Nr   r  r   r  r  rH   rH   rI   
added_date  r  zPhotoAsset.added_datetuple[int | None, int | None]c                 C  s,   t tt t| jdt tt t| jdfS )Nr   r   )r   r   rC   r/   r  r   rH   rH   rI   
dimensions  s   

zPhotoAsset.dimensionsc                 C  s   t | jd}|| jv r| j| S t | jd}|| jv r | j| S t|tr-d| v r-dS | j dr7dS | j drAdS dS )Nr   r   rawrw  )z.heicz.pngz.jpgz.jpeg)z.arwz.cr2z.cr3z.crwz.dngz.nefz.nrfz.nrwz.orfz.pefz.rafz.rw2rx  )r/   r  ry  r   rL   lowerr  endswith)r   raw_typerH   rH   rI   	item_type  s   




zPhotoAsset.item_typer   c                 C  s   | j dkot| jdd uS )Nrw  r   )r  r/   r  r   rH   rH   rI   is_live_photo   s
   

zPhotoAsset.is_live_photodict[str, PhotoResource]c              
   C  sp   | j d u r5i | _ | jdkr| jn| j}| D ]\}}t||| j| j| j| j	| j
d}|d ur4|| j |< q| j S )Nrx  )r   prefixr  r  item_type_extensionsr  item_type_lookup)r  r  r  r  r  r+   r  r  rz  r  ry  )r   mappingr   r  resourcerH   rH   rI   	resources  s(   

	
zPhotoAsset.resourcesdict[str, dict[str, Any]]c                 C  s   dd | j  D S )Nc                 S  s   i | ]	\}}||  qS rH   )as_dict)r  r   rR   rH   rH   rI   r  !  r  z'PhotoAsset.versions.<locals>.<dictcomp>)r  r  r   rH   rH   rI   versions  r  zPhotoAsset.versionsr  versionr_   c                 C  s   | j |}|r|jS d S r   )r  r   r(  )r   r  r  rH   rH   rI   download_url#  s   zPhotoAsset.download_urlbytes | Nonec                 K  sf   |  |}|d u rd S t| jdr!tt| jdd r!| jj|S | jjj|fddi|}|j	
 S )N_private_clientr   streamT)r  r!  r  r   r"  r  download_asset_bytesr   r   r  read)r   r  kwargsr(  r4  rH   rH   rI   download'  s   

zPhotoAsset.downloadNfallback_fieldfallback_valuer/  #Iterable[CKRecord | dict[str, Any]]r  r  r   c          
      C  s$  t | j}|D ]1}t|tr|jdkr|j|kr|| _ dS qt|tr8|ddkr8|d|kr8|| _ dS q|d u r?dS t| jtrl| jjddd}|	di |i }|d	d
|d|d |< t
|| _dS | j	di }||i }d|i}	t|trd	|v r|d	 |	d	< |	||< dS )NrG  Tr   rN   Fre   rf   r0  rQ   r  rP   rR   )r0   r  r   r   r   rN   r  r   ri   
setdefaultr  )
r   r/  r  r  
asset_namer5  rv  existingr0  rV  rH   rH   rI   _replace_asset_record2  s<   



z PhotoAsset._replace_asset_recordc                 C  sZ   | j }|d u r	dS z	|j| j}W n
 ty   Y dS w |d u r#dS |j| _|j| _dS )NFT)r  r  r   r   r  r  r  )r   r  	refreshedrH   rH   rI   _refresh_from_libraryZ  s   z PhotoAsset._refresh_from_library1Iterable[CKRecord | dict[str, Any] | CKErrorItem]	list[str]c              	   C  s   g }| D ]J}t |tr%|jpd}|jpd}|| d|j d| d qt |ts+qd|vr0q|dp6d}|dp=d}|| d|d  d| d q|S )	Nz<unknown record>zno reason provided: z ()serverErrorCoderN   reason)r   r   rN   r  r   r  r  r   )r/  r  r5  record_name_r  rH   rH   rI   _record_errorsh  s   



"zPhotoAsset._record_errorsrR   c                 C  s   |rdnd}t | jpt}t|d |d|dd}d}t| jdrltt| jd	d rlt	d
t
t| jt| jt| jpAt| jdd|ditd i |dd}| jjj|g|dd}t|j}| j|jd|d}nP| jj}	t| jj}
|	 d|
 }| jjj|d
t| jt| jt| jpt| jdd|iiddg|ddttid}| }t|dg }| j|d|d}| |}d}t| jdd dks|r|r|  }t t!| jdpd}|r|sdd"| }t#d| | d||kr|rdd"| nd}t#d| | ddS )!Nr"   r   rY  ownerRecordNamezoneTyperY  r  r  Fr  r   rU  r   r  rP   rN   r   r   r0  ra   r  Tr  r  r  rR   rV  r  r[  r/  r  r  r  z; zFailed to update favorite state)r  r  rH   )$r2   r  r$   r   r   r!  r  r   r"  r   r   r0   r1   r.   r  r   r  r  r   r/  r  r  r   r#  r   r3  r   r   re   r  r  r  rC   r/   joinr5   )r   rR   favorite_value	zone_dictr[   matched_assetr  r4  response_recordsr^  r#  r(  rv  r  r  current_favoritedetailrH   rH   rI   set_favorite|  s   




zPhotoAsset.set_favoritec                 C  
   |  dS r)  r  r   rH   rH   rI   favorite  r   zPhotoAsset.favoritec                 C  r  )NFr  r   rH   rH   rI   
unfavorite  r   zPhotoAsset.unfavoritec                 C  s*  t | jpt}t|d |d|dd}t| jdrWtt| jdd rWt	dt
t| jt| jt| jp9t| jdd	d
ditdi |dd}| jjj|g|dd dS | jj}t| jj}| d| }| jjj|dt| jt| jt| jpt| jddd
iiddg|ddttid dS )NrY  r  r  r  r  r   rU  r   r  r"   rP   r  r  Tr  r  rR   rV  r  r[  rH   )r2   r  r$   r   r   r!  r  r   r"  r   r   r0   r1   r.   r  r   r  r  r  r   r#  r   r3  r   r   )r   r  r[   r  r^  r#  r(  rH   rH   rI   r'    s\   


zPhotoAsset.deletec                 C  s   dt | j d| j dS )Nr-  z: id=>)rQ   r  r   r   rH   rH   rI   r.    s   zPhotoAsset.__repr__)r  r  r  r   r  r   rB   r   rb  )rB   r^   )rB   r   )rB   r  r@  )rB   r  )rB   r  )r  )r  rL   rB   r_   )r  rL   rB   r  )r/  r  r  r_   r  r   rB   r   )r/  r  rB   r  )rR   r   rB   r   )#r  r	  r
  r  ry  r  rz  r  r  r   rc  r   r  rr  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rs  r  r  r  r  r'  r.  rH   rH   rH   rI   r  Y  s
  
 	
	


(

]

4r  c                      s   e Zd ZdZd< fd
dZed=ddZed>ddZed?ddZed?ddZ	e
jfd@ddZdddAd#d$ZdBd%d&Zdd'dCd+d,ZdDd0d1Zdd2dEd8d9ZdFd:d;Z  ZS )GPhotosServicez&Modern CloudKit-backed Photos service.service_rootrL   r#  r`   r  shared_streams_urlrB   r   c           
        s   t  j|||d | jddd | j d}| j d}|| _t||| j|d| _t||| jd| _|| _	|| _
d | _d | _| d| jd	  d
}t| tt|rU| jnd t|dd| _ddlm}	 |	| |d| _d S )N)r  r   r#  T)
remapEnumsgetCurrentSyncTokenz5/database/1/com.apple.photos.cloud/production/privatez4/database/1/com.apple.photos.cloud/production/sharedr  )r  r   r  rR  r  z/sharedstreams/webgetalbumslistr  )r[   r  r  r  r  r   )PhotoStreamLibrary)r  )rD  r   r#  rU  r  r  r#   r  _shared_clientr%  _shared_streams_url
_libraries_legacy_servicer  r$   r   r  _root_librarypyicloud.services.photos_legacyr  _shared_library)
r   r  r   r#  r  r  private_endpointshared_endpointshared_streams_album_urlr  rM  rH   rI   r     sJ   

zPhotosService.__init__dict[str, BasePhotoLibrary]c              	   C  s  | j d u r| j| jd}t| jr| j }|jD ]7}|jrq|j	j
dd}|j	j}|td kr6|j| j_q|}d}t|rEd| }d}t| || j|d||< qz1| j }|jD ]&}|jr`qZ|j	j
dd}|j	j}d| }||v ruqZt| || jdd||< qZW nh ttfy   tjd	dd
 Y nWw | jj| j dt| j i ttid }	|	dg D ]9}|drq|di }
|
d}|td kr|d| j_q|}d}t|rd| }d}t| |
|d||< q|| _ | j S )N)rootsharedT)rh   rY  r  zshared:r  )r[   r  r  z(Shared CloudKit photos zones unavailablerj  rZ  r[  r\  rR  ra   r1  )r[   r  )r  r  r  r   r   r  r]  r\  rR  ra   ri   rY  r$   r1  r'  r   r  r  r   r   ro  rp  r3  r  r   r#  r   r   re   r   )r   	librariesprivate_zonesrX  r  r   r   r  shared_zonesr4  r[   rH   rH   rI   r  L  s   












zPhotosService.librariesr  c                 C     | j jS r   )r  r  r   rH   rH   rI   r       zPhotosService.allr   c                 C  r  r   )r  r   r   rH   rH   rI   r     r  zPhotosService.albumsc                 C  s   t t| jjS r   )r   r   r  r   r   rH   rH   rI   shared_streams  r  zPhotosService.shared_streamsr   rx  r&   Optional[PhotoAlbum]c                 C  r   r   )r  r  )r   r   rx  rH   rH   rI   r    r   zPhotosService.create_albumNr   r  r   str | BasePhotoAlbum | NoneOptional[PhotoAsset]c                C  sn   |du r
| j |S t|tr0| j|}|du r!| j  |}|du r/td| d|dn|}||S )z
        Upload a file into the root library or a specific album.

        ``album`` may be omitted for the root library, provided as an album
        object, or provided as an album name/fullname.
        NzNo album matched ''r  )	r  r  r   rL   r   r   r=  r5   r_  )r   r  r   	album_objrH   rH   rI   r_    s   


zPhotosService.uploadc                 C  s
   | j  S r   )r  r_  r   rH   rH   rI   r_    r   zPhotosService.sync_cursorrM  rN  r_   rO  c                c  s    | j j|dE d H  d S )NrM  )r  rW  )r   rN  rH   rH   rI   rW    s   zPhotosService.iter_changesoptionsr>   r?   c                 C  s
   t | |S )z:Synchronize photo resources into a local output directory.)r@   )r   r  rH   rH   rI   sync  s   
zPhotosService.sync)
iterationsinterval_secondsrC   r  r^   Iterator[PhotoSyncResult]c                c  s    t | |||dE dH  dS )z3Yield repeated sync runs for the given sync target.)r   r  N)rA   )r   r  r   r  rH   rH   rI   watch  s   	zPhotosService.watchc                 C  s4   | j |}|d u rd S |jtjjkr|| |S r   )r  r  r   r*   r  rR   r]  )r   r   r  r  rH   rH   rI   _upload_into_album  s   
z PhotosService._upload_into_album)
r  rL   r#  r`   r  rL   r  rL   rB   r   )rB   r  )rB   r  r`  )r   rL   rx  r&   rB   r  )r  rL   r   r  rB   r  rb  ra  )r  r>   rB   r?   )r  r>   r   rC   r  r^   rB   r  )r   r  r  rL   rB   r  )r  r	  r
  r  r   rc  r  r  r   r  r&   r  r  r_  r_  rW  r  r  r  rt  rH   rH   rM  rI   r    s*    2F


r  r  )rK   rL   rB   r   )rZ   r   r[   r\   rW   r]   rX   r^   rY   r_   rB   r`   )rR   r   rB   r   )r   r   rB   r   )r   r_   rB   r   )gr  
__future__r   r  loggingr  abcr   r   r   r   typingr   r   r	   r
   r   r   unittest.mockr   urllib.parser   pyicloud.common.cloudkitr   r   r   r   r   r   r   r   r   r   r   r   pyicloud.common.cloudkit.clientr   pyicloud.constr   r   pyicloud.exceptionsr   r   r    pyicloud.services.baser!   r  r#   	constantsr$   r%   r&   r'   r(   r)   r*   mappersr+   r,   r-   r.   r/   r0   r1   r2   modelsr3   r4   r5   r6   r7   queriesr8   r9   r:   r;   r<   r=   r  r>   r?   r@   rA   	getLoggerr  ro  r   rJ   rV   rj   r  r   r   r   r   r  r  r  r  r  r  r  r  rH   rH   rH   rI   <module>   sj     8$(	
 



e

8 E     `  Z'   A