Run a script for a determied amount of time - macos

I'd like to run an applescript for a determined amount of time.
When the counter reaches 0 the script should stop working.
I've found online a timer code like this one:
set input to text returned of (display dialog "Enter length of timer" default answer "")
delay input
beep
But instead of waiting for that amount of time I'd like to perform all the cycles and actions of my script. Is there any easy way to achieve that?

set start to current date
repeat
say "a"
if (current date) - start ≥ 3 then exit repeat
delay 1
end repeat

Related

Applescript value increment detection

I'm using midi messages to trigger Applescript commands via MidiPipe. Midi messages contains 3 items and I want to trigger a command when the value of the third item increments +1
if (item 1 of message = 176) then
if (item 2 of message = 97) then
if (item 3 of message + 1) then -- this doesn't work
tell application "System Events"
key code 126
It works when the value I want is fixed but I don't know how to detect positive or negative increments (range 0-127)
AppleScript doesn't have anything automatic like that. It would be up to you to keep track of what the previous value was, compare/update to what it is now, and take the appropriate action. You don't mention how the script is called or any state you are keeping, but your snippet would be something like:
property previous : missing value -- keep track of the previous value
if previous is missing value then set previous to item 3 of message -- initial value
-- other stuff
if item 1 of message = 176 then
if item 2 of message = 97 then
set change to (item 3 of message) - previous -- get any difference
if change < 0 then set change to -change -- absolute value
if change is not 0 and change = 1 then -- or whatever threshold comparison
set previous to item 3 of message -- update
tell application "System Events"
key code 126
-- other stuff
end tell
end if
end if
end if
I don't have MidiPipe to test, but if the script won't keep persistent properties, you will need to do something like read from a file or use NSUserDefaults to keep the value of the previous variable between runs.

How do I add a simple counter to a repeating action in apple script (script editor)

Basically I have a script that im running on my mac using script editor to prevent my character from be kicked due to AFK. Here is what I have right now.
delay 5
repeat 10000 times
tell application "System Events"
key down "w"
delay (random number from 0.5 to 1)
key up "w"
key down "s"
delay (random number from 0.5 to 1)
key up "s"
delay (random number from 20 to 30)
end tell
end repeat
Basically I just want to add a counter so I can see how long it has been running. Ideally it would show the total time elapsed and not the amount of times the script has been repeated, but either would work.

AppleScript Message Format -- Total fail on new line feed

I'm sending out a whole bunch of individual text messaged using AppleScript on a MacBook laptop linked to an iPhone.
If I create a message, copy paste it manually into Messages, and send that out manually, one message at a time (copy paste message, copy paste phone number, send) things works just fine. I can easily format the message in my draft, and the formatting is retained. If I try to do this via script, the linefeeds get lost.
Desired message:
Hello Everybody,
This is going to be a special meeting taking place on Friday, 10AM.
Please call in to the group meeting, access line xxxxxxxxxxx
Topic of Discussion: Quarterly Sales.
Great Job everybody, Sales are thru the roof this quarter; We're all
getting pay raises, yippee. Details shared at the meeting.
Again, thanks to all
Susan,
Sales Manager
And this is how it arrives.
Hello Everybody,This is going to be a special meeting taking place on
Friday, 10AM. Please call in to the group meeting, access line
xxxxxxxxxxxTopic of Discussion: Quarterly Sales. Great Job everybody,
Sales are thru the roof this quarter; We're all getting pay raises,
yippee. Details shared at the meeting. Again, thanks to all Susan,
Sales Manager
And here is the appleScript:
set textMessage to "Hello Everybody,\n\nThis is going to be a special meeting taking place
on Friday, 10AM. Please call in to the group meeting, access line xxxxxxxxxxx\n\nTopic
of Discussion: Quarterly Sales. \n\nGreat Job everybody, Sales are thru the roof this
quarter; We're all getting pay raises, yippee. Details shared at the meeting.
\n\nAgain, thanks to all \n\nSusan, \nSales Manager\n"
set phonelist to {"1999-555-6850", "1999-555-9496", "1999-555-7170", "1999-555-4445",
"1999-555-1182", "1999-555-7463", "1999-555-1809", "1999-555-8916", "1999-555-5139",
"1999-555-5252", "1999-555-6646", "1999-555-3642", "1999-555-2437", "1999-555-0755",
"1999-555-8732", "1999-555-6202", "1999-555-0310", "1999-555-7410", "1999-555-3300",
"1999-555-0655"}
set i to 0
activate application "Messages"
tell application "System Events" to tell process "Messages"
repeat with indPhone in phonelist
set i to i + 1
key code 45 using command down -- press Command + N to start a new window
keystroke indPhone -- input the phone number
delay 1
key code 36
key code 36 -- press Enter to focus on the message area
keystroke textMessage -- type some message
delay 1
key code 36 -- press Enter to send
say i
delay 5 -- Audio plus delay = success tracking.
-- If for some reason something goes wrong, I know where I am.
-- e.g. phone rings during the process.
end repeat
end tell
Note: reference.
Note#2. Oh, and note this isn't the actual message being sent. It's just a contrived sample for StackOverflow. This audience receiving the messages just doesn't understand what happens when someone replies to a group message. They just don't get it, sigh. So no, group text pages are NOT the answer. We want individual text messages, one per person. But thanks for that suggestion. Typically we're sending out just less than 100 messages with this technique, at one time.
Any thoughts on why we're losing the \n formatting when this runs as a script? If you run this exact script on your Mac, do you see the same results?
Edit: I'm going to share some screen shots off the phone.
What I want (created via manual copy & paste into Messages app):
Here's what I get with the script above (/n/n):
And here's what I get with the RobC & return & technique. (See comments)
Just dealing with the 'newline' problem... To get an inline carriage return you need to type control-return. To accomplish that with AppleScript, break the textMessage variable up into a list of paragraphs, then keystroke in each paragraph followed by key code 36 using control down to make the paragraph break.
set textMessageParts to {"Hello Everybody,", "", "This is going to be a special meeting taking place on Friday, 10AM. Please call in to the group meeting, access line xxxxxxxxxxx", "", "Topic of Discussion: Quarterly Sales.", "", "Great Job everybody, Sales are thru the roof this quarter; We're all getting pay raises, yippee. Details shared at the meeting. ", "", "Again, thanks to all", "", "Susan,", "Sales Manager"}
-- empty strings are added above to make two sequential line breaks
set phonelist to {"1999-555-6850", "1999-555-9496", "1999-555-7170", "1999-555-4445", "1999-555-1182", "1999-555-7463", "1999-555-1809", "1999-555-8916", "1999-555-5139", "1999-555-5252", "1999-555-6646", "1999-555-3642", "1999-555-2437", "1999-555-0755", "1999-555-8732", "1999-555-6202", "1999-555-0310", "1999-555-7410", "1999-555-3300", "1999-555-0655"}
set i to 0
activate application "Messages"
tell application "System Events" to tell process "Messages"
repeat with indPhone in phonelist
set i to i + 1
keystroke "n" using command down -- press Command + N to start a new window
keystroke indPhone -- input the phone number
delay 1
key code 36
key code 36 -- press Enter to focus on the message area
repeat with thisPara in textMessageParts
keystroke thisPara -- type one paragraph from the list
key code 36 using control down -- type an inline line break
end repeat
delay 1
key code 36 -- press Enter to send
say i
delay 5 -- Audio plus delay = success tracking.
-- If for some reason something goes wrong, I know where I am.
-- e.g. phone rings during the process.
end repeat
end tell
This code works (partially adapted from here):
set textMessage to "Hello Everybody,\n\nThis is going to be a special meeting taking place
on Friday, 10AM. Please call in to the group meeting, access line xxxxxxxxxxx\n\nTopic
of Discussion: Quarterly Sales. \n\nGreat Job everybody, Sales are thru the roof this
quarter; We're all getting pay raises, yippee. Details shared at the meeting.
\n\nAgain, thanks to all \n\nSusan, \nSales Manager\n"
set phonelist to {"1999-555-6850", "1999-555-9496", "1999-555-7170", "1999-555-4445",
"1999-555-1182", "1999-555-7463", "1999-555-1809", "1999-555-8916", "1999-555-5139",
"1999-555-5252", "1999-555-6646", "1999-555-3642", "1999-555-2437", "1999-555-0755",
"1999-555-8732", "1999-555-6202", "1999-555-0310", "1999-555-7410", "1999-555-3300",
"1999-555-0655"}
repeat with indPhone in phonelist
tell application "Messages"
set targetService to (id of 1st service whose service type = iMessage)
set theBuddy to buddy ("+1" & indPhone) of service id targetService
send textMessage to theBuddy
end tell
end repeat
So it turns out when I upgraded the macOS to Big Sur version 11.0.1 the script provided by Ted Wrigley crashed. Here is a corrected version, ready for copy paste.
set textMessageParts to {"Hello Everybody,", "", "This is going to be a special meeting taking place on Friday, 10AM. Please call in to the group meeting, access line xxxxxxxxxxx", "", "Topic of Discussion: Quarterly Sales.", "", "Great Job everybody, Sales are thru the roof this quarter; We're all getting pay raises, yippee. Details shared at the meeting. ", "", "Again, thanks to all", "", "Susan,", "Sales Manager"}
-- empty strings are added above to make two sequential line breaks
set phonelist to {"1999-555-6850", "1999-555-9496", "1999-555-7170", "1999-555-4445", "1999-555-1182", "1999-555-7463", "1999-555-1809", "1999-555-8916", "1999-555-5139", "1999-555-5252", "1999-555-6646", "1999-555-3642", "1999-555-2437", "1999-555-0755", "1999-555-8732", "1999-555-6202", "1999-555-0310", "1999-555-7410", "1999-555-3300", "1999-555-0655"}
set i to 0
activate application "Messages"
tell application "System Events" to tell process "Messages"
repeat with indPhone in phonelist
set i to i + 1
keystroke "n" using command down -- press Command + N to start a new window
delay 1
keystroke indPhone -- input the phone number
delay 1
key code 36
key code 36 -- press Enter twice to focus on the message area
repeat with thisPara in textMessageParts
keystroke thisPara -- paste one paragraph from the list
key code 36 using shift down -- insert an inline line break
end repeat
delay 1
key code 36 using command down -- press Command Enter to Send
log ("SMS completed: " & indPhone) -- Text completed to this phone #
say i -- audible progress feedback
delay 3 -- Delay to provide an opportunity to stop the script here.
-- If for some reason something goes wrong, I know where I am.
-- e.g. phone rings during the process.
end repeat
end tell
I wanted to add a few lessons learned in fixing this thing:
The log is probably a better way to track progress than an audio clue. You do have to make the log area visible in the Script Editor via top menu --> View --> Show Log. You will want to be in the "Messages Tab" to see the log entries.
key code {57, 36} is not the same as key code 36 using shift down. Not sure what's up with that. One method works, one does not.
Before you start the script / macro you need to ensure Messages is open and running on the MacOS.
You don't want to start the macro while Messages is half way complete with a previous message. Odd things happen.
Stopping the program while the macro is running is problematic. If you are stopping the action during the middle of a paste operation, the content intended for the Messages ends up pasted in the middle of the Script Editor. That was a total mess. If you must stop, ensure you haven't corrupted your original script.
For really long lists of phone numbers, you may need to use "option L" at end of each line as continuation character (¬) per S.O.63927015
Many thanks to Ted Wrigley for his input on the original question.

detecting any keystroke in applescript

I want my script to be listening/detecting any keystroke(any key pressed) via keyboard. If no key is pressed for about 5seconds, then continue to do something. Otherwise, keep on recording the keys pressed in a text edit.
Any help would be greatly appreciated.
Since you specified TextEdit in your question, I wrote a script for you that checks for changes in a TextEdit document within the specified number of seconds. Do note that this only detects keys that input something into the document, so it's not exactly what you wanted. However, there's no way to detect any and every key being pressed in raw AppleScript, so this is the closest you can get (unless someone wrote a Scripting Addition or agent application to do that).
Here's the script, hope it is of use:
global lastText, lastTime, startTime
on run
set lastText to application "TextEdit"'s (text of the document of the front window)
set lastTime to current date
set startTime to current date
repeat
if (checkForRecentTextUpdate given seconds:5) is true then
-- Do something while the user is typing
else
-- Do something after the user has stopped typing
exit repeat -- This is only an example
end if
end repeat
end run
to checkForRecentTextUpdate given seconds:secsRequired
tell application "TextEdit"
-- If midnight just passed, reset the last time
if (the day of (the current date)) > (the day of the lastTime) ¬
then set lastTime to current date
-- If we just started, we can't judge; give a positive
if ((the time of (the current date)) - (the time of the startTime)) < secsRequired ¬
then return true
-- If there have been changes since the last run, update info
if (the text of the document of the front window) ≠ the lastText then
set lastTime to the current date
set lastText to the text of the document of the front window
end if
-- If the specifiied number of seconds has passed without any text updates, give a negative
if ((the time of (the current date)) - (the time of the lastTime)) ≥ secsRequired ¬
then return false
-- If we got this far, there were changes in the seconds specified; give a positive
return true
end tell
end checkForRecentTextUpdate

Speech Recognition Server Does Not Stay Open

I am trying to create a simple program that loops for user speech input using com.apple.speech.recognitionserver. My code thus far is as follows:
set user_response to "start"
repeat while user_response is not equal to "Exit"
tell application id "com.apple.speech.recognitionserver"
set user_response to listen for {"Time", "Weather", "Exit"} with prompt
"Good Morning"
end tell
if user_response = "Time" then
set curr_time to time string of (the current date)
set curr_day to weekday of (the current date)
say "It is"
say curr_time
say "on"
say curr_day
say "day"
else if user_response = "Weather" then
say "It is hot outside. What do you expect?"
end if
end repeat
say "Have a good day"
If the above is run on my system it says good morning and it then pops up with the speech input system and waits for either Time, Weather, or Exit. They all do what they say they are going to do, but instead of looping if I say Time and Weather and asking again until I say exit the speechserver times out and never pops up again. Is there a way of either keeping that application open until the program ends or is applescript not capable of looping for user speech input?
If you don't find a way to keep speech recognition open, try adding a delay before you call it again. I recall (long ago) finding that events can be just lost if you try to send an event to an application that's already in the middle of quitting (it doesn't reopen the application).
Before your end Repeat add
tell application "SpeechRecognitionServer"
quit
end tell
After about 35 seconds it will repeat, it is slow as honey on a cold day but it works. give it a try.
Here is a Simple Example:
repeat
tell application "SpeechRecognitionServer"
set theResponse to listen for {"yes", "no"} with prompt "open a finder?"
set voice to (theResponse as text)
end tell
if voice contains "yes" then
tell application "Finder"
activate
end tell
else
say "not understood"
end if
tell application "SpeechRecognitionServer"
quit
end tell
end repeat

Resources