Skip to content

Instantly share code, notes, and snippets.

@kennonb
Last active August 29, 2015 14:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kennonb/39c049b19f4a3d8585ab to your computer and use it in GitHub Desktop.
Save kennonb/39c049b19f4a3d8585ab to your computer and use it in GitHub Desktop.
Send Mail Message to Todoist
property apiToken : "INSERT YOUR API KEY"
property allProjects : {}
property appName : "Skrypt todoist"
property appDomain : "me.pawel.script"
on run
tell application "Mail"
set _sel to get selection
set _links to {}
repeat with _msg in _sel
set _subj to "Follow-up email "
set _messageURL to "message://%3c" & _msg's message id & "%3e" & " (" & _msg's subject & ") "
set end of _links to _messageURL
end repeat
set AppleScript's text item delimiters to " "
--- set the clipboard to (_links as string)
set _itemlist to (_links as string)
end tell
set {text returned:textReturned, button returned:buttonReturned} to ¬
display dialog ¬
"Edit Todoist task for these messages…" with icon 1 buttons {"Cancel", "OK"} ¬
default button ¬
"OK" default answer _subj
if buttonReturned is "OK" then
--- set textReturnedMod to textReturned & " " & _messageURL
set textReturnedMod to textReturned & " " & _itemlist
my newTask(textReturnedMod)
else if buttonReturned is "Cancel" then
end if
(*
set {text returned:textReturned, button returned:buttonReturned} to ¬
display dialog ¬
"Enter Todoist task..." with icon 1 buttons {"Cancel", "OK"} ¬
default button ¬
"OK" default answer ""
*)
end run
on handle_string(s)
my newTask(s)
end handle_string
on newTask(taskString)
-- Parse for task parts
set parsedTask to {task:missing value, project:"INBOX", due:missing value}
set oldTIDs to (AppleScript's text item delimiters)
set AppleScript's text item delimiters to {"+", "#"}
set task of parsedTask to first text item of taskString
-- Get project
set AppleScript's text item delimiters to {"+"}
if (count of text items of taskString) is greater than 1 then
set stringPart to last text item of taskString
set AppleScript's text item delimiters to {"+", "#"}
set projectNameString to first text item of stringPart
set AppleScript's text item delimiters to {""}
if first character of projectNameString is "!" then
set newProject to true
set projectNameString to (rest of characters of projectNameString) as string
else
set newProject to false
end if
-- Find a matching project
set projectNames to my getProjectNames()
if newProject is true then
if projectNameString is in projectNames then
set matchedProject to my closestMatch(projectNameString, projectNames)
set project of parsedTask to result
else
my addProject(projectNameString)
set allProjects to {result}
set project of parsedTask to |name| of (item 1 of allProjects)
end if
else
try
set matchedProject to my closestMatch(projectNameString, projectNames)
set project of parsedTask to result
end try
end if
end if
set AppleScript's text item delimiters to {"#"}
if (count of text items of taskString) is greater than 1 then
set stringPart to last text item of taskString
set AppleScript's text item delimiters to {"+", "#"}
set due of parsedTask to first text item of stringPart
end if
set AppleScript's text item delimiters to oldTIDs
set requestString to "addItem?content=" & (my urlEncode(task of parsedTask))
log "Project: " & project of parsedTask
my getProjectIDByName(project of parsedTask)
set requestString to requestString & "&project_id=" & result
if due of parsedTask is not missing value then
set requestString to requestString & "&date_string=" & (my urlEncode(due of parsedTask))
end if
log "new task request string: " & requestString
my todoistRequest(requestString, apiToken)
end newTask
on addItem(itemContent, projectName)
try
set projectID to my getProjectIDByName(projectName)
on error
set projectID to my getProjectIDByName("INBOX")
end try
my todoistRequest("addItem?project_id=" & projectID & "&content=" & (my urlEncode(itemContent)), apiToken)
end addItem
on addProject(projectName)
set projectNameEncoded to my urlEncode(projectName)
my todoistRequest("addProject?name=" & projectNameEncoded, apiToken)
end addProject
on getProjects()
if (count of allProjects) is less than 1 then
set allProjects to my todoistRequest("getProjects", apiToken)
else
log "Already stored projects"
end if
return allProjects
end getProjects
on getProjectIDByName(projectName)
set theProjects to my getProjects()
repeat with aProject in theProjects
if |name| of aProject is projectName then return |id| of aProject
end repeat
end getProjectIDByName
on getProjectNames()
set theProjects to my getProjects()
set projectNames to {}
repeat with aProject in theProjects
set projectNames to projectNames & {|name| of aProject}
end repeat
end getProjectNames
on todoistRequest(request, token)
tell application "JSON Helper"
if request does not contain "?" then
set fullRequest to request & "?token=" & token
else
set fullRequest to request & "&token=" & token
end if
set JSONResponse to fetch JSON from "http://todoist.com/API/" & fullRequest with cleaning feed
if result is "" then error "Invalid or empty API response from " & request
return JSONResponse
end tell
end todoistRequest
-- encode string so it's URL-safe
on urlEncode(decodedString)
do shell script "echo " & quoted form of ¬
decodedString & " | /usr/bin/ruby -r cgi -e \"print CGI.escape(STDIN.read.strip).gsub('+','%20')\""
end urlEncode
-- decode URL encoded string
on urlDecode(encodedString)
do shell script "echo " & quoted form of ¬
encodedString & " | /usr/bin/ruby -r cgi -e \"print CGI.unescape(STDIN.read.strip).gsub('+',' ')\""
end urlDecode
-- Look for a string in an array of strings, preferring perfect match, prefix of string, suffix, or contains, respectively.
on closestMatch(needle, haystack)
-- Valid attributes are: case, diacriticals, hyphens, numeric strings, punctuation, white space
ignoring diacriticals, hyphens, punctuation and white space
if needle is in haystack then return needle
set beginsWithNeedle to {}
set endsWithNeedle to {}
set containsNeedle to {}
repeat with hay in haystack
if hay begins with needle then
set beginsWithNeedle to beginsWithNeedle & {hay}
else if hay ends with needle then
set endsWithNeedle to endsWithNeedle & {hay}
else if hay contains needle then
set containsNeedle to containsNeedle & {hay}
end if
end repeat
end ignoring
set allresults to beginsWithNeedle & endsWithNeedle & containsNeedle
log allresults
try
return first item of (beginsWithNeedle & endsWithNeedle & containsNeedle) as string
on error
error needle & " is not in search array."
end try
end closestMatch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment