Hello again everybody,
I have been working on a script for a few weeks now that takes a .txt file (Work Roster) and creates calender events based on the shifts/break times, etc. (An example of the roster is visible on http://pastebin.ca/2358083)
I’ve already had a fair bit of assistance in making this from the very helpful Nigel Garvey, who is a legend on this thread: http://macscripter.net/viewtopic.php?id=40707
The script so far works fine when run on its own via AppleScript Editor, but attempting to make it work during a Mail rule has ultimately failed.
Here is a flow of how I’d expect it to function for every email matching a certain mail rule:
So far, it will work fine with checking the name of the attachments, saving them to a specific folder & trying to make the folders at first, with the script:
using terms from application "Mail"
on perform mail action with messages theselectedMessages
-- Check for the folders & make them if they do not exist
set theDownloadFolder to (path to downloads folder from user domain) as rich text
set theFolder to theDownloadFolder & "Lunch Rosters:"
try
tell application "Finder"
set p to theDownloadFolder
make new folder at p with properties {name:"Lunch Rosters"}
end tell
end try
try
tell application "Finder"
set p to theFolder
make new folder at p with properties {name:"LOB1"}
end tell
end try
try
tell application "Finder"
set p to theFolder
make new folder at p with properties {name:"LOB2"}
end tell
end try
-- get the home folder
set sandboxedhomeFolder to (path to home folder)
-- strip out the stupid sandboxed rubbish in the folder name
set homeFolder to (do shell script "echo " & sandboxedhomeFolder & " | sed 's/Librar.*//'")
-- add on the desired attachments folder (must be somewhere Mail can write to)
set attachmentsFolder to homeFolder & "Downloads:Lunch Rosters"
tell application "Mail"
repeat with theMessage in theselectedMessages
-- get the sender's name
set senderName to extract name from theMessage's sender
repeat with theAttachment in theMessage's mail attachments
set originalName to name of theAttachment
-- default to Tier 1
set tier2 to false
-- Check if the attachment is a tier 2 attachment
if ("T2" is in originalName or "Tier 2" is in originalName) then
set tier2 to true
end if
--if {originalName starts with "LOB1" or foobar starts with "goodbye"} then
if {originalName starts with "LOB1"} and (tier2 is true) then
set savePath to attachmentsFolder & ":LOB1:" & originalName
try
save theAttachment in savePath
end try
else if {originalName starts with "LOB2"} and tier2 is true then
set savePath to attachmentsFolder & ":LOB2:" & originalName
try
save theAttachment in savePath
end try
end if
end repeat
end repeat
end tell
end perform mail action with messages
end using terms from
But as soon as I try to make it do anything more complex, such as displaying dialogs and setting functions or global variables, it just ignores them.
So I’ve got the following as the script that works perfectly fine on its own; Here’s how this script currently works:
- Checks for existing plist folder & .plist
- If they don’t exist, creates them.
2a. For the plist, asks the user their name that shows up on the roster, and their line of business.
- Uses the information from the plist to set variables for use when gathering the user’s chunk of the roster.
- Creates calender entries for the roster.
-- ///Set all global variables
global thePlistFolderLocation
global userName
global thePlistFolder
global endRosterChunk
global theRoster
global theData
-- ///Set location variables
set thePlistFolder to "com.mat.bagoftricks"
set thePlistFolderLocation to (((path to application support from user domain) as text) & thePlistFolder & ":") as text
set thePlist to (((path to application support from user domain) as text) & thePlistFolder & ":info.plist") as text
set rosterRootFolder to (path to downloads folder from user domain as text) & "Lunch Rosters:"
set endRosterChunk to "____________________"
-- ///Check for existing folders, if they don't exist, make them.
if FileExists(thePlistFolderLocation) is false then
tell application "Finder"
set p to path to application support from user domain
make new folder at p with properties {name:thePlistFolder}
end tell
end if
-- ///If no plist exists, make one
if FileExists(thePlist) is false then
--Gather the user's roster name
--display dialog "What is your name in the roster?" default answer "example: 'Matthew Stares'"
display dialog "What is your name in the roster?" default answer "example: 'Matthew Stares'" with title "Bag of tricks setup" with icon 2
set userName to (text returned of result)
--Repeat until it is filled in
repeat while userName = "example: 'Matthew Stares'" or userName is null
display dialog "What is your name in the roster?" default answer "example: 'Matthew Stares'" buttons {"Ok"}
set userName to (text returned of result)
end repeat
--Check if user is in LOB1 or LOB2
display dialog "Are you LOB1 or LOB2?" buttons {"LOB1", "LOB2"} with title "Bag of tricks setup" with icon 2
set userLOB to button returned of result
if userName is not null then
-- Create the plist using the information provided
tell application "System Events"
set the parent_dictionary to make new property list item with properties {kind:record}
set this_plistfile to make new property list file with properties {contents:parent_dictionary, name:thePlist}
make new property list item at end of property list items of contents of this_plistfile with properties {kind:string, name:"RosterName", value:userName}
make new property list item at end of property list items of contents of this_plistfile with properties {kind:string, name:"RosterLineOfBusiness", value:userLOB}
set theRosterLocation to rosterRootFolder & userLOB & ":"
make new property list item at end of property list items of contents of this_plistfile with properties {kind:string, name:"RosterLocation", value:theRosterLocation}
end tell
end if
end if
-- Get the userName
-- Get the roster location
-- Get the time last run for the script
tell application "System Events"
-- Get the plist itself.
set p_list to property list file (thePlist)
-- Get the userName
set userName to value of property list item "RosterName" of p_list
-- Get the roster location
set theRosterLocation to value of property list item "RosterLocation" of p_list
-- Get the last run
set scriptRunTime to current date
make new property list item at end of property list items of contents of p_list with properties {kind:string, name:"LastRun", value:scriptRunTime}
set lastScriptRunTime to value of property list item "LastRun" of p_list
end tell
-- Get every roster that was created after the last scritp run
tell application "Finder"
-- set the folder, ignoring all the DS_Store files.
set the item_list to list folder theRosterLocation without invisibles
end tell
-- repeat for each roster file
repeat with i from 1 to number of items in the item_list
set theRoster to (theRosterLocation & (item i of item_list)) as alias
tell application "Finder"
set theFileDate to (the creation date of theRoster)
end tell
-- if the file was made since the last time the script was run
--if theFileDate > lastScriptRunTime then
-- Read this roster
set theData to (read theRoster)
if userName is in theData then
roster2iCal()
end if
--end if
end repeat
-- ///SET ALL FUNCTIONS HERE
-- Check if a file/folder exists.
on FileExists(thePath) -- (String) as Boolean
try
get thePath as alias
return true
on error
return false
end try
end FileExists
on makeEvent for theSummary from startDate to endDate between theseTimes given allday:allday
tell startDate to set {its hours, its minutes} to words 1 thru 2 of theseTimes
tell endDate to set {its hours, its minutes} to words 3 thru 4 of theseTimes
tell application "Calendar" to make new event at end of events of calendar "Test Roster" with properties {summary:theSummary, start date:startDate, end date:endDate, allday event:allday}
end makeEvent
on roster2iCal()
-- Isolate the section of text containing "my" roster.
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to userName
set theData to text from paragraph (count paragraphs of text item 1 of theData) to end of theData
set AppleScript's text item delimiters to endRosterChunk
set myRoster to paragraphs of text item 1 of theData
set AppleScript's text item delimiters to astid
tell application "Calendar" to activate
set startDate to (current date) -- Create a date object whose properties we'll set below.
set onVacation to false -- For convenience, start each rota week not already being on holiday!
repeat with thisLine in myRoster
if (thisLine contains "Vacation") then -- This line indicates a vacation day.
-- If already on vacation (this week), just advance the current end date.
-- Otherwise note the vacation start date and set the onVacation flag.
if (onVacation) then
set endDate to endDate + days
else
tell startDate to set {day, time, year, {its month, day}} to {1, 1, 2000 + (word 3 of thisLine), words 1 thru 2 of thisLine}
copy startDate to endDate
set onVacation to true
end if
else -- This line doesn't indicate a vacation day.
-- If it's the day after a vacation, make an all-day event for this week's portion of the entire vacation and unset the onVacation flag.
if (onVacation) then
makeEvent for "Vacation" from startDate to endDate between "00:01 00:01" with allday
set onVacation to false
end if
if ((count thisLine's contents's words) > 0) then
-- If thisLine's not blank, it contains either a date and "OFF", a date and shift and break details, or just break details.
if (thisLine contains "/") then -- It begins with a date.
-- Initialise start and end dates to the date.
tell startDate to set {day, year, {its month, day}} to {1, 2000 + (word 3 of thisLine), words 1 thru 2 of thisLine}
copy startDate to endDate
-- If the line contains "OFF", make an all-day event for it.
-- Otherwise make timed events for both the shift and the break.
if (thisLine contains "OFF") then
makeEvent for "Off" from startDate to endDate between "00:01 00:01" with allday
-- Check for public holiday
else if (thisLine contains "Public Holiday") then
makeEvent for "Public Holiday" from startDate to endDate between (text from word 5 to word 8 of thisLine) without allday
else if (thisLine contains "Overtime") then
--display dialog (thisLine)
--display dialog (text from word 5 to word 8 of thisLine)
set checkFirst to (text from word 5 to word 8 of thisLine)
set checkSecond to (text from word 11 to word 14 of thisLine)
-- Check if the line is the first one, or on the end of the shift.
if (checkFirst is equal to checkSecond) then
makeEvent for "Scheduled Overtime" from startDate to endDate between (text from word 5 to word 8 of thisLine) without allday
end if
else
makeEvent for "Available" from startDate to endDate between (text from word 5 to word 8 of thisLine) without allday
makeEvent for (word 9 of thisLine) from startDate to endDate between (text from word 10 to word 13 of thisLine) without allday
end if
else
if (thisLine does not contain userName) and (thisLine does not start with "Date") then
if (thisLine contains "Scheduled Overtime") then
makeEvent for "Overtime" from startDate to endDate between (text from word 3 to word 6 of thisLine) without allday
else
makeEvent for (word 1 of thisLine) from startDate to endDate between (text from word 2 to word 5 of thisLine) without allday
end if
end if
-- It's a line containing only break details.
-- Make a timed event for the break.
--makeEvent for (word 1 of thisLine) from startDate to endDate between (text from word 2 to word 5 of thisLine) without allday
--makeEvent for (word 1 of thisLine) from startDate to endDate between (text from word 2 to word 5 of thisLine) without allday
end if
end if
end if
end repeat
end roster2iCal
The .plist looks like this:
[b]If anyone could please help with getting the second script running INSIDE the mail rule script for every email that matches a mail rule… I would be extremely grateful!
The main reasoning behind doing it via the mail rule is so that the script doesn’t need a timer or to be always-running, it just purely adds new rosters when they come in.[/b]