99import itertools
1010import subprocess
1111import json
12+ import urllib
1213import click
1314
1415from tqdm import tqdm
193194 type = click .IntRange (1 ),
194195 default = 1 ,
195196)
197+ @click .option (
198+ "--delete-after-download" ,
199+ help = 'Delete the photo/video after download it.'
200+ + ' The deleted items will be appear in the "Recently Deleted".'
201+ + ' Therefore, should not combine with --auto-delete option.' ,
202+ is_flag = True ,
203+ )
196204@click .version_option ()
197205# pylint: disable-msg=too-many-arguments,too-many-statements
198206# pylint: disable-msg=too-many-branches,too-many-locals
@@ -224,6 +232,7 @@ def main(
224232 no_progress_bar ,
225233 notification_script ,
226234 threads_num , # pylint: disable=W0613
235+ delete_after_download
227236):
228237 """Download all iCloud photos to a local directory"""
229238
@@ -246,6 +255,10 @@ def main(
246255 print ('--directory or --list-albums are required' )
247256 sys .exit (2 )
248257
258+ if auto_delete and delete_after_download :
259+ print ('--auto-delete and --delete-after-download are mutually exclusive' )
260+ sys .exit (2 )
261+
249262 raise_error_on_2sa = (
250263 smtp_username is not None
251264 or notification_email is not None
@@ -541,6 +554,32 @@ def download_photo(counter, photo):
541554 icloud , photo , lp_download_path , lp_size
542555 )
543556
557+ def delete_photo (photo ):
558+ """Delete a photo from the iCloud account."""
559+ logger .info ("Deleting %s" , photo .filename )
560+ # pylint: disable=W0212
561+ url = f"{ icloud .photos ._service_endpoint } /records/modify?" \
562+ f"{ urllib .parse .urlencode (icloud .photos .params )} "
563+ post_data = json .dumps (
564+ {
565+ "atomic" : True ,
566+ "desiredKeys" : ["isDeleted" ],
567+ "operations" : [{
568+ "operationType" : "update" ,
569+ "record" : {
570+ "fields" : {'isDeleted' : {'value' : 1 }},
571+ "recordChangeTag" : photo ._asset_record ["recordChangeTag" ],
572+ "recordName" : photo ._asset_record ["recordName" ],
573+ "recordType" : "CPLAsset" ,
574+ }
575+ }],
576+ "zoneID" : {"zoneName" : "PrimarySync" }
577+ }
578+ )
579+ icloud .photos .session .post (
580+ url , data = post_data , headers = {
581+ "Content-type" : "application/json" })
582+
544583 consecutive_files_found = Counter (0 )
545584
546585 def should_break (counter ):
@@ -557,6 +596,8 @@ def should_break(counter):
557596 break
558597 item = next (photos_iterator )
559598 download_photo (consecutive_files_found , item )
599+ if delete_after_download :
600+ delete_photo (item )
560601 except StopIteration :
561602 break
562603
0 commit comments