Newbie AppleScript Automation Question

Hi,

I’m very new to Macs and attempting to perform some minor automation. My code is below. Feel free to laugh at my mistakes, but please help me out.

I’m attempting to read a webpage every minute for the word sale, and if so, send myself a text via iMessage with a link to the URL. I’m not worried about and end time because I can just kill the script. I could have it run for a week but not sure how to.

In the example below I’m using Google, but it could be any page that has the word sale on it for testing purposes. I also want to check the site every minute.

I know the texting code works as I had it running successfully in a separate script. Can you please provide guidance/assistance with this?

This first bit of code is my SendMessage script. It gets called from my second script below

on run {targetBuddyPhone, targetMessage}
   tell application "Messages"
      set targetService to 1st account whose service type = iMessage
      set targetBuddy to participant targetBuddyPhone of targetService
      send targetMessage to targetBuddy
   end tell
end run

This second script is where I’m attempting to open a webpage, look for the word sale, and text me if the word exists. I’d like to check the site every minute and only send a text if there’s a sale. I’m not too worried about all of the texts in case there is a sale because I can mute the conversation (text) on my iPhone (I thought about sending a text for the first 10 mins but that’s far too advanced for me).

Any assistance would be greatly appreciated as I’m a windows guy trying to implement this on a mac

set word1 to "Sale"
tell application "Safari"
   activate
   tell application "System Events"
      open location "https://www.google.com"
      set tabContent to text of it
         if word1 is in tabContent then
              display dialog "Sale!" & osascript SendMessage.scpt 5555551234 
                              "https://www.google.com"
               else
                display dialog "No Sale..."
         end if
   end tell
end tell

I’d do that rather with curl or something like that on the command line, something like
(curl -s https://www.google.com | grep -q Sale) && osascript SendMesage.scpt ...

Explanation:

  • curl -s <URL> downloads the content from the given URL and writes it to standard output
  • | grep -q Sale reads from standard input and searches for the word “Sale”. If it does, the whole parenthesis returns true.
  • In that case, the && osascript part is executed, && meaning “and”

You could wrap that in a shell script like

#!/bin/bash
while 1 ; do
curl ...
sleep 60
done

(Note that this script stuff is just off the top of my hat). That runs the curl line every 60 seconds, as requested.

Thanks Chrillek. I’ve extremely new to this so bear with me…

I didn’t throw the command line into a bash shell- I have to take baby steps.

Your curl command is quite helpful, thank you! If the site had two words, such as Flash Sale, how would I handle that in the curl statement?

And out of curiosity, what if I wanted to negate the command, such as send the imessage if Sale is not on the webpage, is that possible as well?

Thanks

Adjust the grep to something like that grep -q "The list of words I'm looking for". Note that you must include them in single or double quotes if they contain spaces. So, grep -q FlashSale finds “FlashSale” while grep -q "Flash Sale" finds “Flash Sale”.

That’s more tricky. You could, of course, use if and test for that (see any text on shell programming for that). But does “not Sale” mean “not Sale in any form, including Flash Sale”?

Thank you again for all of your help so far!

But does “not Sale” mean “not Sale in any form, including Flash Sale”?

Correct, the site actually says “Thanks for Checking” if there is no sale, or simply lists items being sold (without the word sale). So for initial explaining, that’s why I used the word “Sale”.

I thought for this purpose, getting the code to work in reverse might have been easier. I don’t think I need to negate though if an if/else can be used, thanks.

If I did what you suggest, would it look like this?

#!/bin/bash
while 1 ; do
(curl -s https://www.google.com | grep -q "Thanks for checking") 
if 
grep -q Thanks for "checking" 
else
osascript SendMesage.scpt 5555551234
sleep 60
done

No. Firstly, please enclose your code in three backticks like so:
```
code goes here
```
That makes it stand out, enables highlighting and easier copying.

It seems that my explanation in the first part was not clear enough. This
(curl -s https://www.google.com | grep -q “Thanks for checking”)
results in a true-ish value if the web document fetched by curl contains the string “Thanks for checking”. But you don’t do anything with this true-ish value. It’s there, and then it’s gone.

The pipe symbol | is used to connect two programs so that the output of the first (curl in this case) becomes available as input to the second (grep in this case). The parenthesis group the whole thing together. In my original script they made sure that the and operator (&&) used the return value of the curl ... grep pipe. Basic logic: if there curl/grep combo fails, the first part of the and is false. Therefore, the whole and expression can never become true, and is second part is not executed. Only if the curl/grep combo is true, ie the string was found, will the second part of the and be executed, namely your script.

Now you use an if without a test condition, which will cause a syntax error in bash. The next line runs grep -q “Thanks for checking”) on standard input. Which is empty in this moment. So, grep will wait for anything to appear on standard input. Not going to happen, because the script does not provide anything for grep to read at this moment. So this grep would makes the script wait forever or until you stop it. Not that it really matters since there was a syntax error right before…

If you want to run your script when the string is found, use the double ampersand as in my first example. If you want it to run when the string is not found, we’ll have to use a slightly different approach. What is it?

In the meantime, reading up about basic shell programming might be helpful (assuming that others explain the concepts better than I do).

Now responding from my mobile, so I’ll be brief. Will be back in front of my laptop in 1hr

When “thanks for checking” is found, I want the script to continue to run but not text me anything. If “thanks for checking” is Not found, that’s when I want it to text me.

Hey Guys,

Keep in mind that cURL will only pick up static web pages and won’t pick up any dynamically loaded content.

-Chris

Lots to unpack here.

While I generally agree with using something like curl to get the (static) web page, and grep for the filtering, I find the logic processing in bash is a PITA, at least compared to AppleScript.

As such I’d go for a hybrid model:

set thePhone to "12025558927"
set word1 to "Sale"

on idle
	-- use shell to curl the page and look for the keyword
	set itemsOnSale to do shell script "curl -s " & theURL & " | grep -q Sale"
	-- this will return an empty string if the keyword is not found, or a string of text showing the keyword
	
	-- use AppleScript to do the rest
	if itemsOnSale is not "" then -- we have a match!
		my sendAMessage(thePhone, theURL)
	end if
	
	-- come back in 1 minute
	return 60
end idle

on sendAMessage(targetBuddyPhone, targetMessage)
	tell application "Messages"
		set targetService to 1st account whose service type = iMessage
		set targetBuddy to participant targetBuddyPhone of targetService
		send targetMessage to targetBuddy
	end tell
end sendAMessage

Saved as a Stay Open script, the idle loop keeps the script running indefinitely, with the ‘return 60’ telling it to re-run in 60 seconds. Alternatively you can keep it within a simple repeat loop