Applescript value increment detection - applescript

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.

Related

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

Run a script for a determied amount of time

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

Set Messages (iChat) status to song currently playing in Rdio

I have the following script that successfully retrieves the current track and updates my Messages (iChat) status, but for this to work autonomously I guess I need to run it on a loop? Recommendations for that?
tell application "Rdio"
set theTrack to current track
set theArtist to artist of theTrack
set theName to name of theTrack
end tell
tell application "Messages"
if status is available then
set status message to ("♫ Playing in Rdio: " & (theArtist as string) & " - " & (theName as string))
end if
end tell
Unless Rdio has the ability to trigger scripts on certain condition (which you would have to check for yourself, as I am not a Rdio user myself – the rather sparse Rdio AppleScript docs on site do not indicate anything about that), your best chance to achieve this is to store your script as a Stay-Open AppleScript Application and put the script proper in the on idle handler. The AppleScript Language Guide has the nitty-gritty on this, if you want to look it up, but the basic procedure is:
wrap your script above in an on idle handler, i.e.:
on idle
tell application "Rdio"
set theTrack to current track
set theArtist to artist of theTrack
set theName to name of theTrack
end tell
tell application "Messages"
if status is available then
set status message to ("♫ Playing in Rdio: " & (theArtist as string) & " - " & (theName as string))
end if
end tell
return 0 -- change this to stray from the default 30 sec. interval
end idle
save the script as an AppleScript Application, making sure you check Stay open in the saving sheet.
Launch your newly created AppleScript app, and you are good to go – it will keep running, executing the idle handler periodically (every 30 seconds by default – you can change that value by returning an integer value from the idle handler, which will be evaluated as the number of seconds until the next check. If you want to be fancy, and the Rdio AS interface supports it, you could use the remaining playing time of your song, say…)

Resources