Search code examples
macosapplescriptphoto

MacOS Photos - use applescript to update keywords with the name(s) of the albums they are in


TLDR:
I would like to run an Applescript that will iterate newly added photos from a smart album to add the Album Name and Folder Name they are contained in as keywords on the photo.

Case:
My Structure in Photos is this:
My Albums¬
FolderName¬
AlbumName¬
List of Photos

I have created a smart album that is: "Any photos added in the last 90 days"

I would like the applescript to basically do this:

  • Select the photos in the Smart Album
  • Iterate each one, "ask" which Albums and folders they are in
  • Copy the Album names and folder names to append them to the 'keywords' of the photo.

Some things I know about the way Photos App works:

  1. Photos don't know what album(s) they are in
  2. Albums know what photos they contain
  3. The Applescript dictionary is wonky in how it reads containers.
  4. After research, I think the trick is to 'ask' all folders which albums have the selected photo, and then somehow capture the album name and the folder(s) where 'contains photo' is true. But I am seriously lost on how to make this

Those 3 things are tripping me up.
I am really hopeful that someone has done something like this and can help me understand the scripting around this one.

Ultimately, I'm trying to make photos more searchable using smart filters - so having keywords automatically appended will help a lot.

Cat in Photos app with keyword injection

Up to this point, I can get applescript to find a selection (manually chosen files) to iterate through, but I would really like to have it done by a named smart album.

tell application "Photos"
    set eachFile to {}
    set theSelections to (get selection) -- This gets the hilighted photos 
    repeat with i in theSelections
        set selectedPhotoId to get id of i
        set theKeywords to the ({keywords of i})
        
        display dialog theAlbum

        
    end repeat
    
end tell 

My effort so far has been to just figure out which dictionary terms could return some values for me, but I am missing many pieces so far.


Solution

  • global theKeyWords
    
    tell application "Photos"
        -- get the hilighted photos
        set theSelection to (get selection)
        repeat with i from 1 to count theSelection
            set theKeyWords to {}
            set selectionID to id of item i of theSelection
            -- first, get names of albums in the root
            set theKeyWords to theKeyWords & (name of albums whose id of media items contains selectionID)
            -- recursively get names of albums in the subfolders
            my getAlbumNames(its folders, selectionID)
            -- set the keywords of processed photo
            set keywords of media item id selectionID to theKeyWords
        end repeat
    end tell
    
    -- recursive handler 
    on getAlbumNames(theFolders, selectionID)
        if theFolders is {} then return
        tell application "Photos"
            repeat with aFolder in theFolders
                tell aFolder
                    set theKeyWords to theKeyWords & (name of albums whose id of media items contains selectionID)
                    my getAlbumNames(its folders, selectionID)
                end tell
            end repeat
        end tell
    end getAlbumNames