Help me, please! S.O.S.

Hi!
I need urgent help! I have to write an AppleScript, which does the following:
The script gets the price of a stock, specified by the user, and if it reaches a limit given by the user, it sends a mail.
It gets the price from a specific homepage (http://www.bet.hu/onlinesz/10000122.html?uio=), searching for the name of the stock, and the price.
The user inputs are the name of the stock and the price, when it is reached, the user has to be warned (sending SMS or e-mail).
The main problem is for me, how to find a string on the homepage, how to get it’s price, and how to save it into a file. Well, okay, I don’t know, how to make the whole script, I am totally stuck.
If you have any other tool than AppleScript (Konfabulator, Dashboard, whatsoever…), it is also okay, but when it is possible, then AppleScript.
I have a deadline (15th of may 2005, it will be for my thesis), that’s why it is so urgent. If you have any working ideas, please send me a mail to csanakb@gmail.com.
Please, Help!

Browser: Safari 100
Operating System: Mac OS X (10.4)

Use do shell script curl to get the text of a web page into a text variable you can parse. Do you program at all? If so, post what you’ve got. If not, you’ll need an applescript book or check the list of consultants available on this site. You might also consider another language like php or realbasic if you know one of those.

Thanx for the quick reply!
All I have is a not-working code:
tell application “Safari”
ignoring case
set the URL of front document to “http://www.bet.hu/onlinesz/10000122.html?uio=
set theSource to source of front document
set AppleSript’s text item delimiters to “FOTEX”
set theSource to second text item of theSource
set AppleSript’s text item delimiters to “+”
set Reszveny to first text item of theSource
end ignoring
end tell

The problem is, I don’t want to search in the source code of the page, but if there is no other way, then it is okay.
The idea was cut the unnecessary information, so only the price remains. But your idea about getting the text into a file seems to be better, for me.
What do you mean by “use do shell script curl”? How to do that?

Browser: Safari 100
Operating System: Mac OS X (10.4)

This seems to work for me…

set sourceURL to "http://www.bet.hu/onlinesz/10000122.html?uio="
set sourceCode to (do shell script "curl " & sourceURL) as string

set AppleScript's text item delimiters to {">FOTEX</a>"}
set tmpSource to (text item 2 of sourceCode) as string

set AppleScript's text item delimiters to {"+"}
set tmpSource to (text item 2 of tmpSource) as string

set AppleScript's text item delimiters to {"<br>"}
set tmpValue to (text item 1 of tmpSource) as string

set AppleScript's text item delimiters to {""}

display dialog (("The current 'FOTEX' stock price is: " & tmpValue) as string)

The script above may hang a while and will display nothing while it is gathering data and parsing text. This project may be better suited to an applescript studio project, where you could provide a status bar and a message during processing that allows the user to see that something is happening while it computes.
j

do shell script just lets you call command line (OSX Unix Shell) utilities. You can type “man curl” in terminal.app to get some more info. It just gets web pages and returns the text.

You already figured out how to do the exact same thing using Safari, so good for you. curl is often faster because it doesn’t have to display the HTML response like Safari does, but otherwise there’s no critical advantage.

jobu’s response showed you how you can use curl and then set the text item delimitters to parse out bits of text. As long as some kind of text or HTML tags will consistantly surround the data you’re actually looking for, you should be able to get the right stuff.

Good luck with your project.

Here’s another way to do it:


tell application "Safari"
	set URL of document 1 to "http://www.bet.hu/onlinesz/10000122.html?uio="
	set paralist to every paragraph of text of document 1
	set paracount to count items of paralist
	repeat with i from 1 to paracount
		try
			if first word of item i of paralist is equal to "FOTEX" then
				if first word of item (i + 1) of paralist is equal to "HUF" then
					-- keep checking the structure until you've got what you want
					-- everything is dependent on the structure of the text
					-- as fotex occurs in several places you will have to make sure
					-- the right one is referenced
					set thePrice to item (i + 2) of paralist
				end if
			end if
		end try
	end repeat
	display dialog thePrice
end tell

Only you know which occurrence of FOTEX will get you to the right price (my hungarian is, unfortunately, nonexistent) so you’ll probably have to set the indexes into the paragraph list accordingly.

\ Limbo

Browser: Safari 412
Operating System: Mac OS X (10.4)

Hi!

Thx for the help. I have tried Jobu’s code, it worked well, although I had to rewrite it a littlebit to work perfectly. Here’s the code (maybe the ignoring case is superfluous):

tell application “Safari”
ignoring case
set sourceURL to “http://www.bet.hu/onlinesz/10000122.html?uio=
set sourceCode to (do shell script “curl " & sourceURL) as string
set AppleScript’s text item delimiters to {”>FOTEX“}
set tmpSource to (text item 2 of sourceCode) as string
set AppleScript’s text item delimiters to {”"right" nowrap>“}
set tmpSource to (text item 2 of tmpSource) as string
set AppleScript’s text item delimiters to {”“}
set tmpValue to (text item 1 of tmpSource) as string
set AppleScript’s text item delimiters to {”"}
display dialog (("The current ‘FOTEX’ stock price is: " & tmpValue) as string)
end ignoring
end tell

Limbo: I have tried your code also, but for some reason it just don’t want to work (it says, the variable thePrice is not defined). Maybe it is because of the structure of the page, but who knows…
I want ot make this program to check the page for changes with a 1 minute interval (check the page, then check it once again after 1 minute). Maybe with checking the time difference for the Mac clock…
I have another question: I want to make some interface to it, so I can give the program the input: stock name and the limit. Where can I find the AppleScript Studio, and how does it work (some documents, manuals, tutorials will do, if not, I will ask you :).
Once again thanks for the codes, folks.

Browser: Safari 100
Operating System: Mac OS X (10.4)

Yupp, thePrice is not defined if “FOTEX” is not found on the page, as the script is written. And it is not found because the page somehow is not fully loaded when it lists the paragraphs. Use the curl-version as it is a lot faster anyway.

To run the script at certain intervals is easy. You just put a idle handler in the script, like so:


on idle
-- do what you have to do
return 60
end idle

return 60 tells the system to wait for 60 seconds, then repeat.

On the installation DVD for Tiger there is an option to install developer stuff (XCode). Do that and you have complete access to AppleScript documentation, and AppleScript Studio and so on. However, I’d say that you have precious little time on your hand to learn interface programming in AppleScript Studio, so perhaps it is easier to just ask the user through a few simple “display dialog” when the script is started, like so:


display dialog "Enter stock name" default answer "FOTEX"
set theStock to text returned of the result
display dialog "Enter trigger price:" default answer "100"
set theTriggerPrice to text returned of the result
display dialog "Enter interval for checking in seconds:" default answer "60"
set theInterval to text returned of the result

and then use the variables instead of the literal strings in your script.

\ Limbo

Browser: Safari 412
Operating System: Mac OS X (10.4)

Limbo, this on idle stuff looks like a function. Do I have to call this function? Or should I just place it to the code in a proper place, and it will run automatically when processed?
The “interface” is working properly.
There is a question for everybody: I want to send a mail with the program. Does it work somehow by itself (for example is there a function in AppleScript which I call and it sends the mail)? Or can I use a free mailsystem on the internet, like Gmail, or Hotmail? I make the account for the program, but how can it log in and send a mail?
Or sholud I use the Mail application on the Mac?
What do you suggest?

Browser: Safari 100
Operating System: Mac OS X (10.3.7)

…and the idle does not want to work also, although I saved the script as stay-open application. It says “Expected “end” but found “on”.” What’s wrong? The code looks now as follows:

tell application “Safari”
ignoring case
on idle
set sourceURL to “http://www.bet.hu/onlinesz/10000122.html?uio=
set sourceCode to (do shell script “curl " & sourceURL) as string
set AppleScript’s text item delimiters to {symbola & theStock & symbolb}
set tmpSource to (text item 2 of sourceCode) as string
set AppleScript’s text item delimiters to {delimiter1}
set tmpSource to (text item 2 of tmpSource) as string
set AppleScript’s text item delimiters to {delimiter2}
set tmpValue to (text item 1 of tmpSource) as string
set AppleScript’s text item delimiters to {”"}
display dialog ({"A ", theStock, " reszveny aktualis arfolyama : " & tmpValue} as string) buttons {“OK”} default button “OK”
return 60
end idle
end ignoring
end tell

Browser: Safari 100
Operating System: Mac OS X (10.3.7)

Re: the question about sending mail…

I think the easiest way would be to script Mail.app, but you can also do it with shell script. (This is the same issue as deciding to use curl vs. scripting Safari.)

Do a search on this forum and you’ll find sample code for sending messages with mail.app.

If you want to get into Unix utilities and shell scripts you can pick up a book like “Learning Unix for Mac OS X” and read Technical Note TN2065: do shell script in AppleScript

re: why you’re having trouble with timeouts…
Not sure, I always cron stuff that needs to repeat, but the idle is better – i don’t know how to use it, though.

Why did you add the “tell safari” wrapper to your modification of jobu’s script? There doesn’t seem to be any need for safari since curl is doing all the web capture for you.

Hi again!

The idle handler is called by the system with the interval you set in the handlers return statement. That means the handler gets called automatically in a stay open script. The idle handler has to live on the root level of the script, so it cannot be nested into another handler or tell statement. Furthermore, Safari is not used at all, so you don’t have to tell it anything :slight_smile: “do shell script” is a standard addition so no application has to be told to do it either.
I could imagine organizing the script something like this:


property sourceURL : "http://www.bet.hu/onlinesz/10000122.html?uio="
property symbola : ">"
property symbolb : "</a>"
property delimiter1 : {"\"right\" nowrap>"}
property delimiter2 : {"</td>"}

on idle
	set stockToCheck to "FOTEX"
	set thePrice to getPrice(stockToCheck, sourceURL)
	display dialog ({"A ", stockToCheck, " reszveny aktualis arfolyama : " & thePrice} as string) buttons {"OK"} default button "OK"
	return 60
end idle

on getPrice(theStock, theUrl)
	set sourceCode to (do shell script "curl " & theUrl) as string
	set AppleScript's text item delimiters to {symbola & theStock & symbolb}
	set tmpSource to (text item 2 of sourceCode) as string
	set AppleScript's text item delimiters to {delimiter1}
	set tmpSource to (text item 2 of tmpSource) as string
	set AppleScript's text item delimiters to {delimiter2}
	set tmpValue to (text item 1 of tmpSource) as string
	set AppleScript's text item delimiters to {""}
	return tmpValue
end getPrice

Browser: Safari 412
Operating System: Mac OS X (10.4)

I just can’t get this code to work! I don’t see, what could be the problem, but the error message says that the variable theStock is not defined. Why? I made the variables to display, and the dialog was OK. The code looks now as follows (I know, it is a bit chaotic, because of the debugging):

property sourceURL : “http://www.bet.hu/onlinesz/10000122.html?uio=
property symbola : “>”
property symbolb : “”
property delimiter1 : {“"right" nowrap>”}
property delimiter2 : {“”}

display dialog “Melyik részvény árfolyamát figyeljem?” default answer “FOTEX”
set theStock to text returned of the result
display dialog theStock
display dialog “Milyen árfolyamnál küldjek figyelmeztetést?” default answer “1000”
set theTriggerPrice to text returned of the result
display dialog theTriggerPrice
display dialog “Eladásra vagy vételre játszik?” buttons {“Eladásra”, “Vételre”} default button 2
set veszElad to button returned of the result
display dialog veszElad

on idle
display dialog theStock
set thePrice to getPrice(theStock, sourceURL)
display dialog ({"A ", theStock, " reszveny aktualis arfolyama : " & tmpValue} as string) buttons {“OK”} default button “OK”
– if veszElad is “Vételre” then (this part defines the conditions for sending a mail)
– if theTriggerPrice >= tmpValue then
– sendMail(theAcc, theWarning)
– end if
– else
– if theTriggerPrice <= tmpValue then
– sendMail(theAcc, theWarning)
– end if
return 60
end idle

on getPrice(theShare, theURL)
set sourceCode to (do shell script “curl " & theURL) as string
set AppleScript’s text item delimiters to {symbola & theShare & symbolb}
set tmpSource to (text item 2 of sourceCode) as string
set AppleScript’s text item delimiters to {delimiter1}
set tmpSource to (text item 2 of tmpSource) as string
set AppleScript’s text item delimiters to {delimiter2}
set tmpValue to (text item 1 of tmpSource) as string
set AppleScript’s text item delimiters to {”"}
return tmpValue
end getPrice

– on sendMail(theAddress, theMessage) (this is the mail sending function, I never got to test it, whether it is working or not)
– tell application “Mail”
Рset newMessage to make new outgoing message with properties ¬
– {subject:“sms”, content:“api_id:XXXXXX
– user:XXXXXX
– password:XXXXXX
– from:XXXXXX
– to:41” & phone_string & “” & begintext & “” & midtext & “” & endtext}
– tell newMessage
– set visible to true
– set sender to “XXXXXXXXX XXX@XXX.com
–make new to recipient at end of to recipients with properties ¬¨
– {name:“sms@messaging.clickatell.com”, address:"sms@messaging.clickatell.com"}
– send newMessage
– end tell
– end tell

It seems to me that it still has problems with the idle, but I’m not sure. It can’t be saved as a script, not even as an application because of the bugs.

OK. Just add these lines at the beginning to make the variables properties instead. This way their value will be preserved through each idle cycle:

property theStock : “”
property theTriggerPrice : 1000
property veszElad : “”

\ Limbo

Everything seems to work except one thing: the price retrieved from the page is in a special format, for example 5880 is written as 5 880. So I can’t compare it with the trigger price. is there any space strip function in AppleScript (you know, if I use the function on the downloaded price it will get rid of the spaces in the number,
5 880 gets in, and 5880 goes out)? I hope it is clear, what I want to tell. And here is the code:

property theStock : “”
property theTriggerPrice : “1000”
property veszElad : “”
property sourceURL : “http://www.bet.hu/onlinesz/10000122.html?uio=
property symbola : “>”
property symbolb : “”
property delimiter1 : {“"right" nowrap>”}
property delimiter2 : {“”}
property mailAddress1 : “sms@messaging.clickatell.com
property mailAddress2 : “sardaukar@vipmail.hu”
property mailAddress3 : “infrared@freemail.hu”
property theAcc : “” – accTelszam

display dialog “Melyik részvény árfolyamát figyeljem?” default answer “FOTEX”
set theStock to text returned of the result
display dialog “Milyen árfolyamnál küldjek figyelmeztetést?” default answer “1000”
set theTriggerPrice to text returned of the result
display dialog “Eladásra vagy vételre játszik?” buttons {“Eladásra”, “Vételre”} default button 2
set veszElad to button returned of the result
display dialog “Irja be a telefonszámát, amire az értesítôt küldöm:” default answer “36”
set theAcc to text returned of the result

on idle
set thePrice to getPrice(theStock, sourceURL)
display dialog ({"A ", theStock, " reszveny aktualis arfolyama : " & thePrice} as string) buttons {“OK”} default button “OK”
if veszElad is “Vételre” then
if theTriggerPrice ≥ thePrice then – here is the problem, the term will be always true
– sendMail(theAcc)
display dialog theTriggerPrice & thePrice & veszElad
end if
else
if theTriggerPrice ≤ thePrice then – here is also problem, here will be the term always false
– sendMail(theAcc)
display dialog theTriggerPrice & thePrice & veszElad
end if
end if
return 60
end idle

on getPrice(theShare, theURL)
set sourceCode to (do shell script “curl " & theURL) as string
set AppleScript’s text item delimiters to {symbola & theShare & symbolb}
set tmpSource to (text item 2 of sourceCode) as string
set AppleScript’s text item delimiters to {delimiter1}
set tmpSource to (text item 2 of tmpSource) as string
set AppleScript’s text item delimiters to {delimiter2}
set tmpValue to (text item 1 of tmpSource) as string
set AppleScript’s text item delimiters to {”"}
return tmpValue
end getPrice

on sendMail(accTelszam)
tell application “Mail”
set newMessage to (make new outgoing message with properties ¬
{subject:“Reszveny arfolyam”, content:“api_id:584171
user:AFagens
password:warning522
from:Arfolyam Figyelo
to:” & accTelszam & "
text: A(z) " & theStock & " részvény árfolyama elérte a " & theTriggerPrice & " értéket"})
tell newMessage
– set visible to true
set sender to “Arfolyam Figyelo Mobile@t-online.hu
make new to recipient at end of to recipients with properties {name:“sms@messaging.clickatell.com”, address:mailAddress2}
send newMessage
end tell
end tell
end sendMail

The other parts work well (or at least I think so), but if you have any comment, please tell me (but please, be quick, the deadline is near!).


set t to "x yyy"
set AppleScript's text item delimiters to " "
set t to text items of t
set AppleScript's text item delimiters to ""
set t to t as string

-- t == "xyyy"

Well, meanwhile I overwhelmed the problem (it was the same as your solution :). And now it seems that the program is working properly.

Thanks for your help folks, it was really great! The program is done, it works well, except one thing, and this will be my last question: the price comparison (“if theTriggerPrice ≥ thePrice then” and “if theTriggerPrice ≤ thePrice then”) is only working with numbers that have the same digit count. A four digit number can only be compared with another four digit number, and is there is a five or three digit number, it can not compare the prices. Why?

The code is as follows:

 
property theStock : ""
property theTriggerPrice : "1000"
property veszElad : ""
property sourceURL : "http://www.bet.hu/onlinesz/10000122.html?uio="
property symbola : ">"
property symbolb : "</a>"
property delimiter1 : {"\"right\" nowrap>"}
property delimiter2 : {"</td>"}
property mailAddress1 : "sms@messaging.clickatell.com"
property mailAddress2 : "sardaukar@vipmail.hu"
property mailAddress3 : "infrared@freemail.hu"
property theAcc : ""
property errorAcc : "36703897029"
property theReturn : ""
property theMsg1 : ""
property errorMsg : "Hiba lepett fel futaskor! Ellenorizze a honlapot, vagy a Mail alkalmazast! A program leall!"
property sendDate : ""




display dialog "Melyik részvény árfolyamát figyeljem?" default answer "FOTEX"
set theStock to text returned of the result
display dialog "Milyen árfolyamnál küldjek figyelmeztetést?" default answer "1000"
set theTriggerPrice to text returned of the result
display dialog "Eladásra vagy vételre játszik?" buttons {"Eladásra", "Vételre"} default button 2
set veszElad to button returned of the result
display dialog "Irja be a telefonszámát, amire az értesítôt küldöm:" default answer "36"
set theAcc to text returned of the result


on idle
	try
		set thePrice to getPrice(theStock, sourceURL)
		set sendDate to current date
		set theMsg1 to "A(z) " & theStock & " reszveny arfolyama elerte a " & theTriggerPrice & " Ft-os arfolyamot! Idopont: " & sendDate & ". A program leall!"
		set theReturn to 60
		-- display dialog ({"A ", theStock, " reszveny aktualis arfolyama : " & thePrice} as string) buttons {"OK"} default button "OK"
		if veszElad is "Vételre" then
			if theTriggerPrice ≥ thePrice then
				sendMail(theAcc, sendDate, theMsg1)
				--	set theReturn to 3600
				quit
			end if
		else
			if theTriggerPrice ≤ thePrice then
				sendMail(theAcc, sendDate, theMsg1)
				--	set theReturn to 3600
				quit
			end if
		end if
	on error
		sendMail(errorAcc, sendDate, errorMsg)
		quit
	end try
	return theReturn
end idle



on getPrice(theShare, theURL)
	set sourceCode to (do shell script "curl " & theURL) as string
	set AppleScript's text item delimiters to {symbola & theShare & symbolb}
	set tmpSource to (text item 2 of sourceCode) as string
	set AppleScript's text item delimiters to {delimiter1}
	set tmpSource to (text item 2 of tmpSource) as string
	set AppleScript's text item delimiters to {delimiter2}
	set tmpValue to (text item 1 of tmpSource) as string
	set AppleScript's text item delimiters to {" "}
	set tmpValue to (text item 1 of tmpValue & text item 2 of tmpValue) as string
	set AppleScript's text item delimiters to {""}
	return tmpValue
end getPrice


on sendMail(accTelszam, theDate, theText)
	tell application "Mail"
		set newMessage to (make new outgoing message with properties ¬
			{subject:"Reszveny arfolyam", content:"api_id:584171 
	user:AFagens 
	password:warning522 
	from:Arfolyam Figyelo
	to:" & accTelszam & "
	text: " & theText})
		tell newMessage
			set visible to false
			set sender to "Arfolyam Figyelo <Mobile@t-online.hu>"
			make new to recipient at end of to recipients with properties {name:"sms@messaging.clickatell.com", address:mailAddress2}
			send newMessage
		end tell
	end tell
end sendMail

Congratulations on getting a beast like that semi-working.You can get a more solid response if you tell us what the error is. I assume your not getting an error dialog, because the comparison operators are inside “try” statements.

That means if the values aren’t correct for “theTriggerPrice” and “thePrice” for comparison, nothing will will happen. Remove the “try” and “end try” temporarily and run the script to get an error return. This will let you know what’s going on. Post back and tell us what happens. I bet it tells you some data couldn’t be made into certain values for comparison, or an error of that nature. Since it works when the numbers are of the same “digit count”, it’s very likely the text parsing is off for getPrice and the values are incomparable.
SC