-
-
Save kennonb/39c049b19f4a3d8585ab to your computer and use it in GitHub Desktop.
Send Mail Message to Todoist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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