I’m writing a simplistic AI-ish system (Not really AI, just sounds catchy) for my laptop. It has the ability to wake me up in time to get ready for university lectures and keeps me organised with my schedule. It is however far from finished and I am constantly working on it.
It consists of a number of files and I’m not certain I’ve got all of them here. I’m afraid you’ll have to pick apart the appropriate file paths yourself in most cases…
MAIN SCRIPT (I made this script’s icon invisible and it runs at login.)
property lastMarker : 0
property StartupVarsLocation : ""
property CalanderVarsLocation : ""
property QueuesLocation : ""
property Username : ""
property thePassword : ""
property OwnerName : ""
-----------------------------------------------------
on run
set lastMarker to -1
set varFile to load script alias StartupVarsLocation
set myTime to starttime of varFile
set hr to hours of (current date)
set min to minutes of (current date)
set dywrd to weekday of (current date) as text
set dynum to day of (current date)
set mnth to month of (current date) as text
if (time of (current date)) - 5 * minutes < myTime and (time of (current date)) + 5 * minutes > myTime then
if varFile's wakeup is 1 then
tell application "System Preferences" to activate
tell application "System Events"
get properties
tell process "System Preferences"
click menu item "Sound" of menu "View" of menu bar 1
delay 2
set theRows to row 1 of table 1 of scroll area 1 of ¬
tab group 1 of window "sound"
set theOutputs to (value of text field 1 of row 1 of table 1 of scroll area 1 of ¬
tab group 1 of window "sound" as text)
quit
end tell
end tell
if theOutputs is "Headphones" then
set volume output volume 1
else
set volume output volume 5
end if
if hr > 4 then
if theOutputs is "Headphones" then
set volume output volume 2
else
set volume output volume 10
end if
end if
if hr > 6 then
if theOutputs is "Headphones" then
set volume output volume 4
else
set volume output volume 25
end if
end if
if hr > 8 then
if theOutputs is "Headphones" then
set volume output volume 8
else
set volume output volume 50
end if
end if
delay 1
tell application "System Preferences" to quit
set startdelay to (time of (current date)) - myTime
set varFile's startdelay to varFile's startdelay & {startdelay}
speakTxt("Good morning " & OwnerName & ", the time is " & hr & " " & min & ". The date is " & dywrd & " the " & dynum & "th of " & mnth & ".")
tell application "iTunes"
set sound volume to 100
tell playlist "Morning" to play
end tell
end if
end if
set varFile's wakeup to 0
store script varFile in alias StartupVarsLocation with replacing
set calFile to load script alias CalanderVarsLocation
set CalanderEvents to calFile's CalanderEvents
try
if CalanderEvents is not {} then
set outList to {}
repeat with i from 1 to the number of items in CalanderEvents
if eventDate of item i of CalanderEvents < (current date) then
if repeatT of item i of CalanderEvents is not "None" then
set outList to outList & repeatItem(item i of CalanderEvents)
end if
else
set outList to outList & item i of CalanderEvents
end if
end repeat
set calFile's CalanderEvents to outList
store script calFile in alias CalanderVarsLocation with replacing
end if
on error
set CalanderEvents to {CalanderEvents}
if CalanderEvents is not {} then
set outList to {}
repeat with i from 1 to the number of items in CalanderEvents
if eventDate of item i of CalanderEvents > (current date) then
set outList to outList & item i of CalanderEvents
end if
end repeat
set calFile's CalanderEvents to outList
store script calFile in alias CalanderVarsLocation with replacing
end if
end try
end run
on snooze()
tell application "iTunes" to stop
do shell script ("brightness 0")
delay (43200 - (time of (current date)))
do shell script ("brightness 1")
tell application "iTunes" to tell playlist "Morning" to play
speakTxt("Good afternoon " & OwnerName & ", you've had a snooze. The time is " & hr & " " & min & ". The date is " & dywrd & " the " & dynum & "th of " & mnth & ".")
end snooze
----------------------------------------------------------------------------
on idle {}
(*Load defaults*)
set calFile to load script alias CalanderVarsLocation
set CalanderEvents to calFile's CalanderEvents
(*Check for upcoming event*)
if CalanderEvents is not {} then
try
repeat with i from 1 to the number of items in CalanderEvents
if date string of (current date) is date string of eventDate of item i of CalanderEvents then
if eventDate of item i of CalanderEvents < ((current date) + 3 * minutes) then
beep 3
Handle(item i of CalanderEvents)
set saved to {}
repeat with j from 1 to (the number of items in CalanderEvents)
if j is not i then
set saved to saved & item j of CalanderEvents
end if
end repeat
set calFile's CalanderEvents to saved
store script calFile in alias CalanderVarsLocation with replacing
end if
end if
end repeat
on error
if date string of (current date) is date string of eventDate of CalanderEvents then
if eventDate of CalanderEvents < ((current date) + 3 * minutes) then
Handle(CalanderEvents)
set calFile's CalanderEvents to {}
store script calFile in alias CalanderVarsLocation with replacing
return 1
end if
end if
end try
end if
(*Check for new wake time*)
if calFile's UpdateMarker is not lastMarker then
set calFile's UpdateMarker to lastMarker
set cwake to (lateWakeTime of Defaults of calFile) + (wakeupTime of Defaults of calFile)
try
repeat with i from 1 to (the number of items in CalanderEvents)
if time of (eventDate of item i of CalanderEvents) < ((lateWakeTime of Defaults of calFile) + (wakeupTime of Defaults of calFile)) then
if ((current date) + 24 * hours) > (eventDate of item i of CalanderEvents) then
if every character of eventFlags of item i of CalanderEvents does not contain "n" then
set cwake to time of (eventDate of item i of CalanderEvents)
end if
end if
end if
end repeat
on error
if time of (eventDate of CalanderEvents) < ((lateWakeTime of Defaults of calFile) + (wakeupTime of Defaults of calFile)) then
if ((current date) + 24 * hours) > (eventDate of CalanderEvents) then
if every character of eventFlags of CalanderEvents does not contain "n" then
set cwake to time of (eventDate of CalanderEvents)
end if
end if
end if
end try
set waketime to cwake - (wakeupTime of Defaults of calFile)
set startupFile to load script alias StartupVarsLocation
(*clear Pmsets*)
repeat
set pmsettings to (do shell script ("pmset -g sched"))
if pmsettings is not "No scheduled events." then
set pmslist to words 4 thru -1 of paragraph 2 of pmsettings
try
do shell script ("sudo pmset schedule cancel poweron \"" & item 1 of pmslist & "/" & item 2 of pmslist & "/20" & item 3 of pmslist & " " & item 4 of pmslist & ":" & item 5 of pmslist & ":" & item 6 of pmslist & "\"") as text user name Username password thePassword with administrator privileges
on error e
display dialog "sudo pmset schedule cancel poweron \"" & item 1 of pmslist & "/" & item 2 of pmslist & "/20" & item 3 of pmslist & " " & item 4 of pmslist & ":" & item 5 of pmslist & ":" & item 6 of pmslist & "\"" & " Failed. " & e
end try
else
exit repeat
end if
end repeat
(*pick a day*)
if ((hours of (current date)) * hours > (calFile's Defaults's lateWakeTime) - 3200) then
set wakeday to ((current date) + 1 * days)
else
set wakeday to (current date)
end if
(*pmset*)
(*day, month & year*)
set mon to (month of (wakeday) as number)
set dy to (day of (wakeday))
set yr to characters 3 thru 4 of ((year of (wakeday)) as text)
if dy < 10 then
set dy to "0" & dy
end if
if mon < 10 then
set mon to "0" & mon
end if
(*Basic settings*)
set startupFile's starttime to waketime
set startupFile's wakeup to 1
(*start-up delay compensation*)
if startupFile's startdelay is not {} then
set val to 0
repeat with i from 1 to (the number of items in startupFile's startdelay)
set val to val + (item i of startupFile's startdelay)
end repeat
set val to round (val / (the number of items in startupFile's startdelay))
set waketime to waketime - val
end if
set startupFile's settime to waketime
(*format time*)
set hrs to leading0((round (waketime / 3600) rounding down)) as text
set mins to leading0((round (((waketime / 3600) - hrs) * 60))) as text
set secs to leading0(waketime - (mins * 60) - (hrs * 3600)) as text
(*Do tasks*)
store script startupFile in alias StartupVarsLocation with replacing
try
do shell script ("sudo pmset schedule poweron \"" & mon & "/" & dy & "/" & yr & " " & hrs & ":" & mins & ":" & secs & "\"") as text user name Username password thePassword with administrator privileges
end try
end if
(*Check online calander*)
return 60
end idle
on leading0(val)
if val < 10 then
set val to "0" & val
end if
return val
end leading0
(*Basic delegator*)
on Handle(thisEvent)
delay (time of eventDate of thisEvent) - (time of (current date))
set endspch to flagparse(eventFlags of thisEvent)
speakTxt(eventMessage of thisEvent)
delay 5
set queue to load script QueuesLocation
set SpeechStyle of queue to endspch
store script queue in QueuesLocation with replacing
end Handle
on flagparse(flags)
set queue to load script QueuesLocation
set reset to SpeechStyle of queue
set flaglist to (every character of flags)
considering case
if "g" is in flaglist then
set queue to load script QueuesLocation
set SpeechStyle of queue to "Voice"
store script queue in QueuesLocation with replacing
else if "G" is in flaglist then
set SpeechStyle of queue to "Growl"
set reset to SpeechStyle of queue
store script queue in QueuesLocation with replacing
else if "v" is in flaglist then
set queue to load script QueuesLocation
set SpeechStyle of queue to "Voice"
store script queue in QueuesLocation with replacing
else if "V" is in flaglist then
set queue to load script QueuesLocation
set SpeechStyle of queue to "Voice"
set reset to SpeechStyle of queue
store script queue in QueuesLocation with replacing
else if "a" is in flaglist then
set queue to load script QueuesLocation
set SpeechStyle of queue to "AFK"
store script queue in QueuesLocation with replacing
else if "A" is in flaglist then
set queue to load script QueuesLocation
set SpeechStyle of queue to "AFK"
set reset to SpeechStyle of queue
store script queue in QueuesLocation with replacing
end if
if "m" is in flaglist then
set volume 0 output volume 0 with output muted
end if
if "s" is in flaglist then
set volume output volume (Decharacitate(flaglist as text))
end if
end considering
return reset
end flagparse
on speakTxt(inputValues)
set queue to load script QueuesLocation
set SpeechQueue of queue to SpeechQueue of queue & inputValues
store script queue in QueuesLocation with replacing
ignoring application responses
tell application "Ultimate AI Speech Subsystem" to run
end ignoring
end speakTxt
on diag(Ddata)
set queue to load script QueuesLocation
set queue's dialogCont to Ddata
store script queue in QueuesLocation with replacing
try
tell application "Ultimate AI Dialog Subsystem" to activate
end try
repeat (Ddata's Dtimeout) + 2 times
delay 1
set queue to load script QueuesLocation
if queue's dialogCont is not Ddata then
return queue's dialogCont
end if
end repeat
end diag
(*Extract numbers from string*)
on Decharacitate(swissCheese)
set phrase to (every character of swissCheese)
set output to ""
repeat with i from 1 to (the number of items in phrase)
if item i of phrase is in {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"} then
set output to output & item i of phrase
end if
end repeat
return output
end Decharacitate
CALANDER VARIABLES SCRIPT (Stores event data)
property Defaults : {wakeupTime:(75 * minutes), travelTime:(20 * minutes), sleepNeeded:(8 * hours), lateWakeTime:(9 * hours + 30 * minutes)}
property CalanderEvents : {}
property CurrentDayType : "Workday"
property UpdateMarker : 0
STARTUP VARIABLES SCRIPT (Stores startup data)
property starttime : 0
property wakeup : 0
property speakers : 0
property settime : 0
property startdelay : {}
SPEECH SUBSYSTEM SCRIPT(save as app, needs ‘image magick’ for AFK mode and proper command modification. Also makes the voice sound flat. Any idea where I can get a good, free voice not standard with mac?)
property QueuesLocation : ""
set queue to load script QueuesLocation
set MyQueue to SpeechQueue of queue
set SpeechQueue of queue to {}
store script queue in QueuesLocation with replacing
set i to 0
repeat
set i to i + 1
set queue to load script QueuesLocation
if SpeechQueue of queue is not {} then
set MyQueue to MyQueue & SpeechQueue of queue
set SpeechQueue of queue to {}
store script queue in QueuesLocation with replacing
end if
if SpeechStyle of queue is "Voice" then
try
say (item i of MyQueue) using "Victoria" modulation 0
on error
exit repeat
end try
else if SpeechStyle of queue is "Growl" then
try
tell application "GrowlHelperApp"
set the allNotificationsList to {"Basic Notification"}
set the enabledNotificationsList to {"Basic Notification"}
register as application "Michelle" all notifications allNotificationsList default notifications enabledNotificationsList icon of application "Finder"
notify with name "Basic Notification" title "Michelle AI" description item i of MyQueue application name "Michelle"
end tell
on error
exit repeat
end try
else if SpeechStyle of queue is "AFK" then
try
do shell script ("/opt/local/bin/convert ~/Code\\ Box/Applescript/Automation/Ultimate\\ AI/Interface\\ Items/baseimage.gif -pointsize 50 -background green -fill white -font Chalkduster-Regular label:'" & item i of MyQueue & "' -append ~/Code\\ Box/Applescript/Automation/Ultimate\\ AI/Interface\\ Items/baseimage.gif")
do shell script ("/opt/local/bin/convert ~/Code\\ Box/Applescript/Automation/Ultimate\\ AI/Interface\\ Items/baseimage.gif -bordercolor black -border 2x2 -bordercolor '#774411' -border 20x20 ~/Desktop/BlackBoard.gif")
on error
exit repeat
end try
end if
end repeat
DIALOG SUBSYSTEM (save as app, very buggy, basically unused.)
property QueuesLocation : ""
set queue to load script alias QueuesLocation
activate
set queue's dialogCont to (display dialog Dtext of queue's dialogCont buttons Dbuttons of queue's dialogCont giving up after Dtimeout of queue's dialogCont default button 1)
store script queue in QueuesLocation with replacing
CALENDAR EVENT ADDER (Do whatever with it.)
property CalanderVarsLocation : "Reaver:Users:fisto:Code Box:Applescript:Automation:Ultimate AI:Variable files:Calander Vars.scpt"
(*set defaults*)
(*get date*)
set eventDate to (words 2 thru 4 of (date string of (current date)))
(*get time*)
set eventDate to eventDate & every word of (time string of (current date))
(*eventDate = {"26", "September", "2010", "10", "54", "14"} format *)
(*User input*)
(*Date and time*)
set eventDate to every word of (the text returned of (display dialog "Date and time:" default answer (item 1 of eventDate & " " & item 2 of eventDate & " " & item 3 of eventDate & " " & item 4 of eventDate & ":" & item 5 of eventDate)))
(*message*)
set eventMessage to the text returned of (display dialog "Message:" default answer "")
(*special flags*)
set flags to (choose from list {"Set Output", "Growl", "Voice", "AFK", "Mute", "Volume", "No Wake", "Uni"} with multiple selections allowed and empty selection allowed) as list
(*Parse flags to single chars*)
(*Format: g/G,v/V,a/A,f,m,n,s (+args) Caps is for set output.*)
set fstring to ""
if "Growl" is in flags then
if "Set Output" is in flags then
set fstring to fstring & "G"
else
set fstring to fstring & "g"
end if
end if
if "Voice" is in flags then
if "Set Output" is in flags then
set fstring to fstring & "V"
else
set fstring to fstring & "v"
end if
end if
if "Afk" is in flags then
if "Set Output" is in flags then
set fstring to fstring & "A"
else
set fstring to fstring & "a"
end if
end if
if "Mute" is in flags then
set fstring to fstring & "m"
end if
if "Volume" is in flags then
set fstring to fstring & "s" & (the text returned of (display dialog "Volume level (0-100):" default answer "50"))
end if
if "No Wake" is in flags then
set fstring to fstring & "n"
end if
(*patch values together*)
(*date*)
set formattedDate to date (item 1 of eventDate & " " & item 2 of eventDate & " " & item 3 of eventDate & " " & item 4 of eventDate & ":" & item 5 of eventDate)
(*Uni flag*)
set calFile to load script alias CalanderVarsLocation
if "Uni" is in flags then
set formattedDate to formattedDate - (travelTime of Defaults of calFile)
end if
(*Make and save record*)
set calFile's UpdateMarker to (calFile's UpdateMarker) + 1
if the number of items in calFile's CalanderEvents is 0 then
set calFile's CalanderEvents to {eventType:"Event", eventMessage:eventMessage, eventDate:formattedDate, eventFlags:fstring}
else if item 1 of every item of calFile's CalanderEvents is in {"Event", "AutoEvent"} then
set calFile's CalanderEvents to {calFile's CalanderEvents} & {{eventType:"Event", eventMessage:eventMessage, eventDate:formattedDate, eventFlags:fstring}}
else
set calFile's CalanderEvents to calFile's CalanderEvents & {{eventType:"Event", eventMessage:eventMessage, eventDate:formattedDate, eventFlags:fstring}}
end if
store script calFile in alias CalanderVarsLocation with replacing
I repeat, work in progress! It’s quite buggy but the main features work fine. Add an appointment/task/event and it will turn the laptop on in time to wake you up and give you the time specified in the calendar variables script to dress and eat, add a ‘uni’ event and it’ll give 20 mins to get there, it compensates for laptop startup time, and it plays music when you wake (itunes playlist ‘Morning’). The basics are there.
I will start working on chat bot type helpers (makes sure the messages are important if I’m busy, if I choose to ignore someone, they are muted, checks who’s online and tells me if certain people arrive… Problem: Adium dosen’t let you interact with messages much…), a special search system with natural language to find relevant google results, Wolfram alpha data and files/folders or even torrents and facebook + addressbook + other people related information searches and anything else I can think of.