Read from a version file then download with Curl

Good day folks,
I’ve run into a situation for which I am unsure of how to resolve.
First, I have an app that I wrote using AppleScript. At start up, I want it to check to see if there is a new version of the app in question, if so, it should download the DMG file.
How i wish to achieve this is have curl read the contents of a file, simply called, version.txt. This file is located on a website, for this example, will be called, example.com.
The version.txt file only has the following as variables:
1.0.1
www.example.com/downloads/untitled.dmg
I have the following code in my script, but I may be coding in incorrectly. I’d appreciate some guidance as to how to fix it. If changes should be made, feel free to make them then repost the script with said changes.
Thanks for any help that can be provided.
The code is below.


#Check for newer version of Untitled. If it's grater than the current version, download the new file.
set lineDelimiter to paragraphs of versionFile
set versionFile to do shell script ("curl -L 'https://example.com/UntitledData/version.txt'")
set lineDelimiter to paragraphs of versionFile
repeat with oneLine in lineDelimiter
	if length of oneLine is greater than 0 then
		set variable to oneLine
		log "variable: " & variable
	end if
end repeat
tell current application
    do shell script "curl -L 'https://example.com/UntitledData/version.txt' 
--> "1.0.0
[url=http://www.example.com/downloads/untitled.dmg]www.example.com/downloads/untitled.dmg"[/url]
    (*variable: 1.0.1*)
(*variable: [url=http://www.example.com/downloads/untitled.dmg*)]www.example.com/downloads/untitled.dmg*)[/url]
end tell

In that script I cannot determine the issue. Maybe I have my line delimiters wrong? In addition, I want the user to know (perhaps through an echo statement,) if they have the newer version of the untitled.dmg file or not, based upon reading the version.txt file off of the website.

Model: Macbook Pro
AppleScript: 2.10
Browser: Safari 604.1.38
Operating System: Mac OS X (10.13 Developer Beta 3)

I’m doing something similar but with a web page instead of a text file. To start, I curl the page into a variable:

	set test_page to do shell script "curl " & test_web_site & " | textutil -stdin -stdout -format html -convert txt -encoding UTF-8 "

I guess you don’t need to worry about converting the version file into text.

Luckily, the version number I need is always in the same place so I just read the relevant characters:

	set version_check to text 66 thru 70 of test_page

That might be easier than splitting into paragraphs etc. Then it’s a comparison with the current version.

You could pop a dialog to advise the user there is an update. You could provide them with the option to update or not. Or, set the dialog to be displayed for a set time before closing and then downloading the update.

Is there an AppleScript error msg ?

There’s no error msg yet.
So if I understand right, you just created a page just called test_page (without an extension) and put the version number in it?
If so, I was thinking about it and was going to do a web page as well, but a text file came to mind at the last minute.
So, going on your example, I could perhaps create a page called, version (without an extension,) and input it just. 2.0.3 in the file called version?
2.0.3 is the new version number of the app I plan to release.
How then, would I check the current version of my app, and then check it against the version file, and provide an update option? Based on if the version (from the version page,) says anything grater than for instance, 2.0?
Would the versioncheck take into account stuff like, 1.0.0, 2.0.0? And/or, stuff like, 1.0, 2.0?
I ask because I may change version number formats, and don’t feel like changing the version check code.

Hi,
Perhaps I’m half asleep or have forgotten how to write today, but I must be doing something wrong here.
I want to compare whether version 202 (which should read as 2.0.2,) and 203 (which should read as 2.0.3,) are current or not, by checking the current app version, and checking the file called, version which is an html web page.
Below is my code, I seem to be getting either text errors, or else, the code in general won’t run.


#Check for newer version of UntitledApp. If it's grater than the current version, download the new file.
set test_page to do shell script "curl" & "http://example.com/UntitledAppData/version" & " | textutil -stdin -stdout -format html -convert txt -encoding UTF-8"
set version_check to text 200 thru 2030 of test_page
if version_check is less than 200 then
	set question to display dialog "UntitledApp version out of date: The version you have is: & check_version. Shall I download the newer version, which is: &check_version?" buttons {"Yes", "No"} default button 1
	set answer to button returned of question
	if answer is equal to "Yes" then
		say " Downloading newer version of UntitledApp"
		tell application
			do shell script "curl -L [url=https://example.com/downloads/untitledapp.dmg]https://example.com/downloads/untitledapp.dmg"[/url]
on error
display dialog "File Not Found
The file could not be found on the server. Please try again later." with title "File Download error" giving up after 10
	end tell
	else if answer is equal to "No" then
		quit
	end if
else if version_check is greater than 230 then
	display dialog "Version up to date. You are running the latest version of UntitledApp. No update is needed. Now continuing...." with title "Information" giving up after 6
end if

As I said, I am not sure what I may be doing wrong here. Help would be appreciated with this. Thanks.

Hi Hawk.

As I understand you, the file “version.txt” contains just two lines of text, the first being a version number and the second being a URL to a DMG file. If the version number’s later than one you already have, you want to download the DMG.

I think this gets you quite close:

set currentVersion to "1.0" -- Replace with your code for getting the existing version number.

#Check for newer version of Untitled. (URL split to avoid this BBS's habit of inserting BBCode tags around URLs!)
set versionFileText to (do shell script ("curl -L 'htt" & "ps://example.com/UntitledData/version.txt'"))

-- Is the version number in the downloaded text newer than the one we already have?
considering numeric strings
	set newerVersionExists to (paragraph 1 of versionFileText > currentVersion)
end considering

-- If it is…
if (newerVersionExists) then
	-- Read the DMG URL from the text.
	set theURL to paragraph 2 of versionFileText
	-- Get a POSIX path to the download destination (here, the user's Downloads folder).
	set downloadPath to POSIX path of (path to downloads folder)
	-- Make the destination folder the current directory and download the DMG file to it under the name in the URL.
	do shell script ("cd " & quoted form of downloadPath & "; curl -LO " & quoted form of theURL)
end if

Thanks so much for much cleaner code. I guess my attempt at coding to check for a version wasn’t exactly … something to be proud of.
nevertheless, we all learn, so that’s the important thing.
How then can I give the user the option to download the newer version? Or at least, let them know what version of the app they have installed currently, and if need be, what the newer version is that’s available for actual download?
I wanted this to be in a dialog box of sorts, if possible. i may have ideas, and may try them and post them to get any feedback.
Again, thanks for the assistance.

Something like this, I suppose. You may also want to add error checks for the validity of the version file and a message to say why it couldn’t be downloaded if it couldn’t be.

set currentVersion to "1.0" -- Replace with your code for getting the existing version number.

#Check for newer version of Untitled. (URL split to avoid this BBS's habit of inserting BBCode tags around URLs!)
try
	set versionFileText to (do shell script ("curl -L 'htt" & "ps://example.com/UntitledData/version.txt'"))
on error
	-- Can't get the version file for some reason. Stop the script.
	error number -128 -- "User canceled." error.
end try

-- Is the version number in the downloaded text newer than the one we already have?
set latestVersion to paragraph 1 of versionFileText
considering numeric strings
	set newerVersionExists to (latestVersion > currentVersion)
end considering

-- If it is…
if (newerVersionExists) then
	-- Ask the user if they want to download the latest version. Stop the script if they click "No" or haven't responded after, say, 90 seconds.
	set theResponse to (display dialog "UntitledApp version out of date: The version you have is: " & currentVersion & ". Shall I download the newer version, which is: " & latestVersion & "?" buttons {"Yes", "No"} default button 1 cancel button 2 with title "UntitledApp" with icon note giving up after 90)
	(* -- Or you may like:
	set theResponse to (display alert "UntitledApp version out of date:" message "The version you have is: " & currentVersion & ". Shall I download the newer version, which is: " & latestVersion & "?" buttons {"Yes", "No"} default button 1 cancel button 2 as informational giving up after 90)
	*)
	if (theResponse's gave up) then error number -128
	
	-- If the script's still running, read the DMG URL from the text.
	set theURL to paragraph 2 of versionFileText
	say " Downloading newer version of UntitledApp"
	-- Get a POSIX path to the download destination (here, the user's Downloads folder).
	set downloadPath to POSIX path of (path to downloads folder)
	-- Make the destination folder the current directory and download the DMG file to it under the name in the URL.
	try
		do shell script ("cd " & quoted form of downloadPath & "; curl -LO " & quoted form of theURL)
	on error errMsg
		display alert "File Download error:" message errMsg & linefeed & linefeed & "Please try again later. If the problem persists, please inform the developer." buttons {"OK"} default button 1 cancel button 1 as critical giving up after 10
	end try
else
	display dialog "Version up to date. You are running the latest version of UntitledApp. No update is needed. Now continuing...." with title "Information" giving up after 6
end if

Nigel,
Thanks so much for your help. I noticed the script isn’t catching any of the HTTP 404 errors, is this because of the use of Curl?
For instance, I renamed the version.txt file to example.doc, and when I run the script, it reports the application is running the latest version.
When i rename the file back to version.txt, and rename the dmg from it’s original name to something like, light.exe, it doesn’t report the HTTP 404 error, the script continues to run as if nothing happened.
I’ve been trying to Google around but couldn’t find a good error handler for both the missing version file (the fact that the version file doesn’t exist, and gives a 404 error,) nor the missing DMG file (the fact that the dmg file does not exist, returning a 404 error.)
When I curl -L plus the UntitledApp and version.txt URL’s, it says:
The requested URL /downloads/UntitledApp.dmg was not found on this server.
The requested URL /UntitledAppData/version.txt was not found on this server.
Do you have a good handler for both of those errors that might work?

Hi Hawk.

I’ve just tried it myself in the script, using your real domain, which I got from your duplicate post on AppleScript-Users. What’s happening when the file name’s wrong is that the server’s returning an HTML text message saying that the file couldn’t be found. This text is a result for curl, so it doesn’t error and doesn’t stop the script. The script then compares the first line of the HTML with currentVersion, finds that it’s not lexically greater, and so reports that the version’s up-to-date.

To catch 404 errors, the script will have to check what’s in what it gets back from the server. I’ll think about it, but it may have to wait until tomorrow (BST) now.

Not a problem. I did see one thing on the curl man page.
Could i not use -f as a flag? I saw somewhere where -f is suppose to return error responses, but I may be doing something incorrectly, such as the below.


try
		do shell script ("cd " & quoted form of downloadPath & "; curl -LO " & "-f" & quoted form of theURL)
	on error errMsg
		display alert "File Download error:" message errMsg & linefeed & linefeed & "Please try again later. If the problem persists, please inform the developer." buttons {"OK"} default button 1 cancel button 1 as critical giving up after 10
	end try
else
	display dialog "Version up to date. You are running the latest version of NetUtilsHighSierra. No update is needed. Now continuing..." buttons "" with title "Information" giving up after 6
end if

I think I may have changed something around before to get the code above to work and all it produced was the curl percentage of the non-existant file, plus the file download alert prompt. However, the part about contacting the developer never showed up.
Take what time you need, and when you’ve come up with something, I look forward to seeing a solution to this.
Thanks.

Hi Hawk.

The -f option does seem to be a good solution. It causes the script’s error traps to trigger when either of the files can’t be downloaded for any reason.

The “please contact the developer” part does show up in the download failure alert, but comes at the very end and so isn’t easy to see. I’ve inserted a line to reduce the message actually displayed.

set currentVersion to "1.0" -- Replace with your code for getting the existing version number.

#Check for newer version of Untitled. (URL split to avoid this BBS's habit of inserting BBCode tags around URLs!)
try
	set versionFileText to (do shell script ("curl -fL 'htt" & "ps://example.com/UntitledData/version.txt'"))
on error
	-- Can't get the version file for some reason. Stop the script.
	error number -128 -- "User canceled." error.
end try

-- Is the version number in the downloaded text newer than the one we already have?
set latestVersion to paragraph 1 of versionFileText
considering numeric strings
	set newerVersionExists to (latestVersion > currentVersion)
end considering

-- If it is…
if (newerVersionExists) then
	-- Ask the user if they want to download the latest version. Stop the script if they click "No" or haven't responded after, say, 90 seconds.
	set theResponse to (display dialog "UntitledApp version out of date: The version you have is: " & currentVersion & ". Shall I download the newer version, which is: " & latestVersion & "?" buttons {"Yes", "No"} default button 1 cancel button 2 with title "UntitledApp" with icon note giving up after 90)
	(* -- Or you may like:
	set theResponse to (display alert "UntitledApp version out of date:" message "The version you have is: " & currentVersion & ". Shall I download the newer version, which is: " & latestVersion & "?" buttons {"Yes", "No"} default button 1 cancel button 2 as informational giving up after 90)
	*)
	if (theResponse's gave up) then error number -128
	
	-- If the script's still running, read the DMG URL from the text.
	set theURL to paragraph 2 of versionFileText
	say " Downloading newer version of UntitledApp"
	-- Get a POSIX path to the download destination (here, the user's Downloads folder).
	set downloadPath to POSIX path of (path to downloads folder)
	-- Make the destination folder the current directory and download the DMG file to it under the name in the URL.
	try
		do shell script ("cd " & quoted form of downloadPath & "; curl -fLO " & quoted form of theURL)
	on error errMsg
		if (errMsg contains "curl") then set errMsg to text (offset of "curl" in errMsg) thru -1 of errMsg
		display alert "File Download error:" message errMsg & linefeed & linefeed & "Please try again later. If the problem persists, please inform the developer." buttons {"OK"} default button 1 cancel button 1 as critical giving up after 10
	end try
else
	display dialog "Version up to date. You are running the latest version of UntitledApp. No update is needed. Now continuing...." with title "Information" giving up after 6
end if

Great fix to the script. Now my question becomes, it’s not realizing that the version file is deleted. How can that be checked?
Also, is there no code to check the Mac’s application current version and compare it to the version.txt file on the web?
Furthermore, how can I silence the progress bar output in curl? I tried using the -s option, as well as the --silent option. Both say the command exited with status code zero.

Sorry. It seems I deleted the ‘on error’ line along with your real URL just before posting the script. I’ve now reinstated it in post #11 above.

Do you mean the version of the AppleScript application? I presumed you already had that in hand. If the current script’s part of the code for that, you could put a ‘version’ property at the top of the code:

property version : "1.0" -- Edit this each time you do a new version.

Then delete the set currentVersion to “1.0” line and change all other mentions of currentVersion to version.

:confused: That’s what the script already does.

As far as I’m aware, you’ll only see a progress bar or an exit status if you run the curl code in Terminal. I’m certainly not seeing either with do shell script.

You had mentioned to put a version property and replace set current version.
I did all of this, but either it’s not checking correctly, or else, i mistyped it?
I ask about this because the version.txt says 2.0.5, the app says 2.0.4.
Here’s what I did


#Set Current Version with a version property
property version : "2.0.4"
#Is the version number in the downloaded text newer than the one we already have?
set latestVersion to paragraph 1 of versionFileText
considering numeric strings
	set newerVersionExists to (latestVersion > version)
end considering
if (newerVersionExists) then
	-- Ask the user if they want to download the latest version. Stop the script if they click "No" or haven't responded after, say, 90 seconds.
	set theResponse to (display alert "NetUtilsHighSierra version out of date." message "The version you have is: " & version & ". Shall I download the newer version, which is: " & latestVersion & "?" buttons {"Yes", "No"} default button 1 cancel button 2 as informational giving up after 90)
	if (theResponse's gave up) then error number -128

Your code doesn’t include the fetching of the version file, but otherwise looks OK. Here’s the full script I’ve been testing. I’ll remove the real URL in a few hours. [Edit: now done.]

property version : "2.0.4" -- Edit this each time you do a new version.

#Check for newer version of Untitled. (URL split to avoid this BBS's habit of inserting BBCode tags around URLs!)
try
	set versionFileText to (do shell script ("curl -fL 'htt" & "ps://example.com/UntitledData/version.txt'"))
on error
	-- Can't get the version file for some reason. Stop the script.
	error number -128 -- "User canceled." error.
end try

-- Is the version number in the downloaded text newer than the one we already have?
set latestVersion to paragraph 1 of versionFileText
considering numeric strings
	set newerVersionExists to (latestVersion > version)
end considering

-- If it is…
if (newerVersionExists) then
	-- Ask the user if they want to download the latest version. Stop the script if they click "No" or haven't responded after, say, 90 seconds.
	-- set theResponse to (display dialog "UntitledApp version out of date: The version you have is: " & version & ". Shall I download the newer version, which is: " & latestVersion & "?" buttons {"Yes", "No"} default button 1 cancel button 2 with title "UntitledApp" with icon note giving up after 90)
	--(* -- Or you may like:
	set theResponse to (display alert "NetUtilsHighSierra version out of date:" message "The version you have is: " & version & ". Shall I download the newer version, which is: " & latestVersion & "?" buttons {"Yes", "No"} default button 1 cancel button 2 as informational giving up after 90)
	--*)
	if (theResponse's gave up) then error number -128
	
	-- If the script's still running, read the DMG URL from the text.
	set theURL to paragraph 2 of versionFileText
	say " Downloading newer version of UntitledApp"
	-- Get a POSIX path to the download destination (here, the user's Downloads folder).
	set downloadPath to POSIX path of (path to downloads folder)
	-- Make the destination folder the current directory and download the DMG file to it under the name in the URL.
	try
		do shell script ("cd " & quoted form of downloadPath & "; curl -fLO " & quoted form of theURL)
	on error errMsg
		if (errMsg contains "curl") then set errMsg to text (offset of "curl" in errMsg) thru -1 of errMsg
		display alert "File Download error:" message errMsg & linefeed & linefeed & "Please try again later. If the problem persists, please inform the developer." buttons {"OK"} default button 1 cancel button 1 as critical giving up after 10
	end try
else
	display dialog "Version up to date. You are running the latest version of UntitledApp. No update is needed. Now continuing...." with title "Information" giving up after 6
end if