Does anybody know how to script an alarm for an iCal to-do item? Although event alarms can be scripted, and to-do alarms can be assigned in iCal, there does not seem to be support for scripting to-do alarms.
I updated this code that i found online. It allows you to make an event (event must run alarm of this script), place a note in the notes section that says due …/… This will result in the TODO item due date. It makes a todo item, then deletes the event.
But if you have recurring events that you want to make todo items, it will default to the event date, and the event date will be the due date for the TODO item
(* This code belongs to Ryan Cuthbertson. Email igloo@internode.on.net
I would love to hear from you.
Licence:
You may use fragments or ideas from here in your own scripts. If the size of the fragment used in your script is appreciable (eg. the download subroutine) you must make acknowledgement of its source in your code, and if the script is to be distributed, in your read me/documentation or other appropriate place. If this sounds too restrictive, contact me for special permission.
If you wish to modify this code and use it for your own purpose, you may, provided you acknowledge this as the original version and do not publicly redistribute your version without permission. Only the original unmodified version with all its other files (eg. the Read me) can be redistributed.
Thank you!
Tested for iCal 1.5.5 (Panther) and 2.0.3 (Tiger)
Known probs:
Don't think it works right on repeating events. Not that it should... Recurring todos, ugh!
Version History:
1.0 Initial release
*)
property randomIdentifier : 68894652
-- ^ This is used by the "areYouMe" method which this script will attempt to call on the event's open file alarm file. The "areYouMe" method will return the random number which will be checked for equality by the main method.
--Else I could make this script an application and use (path to me as text).
--tell application "iCal" to activate
tell application "iCal" to set calList to every calendar
repeat with thisCal in calList
tell application "iCal" to set convertMePosList to uid of (every event in thisCal whose open file alarms is not {} and start date is less than or equal to (current date) + 20 * minutes)
-- convertMePosList must be a list of UIDs rather than iCal events because after an event is deleted, the list points to different events.
repeat with thisEventUID in convertMePosList
tell application "iCal"
set thisEvent to item 1 of (every event in thisCal whose uid is thisEventUID)
set attachedFiles to filepath of every open file alarm in thisEvent
end tell
repeat with attachedFile in attachedFiles
set attachedFile to text 17 thru end of attachedFile
set attachedFile to my decode_text(attachedFile)
set areYouMeResult to "" --for now
try
set attachedFile to (POSIX file attachedFile) as alias -- may fail if the file has been moved and because iCal is stupid for not updating the path by using the alias system.
set hopefullyMe to load script attachedFile
set areYouMeResult to areYouMe() of hopefullyMe
on error
--it seems the attached file is not me. No further action in this iteration.
end try
if areYouMeResult is equal to my randomIdentifier then
--thisEvent is an event requiring conversion.
tell application "iCal"
-- Make a new To Do item
set newTodoProps to {}
set todoSummary to summary of thisEvent
set todoDate to start date of thisEvent
if todoSummary starts with "start " or todoSummary starts with "begin " then
set todoSummary to text 7 thru end of todoSummary
end if
set newTodoProps to newTodoProps & {summary:todoSummary}
set todoURL to (url of thisEvent) as string
set newTodoProps to newTodoProps & {url:todoURL}
set newTodoProps to newTodoProps & {description:(description of thisEvent)}
-- Only works on Tiger :-( Don't tell Jonathon.
--get dueDate
set dueLine to "" --for now
repeat with thisPara in (every paragraph in (description of thisEvent as text))
if thisPara starts with "due" then set dueLine to thisPara as text
end repeat
if dueLine is not "" then
try
--dates start with a number
if first character of word 2 of dueLine is in "1234567890" then
set dueDateText to text from word 2 to last word of dueLine
else
-- eg. "due on 31/3/06"
set dueDateText to text from word 3 to last word of dueLine
end if
tell me to set dueDate to date dueDateText -- telling iCal doesn't work (?!)
set newTodoProps to newTodoProps & {due date:dueDate}
on error
display dialog "Couldn't work out the due date" buttons {"Cancel", "Set to none"} default button 2 with icon caution
end try
else --they didn't put a due date, make the event date the todo date.
set newTodoProps to newTodoProps & {due date:todoDate}
end if
make new todo at end of thisCal with properties newTodoProps
set myTodo to properties of the result
-- log (myTodo)
delete thisEvent
--display dialog "a todo was converted"
exit repeat --we don't need to check the other attachedFiles for thisEvent.
end tell
else
--It's not me that's attached. Must be some other script with a similar mechanism. Ignore and continue.
end if
end repeat
end repeat
end repeat
to areYouMe()
return randomIdentifier
end areYouMe
--Thanks to Apple for supplying the following code (which would not be necessary if iCal was better).
-- this sub-routine is used to decode text strings
on decode_text(this_text)
set flag_A to false
set flag_B to false
set temp_char to ""
set the character_list to {}
repeat with this_char in this_text
set this_char to the contents of this_char
if this_char is "%" then
set flag_A to true
else if flag_A is true then
set the temp_char to this_char
set flag_A to false
set flag_B to true
else if flag_B is true then
set the end of the character_list to my decode_chars(("%" & temp_char & this_char) as string)
set the temp_char to ""
set flag_A to false
set flag_B to false
else
set the end of the character_list to this_char
end if
end repeat
return the character_list as string
end decode_text
-- this sub-routine is used to decode a three-character hex string
on decode_chars(these_chars)
copy these_chars to {indentifying_char, multiplier_char, remainder_char}
set the hex_list to "123456789ABCDEF"
if the multiplier_char is in "ABCDEF" then
set the multiplier_amt to the offset of the multiplier_char in the hex_list
else
set the multiplier_amt to the multiplier_char as integer
end if
if the remainder_char is in "ABCDEF" then
set the remainder_amt to the offset of the remainder_char in the hex_list
else
set the remainder_amt to the remainder_char as integer
end if
set the ASCII_num to (multiplier_amt * 16) + remainder_amt
return (ASCII character ASCII_num)
end decode_chars