--
-- Sets the date a photo was taken in iPhoto using the date stored in
-- Flickr for that photo as the source (via each photo's XML file as
-- generated by the Python script).
--
-- the folder where the XML files are for each Flickr photo, as
-- downloaded with the Python script
set the_xml_folder to ((path to home folder as text) & "Documents:scripts:flickr:photoinfo")
-- replace the tell section with the following line if you
-- want to run the script on *all* photos in your iPhoto library
-- as opposed to just those you have selected.
--set all_the_photos to get_all_photos()
tell application "iPhoto"
set all_the_photos to selection
end tell
-- loop over the photos (either all or the selection as chosen above)
set photo_count to count of all_the_photos
repeat with i from 1 to photo_count
-- get information about this photo
set the_photo to (item i of all_the_photos)
set the_filename to get_photo_filename(the_photo)
set the_id to (item 1 of (string_to_list(the_filename, "_")))
-- load and parse this photo's XML file (as downloaded by that Python script)
set the_data to load_xml(the_xml_folder & ":" & the_id & ".xml")
set the_xml to parse_it(the_data)
-- extract the photo's date taken from the XML document
set the_photo_tag to getAnElement(the_xml, "photo")
set the_dates to getElementFromPath(the_xml, {"photo", "dates"})
set the_date_taken to convert_date(taken of XML attributes of the_dates)
-- set the photo's date taken in iPhoto to what we got from its XML file
tell application "iPhoto"
select the_photo
set date of the_photo to the_date_taken
end tell
end repeat
return 0
on convert_date(the_flickr_date)
-- convert a Flickr date, as extract from the XML file, to an AppleScript Date object
set d_n_t to string_to_list(the_flickr_date, " ")
set the_date to (item 1 of d_n_t)
set the_exif_time to (item 2 of d_n_t)
set y_m_d to string_to_list(the_date, "-")
set the_year to (item 1 of y_m_d)
set the_month to (item 2 of y_m_d)
set the_day to (item 3 of y_m_d)
set the_exif_year to the_year & " " & the_month & " " & the_day
set the_exif_date to the_exif_year & " " & the_exif_time
return EXIFDateDecode(the_exif_date)
end convert_date
on EXIFDateDecode(iPhotoDate) -- converts EXIF dates into AppleScript Date objects
-- original subroutine by Joe Maller <http://www.joemaller.com>
-- authored March 2005
-- licensed under Creative Commons Attribution Non Commercial ShareAlike 2.0
-- http://creativecommons.org/licenses/by-nc-sa/2.0/-- 1.1 Added a month key to workaround an ambiguity problem with some international date formats
-- 1.2 (May 2005) removed any English language dependencies from date rebuilding
-- 1.3 (May 2005) rebuilt date extraction for compatibility with older versions of Applescript
-- 1.5 (January 2006) Adapted for iPhoto 6, now checks to see if iPhotoDate is a date
--iPhoto 6 returns a date object instead of an exif-formatted string:
if class of iPhotoDate is date then return iPhotoDate
-- EXIF dates are always #### ## ## ##:##:## [-####], extract characters to desired places, translate months to words
if length of iPhotoDate < 19 then
return false -- fail on too short a supplied date
else
set monthList to {January, February, March, April, May, June, July, August, September, October, November, December} -- month constants, seems work internationally
set theDate to "1/1/1 2:2:2" -- save a call to "current date"
set theDate to date theDate
set month of theDate to item (text 6 thru 7 of iPhotoDate) of monthList
set day of theDate to text 9 thru 10 of iPhotoDate
set year of theDate to text 1 thru 4 of iPhotoDate
set time of theDate to ((text 12 thru 13 of iPhotoDate) * hours + (text 15 thru 16 of iPhotoDate) * minutes + (text 18 thru 19 of iPhotoDate))
return theDate
end if
end EXIFDateDecode
on get_all_photos()
-- return all the photos in iPhoto's library
tell application "iPhoto"
set all_the_photos to the photos of photo library album
return all_the_photos
end tell
end get_all_photos
on get_photo_filename(the_photo)
-- get the name of a photo from iPhoto
tell application "iPhoto"
tell the_photo
return the image filename
end tell
end tell
end get_photo_filename
on getElementFromPath(theXML, theElementPath)
-- extract an element from an arbitrary path into the document
if theElementPath is {} then
return theXML
else
local foundElement
set foundElement to getAnElement(theXML, item 1 of theElementPath)
if foundElement is not missing value and ¬
class of foundElement is XML element then
return getElementFromPath(foundElement, rest of theElementPath)
else
return missing value
end if
end if
end getElementFromPath
on getAnElement(theXML, theElementName)
-- find and return a particular element (this presumes there is only one instance of the element)
repeat with anElement in XML contents of theXML
if class of anElement is XML element and ¬
XML tag of anElement is theElementName then
return contents of anElement
end if
end repeat
return missing value
end getAnElement
on getNamedElement(theXML, theElementName, theName)
-- find and return the first element with a particular name attribute
if class of theXML is XML element or class of theXML is XML document then
repeat with anElement in XML contents of theXML
try
if class of anElement is XML element and ¬
XML tag of anElement is theElementName and ¬
|name| of XML attributes of anElement is theName then
return contents of anElement
end if
on error number -1728
-- ignore this error
end try
end repeat
else if class of theXML is list then
repeat with anElement in theXML
try
if class of anElement is XML element and ¬
XML tag of anElement is theElementName and ¬
|name| of XML attributes of anElement is theName then
return contents of anElement
end if
on error number -1728
-- ignore this error
end try
end repeat
end if
return missing value
end getNamedElement
on load_xml(the_file)
-- read in a file
set fRef to open for access file the_file without write permission
set the_contents to (read fRef)
close access fRef
return the_contents
end load_xml
on parse_it(the_xml_data)
-- parse XML data
set the_xml to parse XML the_xml_data
return the_xml
end parse_it
on string_to_list(the_string, the_delim)
-- a sort of strtok, where we break a string into elements at delimiters
my atid(the_delim)
set the_list to (every text item of the_string) as list
my atid("")
return the_list
end string_to_list
on atid(the_delim)
-- tell AppleScript what delimiter to use
set AppleScript's text item delimiters to the_delim
end atid