Hello all,
I’m relatively new to AppleScript and I’m just about finished with my first real script project! My intention all along has been to make the final script a “Folder Action” but for testing purposes it has been a droplet. It works fine as a droplet and I assumed that all I needed to do was switch out
“on open {upload_folder}” with “on adding folder items to this_folder after receiving added_items”
and
“end open” with “end adding folder items to”
But it seems that Folder Actions are not as simple as I expected. I’ve played around with some of the sample Folder Actions that are preinstalled and they work fine but when I try to write one that has very many variables assigned inside the script, my “Folder Actions” do nothing. What am I doing wrong? The help section on MacScripter specific to Folder Actions doesn’t seem to address my issue. Any suggestions or suggested sites I can go to for help on what I’m missing? This is killing me because I feel like I’m so close to finishing up this project!
Also, when you look over my script, please feel free to correct any inefficient coding you notice but please, please explain what you’ve changed and why, so I can follow along. Thanks.
NOTES: My script requires Stuffit Delux 10.0, Cyberduck and Mail. The folders that are added to this script require a specific naming strategy to work properly; Date_DesignerName_Printer. A specific example would be: 0823_Jessica_ABC
on adding folder items to this_folder after receiving added_items
tell application "Finder"
set folderName to name of added_items
set TID to " "
set AppleScript's text item delimiters to "_"
set designerName to text item 2 of folderName
--This line pulls the designer's name from the folder name.
set printerName to text item 3 of folderName
--This line pulls the printer's name from the folder name.
set AppleScript's text item delimiters to TID
if designerName is "Jon" then --This section finds out which designer is using the script and assigns his/her email to a variable.
set theDesignerEmail to "jon@misc.com"
else if designerName is "James" then
set theDesignerEmail to "james@misc.com"
else if designerName is "Jeff" then
set theDesignerEmail to "jeff@misc.com"
else if designerName is "Jessica" then
set theDesignerEmail to "jessica@misc.com"
end if
try --This section "stuffs" of "zips" the collected folders. (It is important to note that this section of the script works with Stuffit Delux 10.0, with the "Stuffit AVR" option turned "On".)
set only_folders to (every item of upload_folder whose kind is "Folder") as alias list
on error
set only_folders to (every item of upload_folder whose kind is "Folder") as alias as list
end try
if printerName is "ABC" then
repeat with i in only_folders
set theName to name of i
if length of theName is greater than 20 then
set AppleScript's text item delimiters to ""
set theName to (characters 1 through 20 of theName) as string
set AppleScript's text item delimiters to TID
end if
set the name of i to theName & ".zip"
end repeat
else
repeat with i in only_folders
set theName to name of i
if length of theName is greater than 20 then
set AppleScript's text item delimiters to ""
set theName to (characters 1 through 20 of theName) as string
set AppleScript's text item delimiters to TID
end if
set the name of i to theName & ".sit"
end repeat
end if
if printerName is "ABC" then --This section finds out which printer to upload the art to and assigns variables accordingly.
set thePrinterEmail to "contact@abc.com"
set theServer to "address name"
set theUser to "user name"
set thePassword to "password"
set theUploadFolder to ""
else if printerName is "DEF" then
set thePrinterEmail to "contact@def.com"
set theServer to "address name"
set theUser to "user name"
set thePassword to "password"
set theUploadFolder to "misc"
else if printerName is "GHI" then
set thePrinterEmail to "contact@ghi.com"
set theServer to "address name"
set theUser to "user name"
set thePassword to "password"
set theUploadFolder to ""
end if
set wait to true --This section is a repeat loop that delays the progression of the script until all folders are "stuffed" or "zipped" with Stuffit AVR.
repeat while wait is true
tell application "Finder"
if exists (items of folder added_items whose (class is folder)) then
delay 3
else
set wait to false
end if
end tell
end repeat
set upload_items to (every file of added_items whose kind is not "Folder") as alias list
if the number of items in the upload_items is greater than 0 then --This connects to the printer's FTP site.
with timeout of 600 seconds
tell application "Cyberduck"
activate
set theBrowser to (make new browser)
tell (theBrowser)
set theProtocol to "ftp"
set encoding to "UTF-8"
try
if theUploadFolder is "" then
connect to theServer with protocol theProtocol as user theUser with password thePassword
else
connect to theServer with protocol theProtocol as user theUser with password thePassword with initial folder theUploadFolder
end if
on error --This happens if it cannot connect to the FTP.
set errorSubject to "Your FTP upload has been delayed."
set errorMessage to "Your FTP connection failed on the first attempt.
Don't worry though, your trusty AppleScript will attempt to upload the art again in 5 minutes.
You will get a confirmation email to let you know if the upload was successful. You may need to contact the printer if this problem persists with their FTP Server."
tell application "Mail"
activate
set emailNotice to make new outgoing message with properties {subject:errorSubject, content:errorMessage}
tell emailNotice to make new to recipient at end of to recipients with properties {address:theDesignerEmail}
send emailNotice
end tell
delay 300
try
if theUploadFolder is "" then
connect to theServer with protocol theProtocol as user theUser with password thePassword
else
connect to theServer with protocol theProtocol as user theUser with password thePassword with initial folder theUploadFolder
end if
on error --This happens if it still cannot connect to the FTP.
set errorSubject to "Your FTP upload has been cancelled."
set errorMessage to "Your FTP connection failed on the second attempt.
It is possible that there is something wrong with your system; the G4 Server may be offline or the AppleScript may have an undefined error but it is most likely that the printers FTP is offline or experiencing problems.
You can try to upload the art from your own computer but you may need to contact the printer about their FTP Server."
tell application "Mail"
set emailNotice to make new outgoing message with properties {subject:errorSubject, content:errorMessage}
tell emailNotice to make new to recipient at end of to recipients with properties {address:theDesignerEmail}
send emailNotice
end tell
return
end try
end try --If the connection to the FTP was good.
repeat with theFile in upload_items
upload file theFile
end repeat
disconnect
end tell
quit
end tell
end timeout
end if
try --This sends the notification/confirmation email to the printer and the designer.
set only_PDFs to (every item of entire contents of added_items whose kind is "Adobe PDF document") as alias list
on error -- happens if there is only one
set only_PDFs to (every item of entire contents of added_items whose kind is "Adobe PDF document") as alias as list
end try
set AppleScript's text item delimiters to ", "
set file_list to (list folder added_items without invisibles) as string
set the_message to "This is an automatically generated Upload Status Notification.
Here are the files that were recently uploaded to your FTP site: " & file_list & "
ATTENTION: DO NOT reply to this message.This email was automatically sent to you from an unmonitored email account. All correspondence should be directed to: " & theDesignerEmail
set AppleScript's text item delimiters to TID
set theSubject to "New files were just uploaded to your FTP"
tell application "Mail"
activate
set emailNotice to make new outgoing message with properties {subject:theSubject, content:the_message}
tell emailNotice to make new to recipient at end of to recipients with properties {address:thePrinterEmail}
tell emailNotice to make new cc recipient at end of cc recipients with properties {address:theDesignerEmail}
tell emailNotice
tell content
repeat with aPDF in only_PDFs
make new attachment ¬
with properties {file name:aPDF} at after the last word of paragraph 5
end repeat
end tell
end tell
send emailNotice
end tell
set label index of added_items to 6 --This turns the folder green to signal that the upload is complete.
end tell
end adding folder items to
Before attacking the script itself which you said works with an ‘on open’ handler, a check on how you’re doing the folder action.
Folder Actions should be placed in your ~/Library/Scripts/Folder Action Scripts folder (your users script folder).
If no such folder exists, then you should go to /Library/Scripts/Folder Actions/ (the HD library folder) and run “Configure Folder Actions”. This will install a folder for you, but more important, it will produce a Contextual Menu Item for configuring Folder Actions.
Select the folder to which the action is to be applied. Control-Click or Right-Click on the folder and select “Configure Folder Actions …” and in the left pane of the window that appears select your folder, and in the right, add your script. Make sure that ‘Enable Folder Actions’ is checked.
Adam,
Didn’t I mention that I’ve used a number of the pre-installed Folder Actions? I did the process you mentioned to make those work but no such luck when transitioning my script. I even checked out the forum that dealt with AppleScript Folder Actions and they recommended all these things.
Adam and all,
I realize looking at my original post, it may be somewhat time consuming for any of you to take a close look at my entire script and help me out.
If you can, that’s great but I guess what this boils down to is…
Are there any special scripting rules for writing Folder Actions? In many of the sample folder action scripts there are “properties” established before the “on adding folder items to…” line. Is this significant? I guess I’m thinking that might be the problem I’m having. Any thoughts?
I should have known, I guess, as your script shows a good understanding of AppleScript, but you’d be surprised at how often the answer to those questions is “no”, so I always ask first.
With respect to your next post in the thread, there are no special rules you don’t seem to be observing, except this:
‘added_items’ is a list even for only one item. Try ‘set folderName to name of item 1 of added_items’.
Adam’s already pointed out that ‘added_items’ is a list, so you need to get the names of its items individually. Similarly, near the end of the script, you won’t be able to get ‘(every item of entire contents of added_items whose kind is “Adobe PDF document”) as alias list’, because ‘added_items’ is a list, not an alias or a Finder reference.
Elsewhere, you have 'set only_folders to ‘(every item of upload_folder whose kind is “Folder”) as alias list’, but you haven’t defined ‘upload_folder’. That will cause a fatal error too. Sadly, faulty scripts often fail silently when run in OS X unless they trap their own errors and display the messages themselves. If the system displayed error messages by default, scripts would be much easier to debug!
If ‘upload_folder’ is meant to be ‘this_folder’ (and it seems from your first post that it is), renaming items in it will retrigger the folder action, because the appearance of the new names in the folder will make the system think that more new items have been added.
For some reason, you’ve set ‘TID’ (your restoration variable for AppleScript’s text item delimiters) to a space. It should be set to whatever the delimiters happen to be before the script starts fooling with them them, though it doesn’t appear to cause any problems here:
set TID to AppleScript's text item delimiters
Those are the things I’ve found that are actually wrong in your script. There are a few other things that are sub-optimal, but you can worry about those when you’ve got the script working.
Adam,
Thank you for pointing out that “added_items” is a list. I’ve changed the script accordingly.
Nigel,
You’re right; I missed switching “upload_folder” to “added_items” when I was making my script vanilla for posting purposes.
As for these comments:
I’m not sure what to make of these comments. As Adam suggested, I’ve changed to:
set folderName to name of item 1 of added_items
But your comments about
seem to be wrong because I don’t have any problems with that section of the script when I’ve tested it. Could it be that the next statement in the try block
is catching this error you are talking about and that I’m just not noticing it?
This brings up a good point for clarification: Do I need to use this sort of construction…
try
set only_folders to (every item of upload_folder whose kind is "Folder") as alias list
on error
set only_folders to (every item of upload_folder whose kind is "Folder") as alias as list
end try
…when I’m trying to get a list of a particular kind? I read somewhere that I needed to do this in case there is only one item in the list. Is this an older legacy AppleScript thing that is no longer needed?
All,
I believe this may be the real issue that is holding things up when I transition this script to a Folder Action; Nigel touched on it here:
What do you think? Am I retriggering the folder action?
I was just reading the featured article on this sort of issue called
at www.MacScripter.net. If this is my problem, can this idea be applied to my situation?
After reading through it a couple times, I’m not quite sure why the Folder Action wouldn’t be triggered again when the folder is created. In my case, I will have to deal with the new compressed files and somehow keep them from triggering the folder action. Any thoughts?
There may have been some confusion over which folder was which. It’s a bit difficult to sort out what the script’s supposed to do when the variable names aren’t correct. Here’s an untested (and therefore unguaranteed) reworking of it, which I hope works and isn’t too far off-beam. I’ve taken it that the folders and files to be treated are all in a folder that’s dropped into the “watched” folder, and that it’s the dropped folder that has its label index set at the end.
The things I mentioned above have been corrected and any unanticipated errors (or errors in the script) should now be reported in a dialog rather than just causing the script to fail silently. If more than one folder’s dropped, they’re all treated. There’s also a check to make sure that the dropped items are folders. I’ve un-nested the ‘tell’ blocks to the applications, both to avoid any possible terminology conflicts and for general clarity.
on adding folder items to this_folder after receiving added_items
-- Activate these apps before starting on the repeat loop.
tell application "CyberDuck" to activate
tell application "Mail" to activate
try
repeat with this_item in added_items
-- Check that the item's a folder and process it if it is.
set {isFolder, isPackage, itemName} to {folder, package folder, name} of (info for this_item)
if (isFolder) and not (isPackage) then
do_the_business(this_item, itemName)
end if
end repeat
on error errMsg -- Attempt to catch and display any unresolved errors.
display dialog errMsg
end try
tell application "CyberDuck" to quit
tell application "Mail" to quit
end adding folder items to
on do_the_business(this_folder, folderName)
set TID to AppleScript's text item delimiters
set AppleScript's text item delimiters to "_"
set designerName to text item 2 of folderName
--This line pulls the designer's name from the folder name.
set printerName to text item 3 of folderName
--This line pulls the printer's name from the folder name.
set AppleScript's text item delimiters to TID
if designerName is "Jon" then --This section finds out which designer is using the script and assigns his/her email to a variable.
set theDesignerEmail to "jon@misc.com"
else if designerName is "James" then
set theDesignerEmail to "james@misc.com"
else if designerName is "Jeff" then
set theDesignerEmail to "jeff@misc.com"
else if designerName is "Jessica" then
set theDesignerEmail to "jessica@misc.com"
end if
if printerName is "ABC" then
set new_extn to ".zip" as Unicode text
else
set new_extn to ".sit" as Unicode text
end if
tell application "Finder"
set only_folders to every folder of this_folder -- Don't need aliases here. The Finder understands its own references.
repeat with i in only_folders
set theName to name of i
if length of theName is greater than 20 then
set theName to text 1 through 20 of theName
end if
set the name of i to theName & new_extn
end repeat
if printerName is "ABC" then --This section finds out which printer to upload the art to and assigns variables accordingly.
set thePrinterEmail to "contact@abc.com"
set theServer to "address name"
set theUser to "user name"
set thePassword to "password"
set theUploadFolder to ""
else if printerName is "DEF" then
set thePrinterEmail to "contact@def.com"
set theServer to "address name"
set theUser to "user name"
set thePassword to "password"
set theUploadFolder to "misc"
else if printerName is "GHI" then
set thePrinterEmail to "contact@ghi.com"
set theServer to "address name"
set theUser to "user name"
set thePassword to "password"
set theUploadFolder to ""
end if
set wait to true --This section is a repeat loop that delays the progression of the script until all folders are "stuffed" or "zipped" with Stuffit AVR.
repeat while wait is true
if exists (items of this_folder whose (class is folder)) then
delay 3
else
set wait to false
end if
end repeat
try -- Aliases *are* required for use by CyberDuck.
set upload_items to (every file of this_folder) as alias list
on error
set upload_items to first file of this_folder as alias as list
end try
end tell
if the number of items in the upload_items is greater than 0 then --This connects to the printer's FTP site.
with timeout of 600 seconds
tell application "Cyberduck"
activate
set theBrowser to (make new browser)
tell (theBrowser)
set theProtocol to "ftp"
set encoding to "UTF-8"
repeat with attempt from 1 to 2 -- Allow two connection attempts.
try
if theUploadFolder is "" then
connect to theServer with protocol theProtocol as user theUser with password thePassword
else
connect to theServer with protocol theProtocol as user theUser with password thePassword with initial folder theUploadFolder
end if
-- If no error so far (ie. successful connection), upload the files, disconnect, and exit repeat
repeat with theFile in upload_items
upload file theFile
end repeat
disconnect
exit repeat
on error -- This happens if it cannot connect to the FTP.
if (attempt is 1 then) -- First attempt failed.
set errorSubject to "Your FTP upload has been delayed."
set errorMessage to "Your FTP connection failed on the first attempt.
Don't worry though, your trusty AppleScript will attempt to upload the art again in 5 minutes.
You will get a confirmation email to let you know if the upload was successful. You may need to contact the printer if this problem persists with their FTP Server."
send_error_email(errorSubject, errorMessage, theDesignerEmail)
delay 300
else -- Second attempt failed too.
set errorSubject to "Your FTP upload has been cancelled."
set errorMessage to "Your FTP connection failed on the second attempt.
It is possible that there is something wrong with your system; the G4 Server may be offline or the AppleScript may have an undefined error but it is most likely that the printers FTP is offline or experiencing problems.
You can try to upload the art from your own computer but you may need to contact the printer about their FTP Server."
send_error_email(errorSubject, errorMessage, theDesignerEmail)
end if
end try
end repeat
end tell
end tell
end timeout
end if
tell application "Finder" -- Aliases needed here too.
try --This sends the notification/confirmation email to the printer and the designer.
set only_PDFs to (every item of entire contents of this_folder whose kind is "Adobe PDF document") as alias list
on error -- happens if there is only one
set only_PDFs to (every item of entire contents of this_folder whose kind is "Adobe PDF document") as alias as list
end try
end tell
set AppleScript's text item delimiters to ", "
set file_list to (list folder this_folder without invisibles) as string
set AppleScript's text item delimiters to TID
set the_message to "This is an automatically generated Upload Status Notification.
Here are the files that were recently uploaded to your FTP site: " & file_list & "
ATTENTION: DO NOT reply to this message.This email was automatically sent to you from an unmonitored email account. All correspondence should be directed to: " & theDesignerEmail
set theSubject to "New files were just uploaded to your FTP"
tell application "Mail"
activate
set emailNotice to make new outgoing message with properties {subject:theSubject, content:the_message}
tell emailNotice to make new to recipient at end of to recipients with properties {address:thePrinterEmail}
tell emailNotice to make new cc recipient at end of cc recipients with properties {address:theDesignerEmail}
tell emailNotice
tell content
repeat with aPDF in only_PDFs
make new attachment ¬
with properties {file name:aPDF} at after the last word of paragraph 5
end repeat
end tell
end tell
send emailNotice
end tell
tell application "Finder" to set label index of this_folder to 6 --This turns the folder green to signal that the upload is complete.
end do_the_business
on send_error_email(errorSubject, errorMessage, theDesignerEmail)
tell application "Mail"
set emailNotice to make new outgoing message with properties {subject:errorSubject, content:errorMessage}
tell emailNotice to make new to recipient at end of to recipients with properties {address:theDesignerEmail}
send emailNotice
end tell
end send_error_email
Nigel,
You got the idea! This is exactly what I intended. You were right on your assumption that the target files and folders are inside the dropped folder with the label index. Your reworking of my script works very well with one minor edit and one continued problem.
This line…
on error -- This happens if it cannot connect to the FTP.
if (attempt is 1) then -- First attempt failed.
set errorSubject to "Your FTP upload has been delayed."
set errorMessage to "Your FTP connection failed on the first attempt.
…needed “then” pulled outside the paranthesis. Easy fix.
The problem I’m still having is that the confirmation email sent at the end does not attach the PDFs:
tell application "Mail"
activate
set emailNotice to make new outgoing message with properties {subject:theSubject, content:the_message}
tell emailNotice to make new to recipient at end of to recipients with properties {address:thePrinterEmail}
tell emailNotice to make new cc recipient at end of cc recipients with properties {address:theDesignerEmail}
tell emailNotice
tell content
repeat with aPDF in only_PDFs
make new attachment ¬
with properties {file name:aPDF} at after the last word of paragraph 5
end repeat
end tell
end tell
send emailNotice
end tell
Seems strange to me! I can’t see why it wouldn’t attach them. Any thoughts?
Regardless of these minor issues, I can’t thank you enough for “getting me over the hump” on this script. I am totally thrilled that this is working as well as it is. Thanks for your help Nigel!
Jacques,
You are spot on! The issue is that I’m droping files on this folder from another computer that sees these files as file type “Adobe PDF document” but the station with the Folder Action dropped folder does not have any Adobe product loaded, not even Adobe Reader, so it sees the PDFs as file type “PDF Document”.
tell application "Finder" -- Aliases needed here too.
return kind of files of this_folder
try --This sends the notification/confirmation email to the printer and the designer.
set only_PDFs to (every item of entire contents of this_folder whose kind is in {"Adobe PDF document", "PDF Document"}) as alias list
on error -- happens if there is only one
set only_PDFs to (every item of entire contents of this_folder whose kind is in {"Adobe PDF document", "PDF Document"}) as alias as list
end try
end tell
NOTE: It needed to be “PDF Document”, rather than “Document PDF”.
Thanks for the help!
A slight issue has popped up…
Whenever the script runs it does everything I want it to but I get a dialog box that says:
This dialog box pops up near the end of the script’s execution while it is sending the email notification. The email is sent by “Mail” and properly inserts all of the text that I’ve designed it to and even attaches the appropriate PDFs. As I mentioned, there are really no problems with the script but I’d like to keep this box from popping up. I’m also slightly concerned that this might be a part of a larger issue that I’m just not seeing yet.
Remember, for anyone wanting to look into this further, this script requires Stuffit Delux 10.0, Cyberduck and Mail. The folders that are added to this script require a specific naming strategy to work properly; Date_DesignerName_Printer. A specific example would be: 0905_Jessica_ABC