Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Applescript to post webhooks triggered by newly completed iOS reminders in specific list(s)
--Look for newly completed reminders (since the last check) and if there is a new one, make a webhook post with date, title, and list JSON values
--by Robert W. Leach, based on scripts by Craig Eley, Samantha Hilton, and Nick Morris
--This is not foolproof. If you have more than 1 device you use to "complete" reminders and a reminder is completed while offline, after which, a reminder is completed from a second online device, the completion of the reminders in the offline device (once it comes online) will be missed. However, it's done this way so that the script doesn't take forever looking at all reminders each time.
--Schedule it to run as frequently as you would like using osascript in a cron job and forget about it. Run once manually in order to "allow" this script to run in the security settings by responding to the resulting dialog.
--Cron job every 30 minutes looking for newly completed reminders in list "MyReminders" example (execute `crontab -e` in terminal and enter): */30 * * * * osascript /Users/username/Scripts/completion_notifier.scpt "/Users/username/reminder_completions.txt" "" -1 "MyReminders"
--Run without command line arguments to get the usage
--Command line argument examples:
-- "~/completed_reminders.txt" --No spaces allowed in file path. File does not need to pre-exist (but directories do).
-- "{event}/with/key/{key}" --Empty = don't make a webhook call (for testing)
-- -1 --Priority level cutoff. -1 = all. 1 = !, 2 = !!, 3 = !!!. Considers only reminders with priority greater than this value.
-- "ToDo" --Empty = all. Example: "Grocery" "ToDo" "Work" "Home" - only provided lists are checked for newly completed items
on run argv
set debug to false
if (count of argv) is less than 3 then
return "Usage: osascript completion_notifier.scpt \"/path/to/outfile.txt\" \"http://webhook_url\" priority_level [reminder list names...]" & linefeed & "Example: osascript completion_notifier.scpt \"/Users/jsmith/completed_reminders.txt\" \"\" -1"
end if
set lastcompletionfile to item 1 of argv
set webhookurl to item 2 of argv
set prilev to item 3 of argv
set liststocheck to {}
if (count of argv) is equal to 4 then
set liststocheck to {item 4 of argv}
else if (count of argv) is greater than 3 then
set liststocheck to {items 4 thru (count of argv) of argv}
end if
tell application "Reminders"
set {startdate, firsttime} to my getStart(lastcompletionfile)
if debug is true then
display dialog "Starting datetime: " & startdate as text
end if
set output to ""
set lastcompletion to startdate
set mostrecentdate to ""
set mostrecenttitle to ""
set mostrecentlist to ""
--Find entries completed today from each list
set hasOne to false
repeat with alist in every list
set mylist to name of alist as text
if (count of liststocheck) is 0 or liststocheck contains mylist then
--set listid to id of alist as text
if debug is true then
--display dialog mylist & linefeed & listid
display dialog mylist
end if
repeat with reminderObj in (reminders in alist whose (completed is true) and (completion date is greater than startdate) and (priority is greater than prilev))
set nameObj to name of reminderObj
set compDateObj to completion date of reminderObj
set timeStr to date string of compDateObj & " at " & time string of compDateObj
--set idObj to id of reminderObj
if compDateObj is greater than lastcompletion then
set hasOne to true
set lastcompletion to compDateObj
set mostrecentdate to timeStr
set mostrecenttitle to nameObj
set mostrecentlist to mylist
end if
if debug is true then
display dialog idObj & tab & timeStr & tab & nameObj
end if
--set output to output & listid & tab & idObj & tab & timeStr & tab & mylist & tab & nameObj & linefeed
set output to output & timeStr & tab & mylist & tab & nameObj & linefeed
if debug is true then
--display dialog listid & tab & idObj & tab & timeStr & tab & mylist & tab & nameObj
display dialog timeStr & tab & mylist & tab & nameObj
end if
end repeat
end if
end repeat
if hasOne is true then
--save the newly completed items found this time so that next time, we can look for newer items
set shellTxt to "echo \"" & output & "\" > " & lastcompletionfile
if debug is true then
display dialog shellTxt
end if
do shell script shellTxt
--Make the webhook call (if the webhookurl is not an empty string)
if webhookurl is not "" then
--Use this example to send json data
--set shellScript to "curl -X POST --data-urlencode 'payload={\"channel\": \"#general\", \"username\": \"Completion Notifier Bot\", \"icon_emoji\": \":ghost:\"}' " & webhookurl
set jsonoption to "--data-urlencode 'payload={\"value1\": \"" & mostrecentdate & "\", \"value2\": \"" & mostrecenttitle & "\", \"value3\": \"" & mostrecentlist & "\"}'"
set shellTxt to "curl -X POST " & jsonoption & " \"" & webhookurl & "\" > /dev/null"
if debug is true then
display dialog shellTxt
end if
do shell script shellTxt
end if
--Save the date this was run so it can be parsed later the next time it's run
if firsttime is true then
set shellTxt to "echo \"" & startdate & tab & "initial run" & tab & "no completed reminders" & linefeed & "\" > " & lastcompletionfile
if debug is true then
display dialog shellTxt
end if
do shell script shellTxt
end if
if debug is true then
display dialog "Nothing is newly completed"
end if
end if
end tell
end run
--Takes the file containing the last determined most recent completion date (since the last time this script ran).
--Returns from the file, the most recent reminder completion date and a boolean indicating whether write an initial start record into the file
on getStart(lastcompletionfile)
set startdate to the current date
set checkscript to "if [ -e \"`eval echo " & lastcompletionfile & "`\" ]; then echo yes; else echo no; fi"
--display dialog checkscript
set fileisthere to first paragraph of (do shell script checkscript)
--display dialog lastcompletionfile & " exists? [" & fileisthere & "]"
set gotone to false
if fileisthere is equal to "yes" then
set lastdate to missing value
set datescript to "cut -f 3 " & "\"`eval echo " & lastcompletionfile & "`\""
--display dialog datescript
set datelines to paragraphs of (do shell script "cut -f 1 " & "\"`eval echo " & lastcompletionfile & "`\"")
repeat with adateline in datelines
--display dialog "Checking [" & adateline & "]"
set tmpdate to date adateline
if lastdate is missing value or tmpdate is greater than lastdate then
set lastdate to tmpdate
set gotone to true
--display dialog "Later: " & lastdate as text
end if
end try
end repeat
if gotone is true then
--display dialog "Setting start date: " & lastdate as text
set startdate to lastdate
end if
end if
--display dialog "Returning start date: " & startdate as text
return {startdate, not gotone}
end getStart
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment