How to send real PUSH NOTIFICATIONS to an iPhone or iPod Touch!

Here’s my sales pitch:

Have you been wondering the question: Do you want to send things to your iPhone or iPod Touch without having to know anything about push notifications? Do you not like having to use other scripting languages that are not already integrated into Mac OS X?

If they answer to all these questions is yes, than I have a deal for you!

The name is Prowl. The original service is for sending Growl notifications to your iPhone. I use this service in this script to send anything that isn’t a Growl notification.

Now I’m really sorry about this, but THE APPLICATION ON THE iPhone THAT BRINGS THE NOTIFICATION TO YOUR PHONE IS $2.99 + tax, but the username and password for Prowl, and API key, are free. I am not a part of Prowl or Growl in anyway except I am a user of both of their services. I am not advertising their products, either.

Read more about Prowl’s API here. Sign up for Prowl here, where you can get your API key in the settings tab once your logged in.

Adding this to your application means that you might want to make a user input their own API key into the app is it goes to their iPhone, and not yours (unless your tracking who uses your app).

Here is the code that is full of logging commands (good to use when you are just adding this):

property apikey_verified : "" --this is VERY important

on run
	sendrequest("GETANAPIKEYTOPUTHERE", "0", "Application Name Here", "Event Description", "Description")
end run

on sendrequest(apikey, priority, appname, eventname, desc) -- take note of the names of the variables, this tells you what they do
	if apikey ≠ apikey_verified then
		set i to do shell script "curl --anyauth -G [url=https://prowl.weks.net/publicapi/verify?apikey=]https://prowl.weks.net/publicapi/verify?apikey="[/url] & apikey
		log "Sent Verification"
		if i contains "<success code=\"200\"" then
			set apikey_verified to apikey
			log "Using the API key " & apikey_verified & ", it was accepted."
		else if i contains "<error code=\"406\">" then
			display dialog "Your IP has reached the API limit. Please wait until " & (do shell script "perl -e \"print scalar(gmtime(" & resetdate & ")), \"\\n\"\"" & ".") & ". (once you are whitelisted, you can NOT use this Applescipt-Prowl brigde again)"
		else if i contains "<error code=\"500\">" then
			display dialog "Internal Server Error. Please try again later."
		else
			display dialog "The API key that was used was not valid. Please try again with another API key, or check to make sure your API key works." buttons {"OK"} default button 1
			log "Verification Declined"
			return
		end if
	end if
	if priority ≠ "" then
		set prisend to ""
	else
		set prisend to " --data-urlencode priority=\"" & priority & "\""
	end if
	log "curl --anyauth --data-urlencode apikey=\"" & apikey & "\" " & prisend & " --data-urlencode application=\"" & appname & "\" --data-urlencode event=\"" & eventname & "\" --data-urlencode description=\"" & desc & "\" [url=https://prowl.weks.net/publicapi/add]https://prowl.weks.net/publicapi/add"[/url]
	do shell script "curl -o \"" & ((path to preferences folder as text) & "prowl.savings.xml") & "\" --anyauth --data-urlencode apikey=\"" & apikey & "\" " & prisend & " --data-urlencode application=\"" & appname & "\" --data-urlencode event=\"" & eventname & "\" --data-urlencode description=\"" & desc & "\" [url=https://prowl.weks.net/publicapi/add]https://prowl.weks.net/publicapi/add"[/url]
	try
		set s to open for access file ((path to preferences folder as text) & "prowl.savings.xml")
		set i to read s
		close access s
	on error i
		display dialog "An error has occured.\n\t\t\t\n\t\t\t" & i
		try
			close access s
		end try
		return
	end try
	if i contains "<success code=\"200\"" then
		set apikey_verified to apikey
		tell application "System Events"
			tell contents of XML file ((path to preferences folder as text) & "prowl.savings.xml")
				tell XML element 1
					tell XML element "success"
						set resetdate to value of XML attribute "resetdate"
						set remaining to value of XML attribute "remaining"
					end tell
				end tell
			end tell
		end tell
		log "Using the API key " & apikey_verified & ", it was accepted with " & remaining & " notifications left until " & (do shell script "perl -e \"print scalar(gmtime(" & resetdate & ")), \"\"\"") & "."
		return {true, remaining, resetdate}
	else if i contains "<error code=\"406\">" then
		display dialog "Your IP has reached the API limit. Please wait until " & (do shell script "perl -e \"print scalar(gmtime(" & resetdate & ")), \"\\n\"\"" & ".") & ". (once you are whitelisted, you can NOT use this Applescipt-Prowl brigde again)"
		return
	else if i contains "<error code=\"500\">" then
		display dialog "Internal Server Error. Please try again later."
		return {false}
	else
		display dialog "The API key that was used was not valid. Please try again with another API key, or check to make sure your API key works." buttons {"OK"} default button 1
		log "Verification Declined"
		return {false}
	end if
end sendrequest

Here is the script without the logging:

property apikey_verified : "" --this is VERY important

on run
	sendrequest("GETANAPIKEYTOPUTHERE", "0", "Application Name Here", "Event Description", "Description")
end run

on sendrequest(apikey, priority, appname, eventname, desc) -- take note of the names of the variables, this tells you what they do
	if apikey ≠ apikey_verified then
		set i to do shell script "curl --anyauth -G [url=https://prowl.weks.net/publicapi/verify?apikey=]https://prowl.weks.net/publicapi/verify?apikey="[/url] & apikey
		if i contains "<success code=\"200\"" then
			set apikey_verified to apikey
		else if i contains "<error code=\"406\">" then
			display dialog "Your IP has reached the API limit. Please wait until " & (do shell script "perl -e \"print scalar(gmtime(" & resetdate & ")), \"\\n\"\"" & ".") & ". (once you are whitelisted, you can NOT use this Applescipt-Prowl brigde again)"
		else if i contains "<error code=\"500\">" then
			display dialog "Internal Server Error. Please try again later."
		else
			display dialog "The API key that was used was not valid. Please try again with another API key, or check to make sure your API key works." buttons {"OK"} default button 1
			return
		end if
	end if
	if priority ≠ "" then
		set prisend to ""
	else
		set prisend to " --data-urlencode priority=\"" & priority & "\""
	end if
	do shell script "curl -o \"" & ((path to preferences folder as text) & "prowl.savings.xml") & "\" --anyauth --data-urlencode apikey=\"" & apikey & "\" " & prisend & " --data-urlencode application=\"" & appname & "\" --data-urlencode event=\"" & eventname & "\" --data-urlencode description=\"" & desc & "\" [url=https://prowl.weks.net/publicapi/add]https://prowl.weks.net/publicapi/add"[/url]
	try
		set s to open for access file ((path to preferences folder as text) & "prowl.savings.xml")
		set i to read s
		close access s
	on error i
		display dialog "An error has occured.\n\t\t\t\n\t\t\t" & i
		try
			close access s
		end try
		return
	end try
	if i contains "<success code=\"200\"" then
		set apikey_verified to apikey
		tell application "System Events"
			tell contents of XML file ((path to preferences folder as text) & "prowl.savings.xml")
				tell XML element 1
					tell XML element "success"
						set resetdate to value of XML attribute "resetdate"
						set remaining to value of XML attribute "remaining"
					end tell
				end tell
			end tell
		end tell
		return {true, remaining, resetdate}
	else if i contains "<error code=\"406\">" then
		display dialog "Your IP has reached the API limit. Please wait until " & (do shell script "perl -e \"print scalar(gmtime(" & resetdate & ")), \"\\n\"\"" & ".") & ". (once you are whitelisted, you can NOT use this Applescipt-Prowl brigde again)"
		return
	else if i contains "<error code=\"500\">" then
		display dialog "Internal Server Error. Please try again later."
		return {false}
	else
		display dialog "The API key that was used was not valid. Please try again with another API key, or check to make sure your API key works." buttons {"OK"} default button 1
		return {false}
	end if
end sendrequest

Let me explain how the data that is returned can be used. The first item (out of 3) in the list is true (unless it’s false, where there is only 1 item) to show that it was successfully sent. The second item in the list is the amount of more requests you can send before it’s declined (you get 1000 per hour). The third item is the date of the next hour according to Prowl in GMT. This can be translated with (do shell script “perl -e "print scalar(gmtime(” & resetdate & “)), "\n""” & “.”)

This is how it will look like on the iPhone without changing the information on the example scripts.

Have any problems? Just post a reply to this topic.

Hi Dylan.

Thanks for this handler, I’m sure I’ll find a use for it.
The notification arrives on my iPhone as it should but the script fails with the following error message:

error "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100   111    0     0  100   111      0    211 --:--:-- --:--:-- --:--:--   309Warning: Failed to create the file Mac 
Warning: HD:Users:Morten:Library:Preferences:prowl.savings.xml: Permission 
Warning: denied

100   229  100   118  100   111    165    155 --:--:-- --:--:-- --:--:--   215
curl: (23) Failed writing body (0 != 118)" number 23

Just to test I gave “everyone” read & write permission to my preferences folder but the error persists. Any thought?

I also have a question. Is there any way to link a notification to an actual app on the iPhone so clicking the notification will launch that app?

Thanks,
Morten

PS: I’m running OS X 10.7 Lion

This should fix any errors. The cause seems to be non-Lion dependent, but it only happens in Lion. :confused: Weird.

property apikey_verified : "" --this is VERY important

on run
	sendrequest("APIKEYHERE", "0", "Application Name Here", "Event Description", "Description")
end run

on sendrequest(apikey, priority, appname, eventname, desc) -- take note of the names of the variables, this tells you what they do
	tell application "Finder" to if not (exists file ((path to preferences folder as text) & "prowl.savings.xml")) then
		make new file at preferences folder with properties {name:"prowl.savings.xml"}
	end if
	if apikey ≠ apikey_verified then
		set i to do shell script "curl --anyauth -G [url=https://prowl.weks.net/publicapi/verify?apikey=]https://prowl.weks.net/publicapi/verify?apikey="[/url] & apikey
		log "Sent Verification"
		if i contains "<success code=\"200\"" then
			set apikey_verified to apikey
			log "Using the API key " & apikey_verified & ", it was accepted."
		else if i contains "<error code=\"406\">" then
			display dialog "Your IP has reached the API limit. Please wait until " & (do shell script "perl -e \"print scalar(gmtime(" & resetdate & ")), \"\\n\"\"" & ".") & ". (once you are whitelisted, you can NOT use this Applescipt-Prowl bridgee again)"
		else if i contains "<error code=\"500\">" then
			display dialog "Internal Server Error. Please try again later."
		else
			display dialog "The API key that was used was not valid. Please try again with another API key, or check to make sure your API key works." buttons {"OK"} default button 1
			log "Verification Declined"
			return
		end if
	end if
	if priority ≠ "" then
		set prisend to ""
	else
		set prisend to " --data-urlencode priority=\"" & priority & "\""
	end if
	log "curl -o \"" & (POSIX path of ((path to preferences folder as text) & "prowl.savings.xml")) & "\" --anyauth --data-urlencode apikey=\"" & apikey & "\" " & prisend & " --data-urlencode application=\"" & appname & "\" --data-urlencode event=\"" & eventname & "\" --data-urlencode description=\"" & desc & "\" [url=https://prowl.weks.net/publicapi/add]https://prowl.weks.net/publicapi/add"[/url]
	do shell script "curl -o \"" & (POSIX path of ((path to preferences folder as text) & "prowl.savings.xml")) & "\" --anyauth --data-urlencode apikey=\"" & apikey & "\" " & prisend & " --data-urlencode application=\"" & appname & "\" --data-urlencode event=\"" & eventname & "\" --data-urlencode description=\"" & desc & "\" [url=https://prowl.weks.net/publicapi/add]https://prowl.weks.net/publicapi/add"[/url]
	try
		set s to open for access file ((path to preferences folder as text) & "prowl.savings.xml")
		set i to read s
		close access s
	on error i
		display dialog "An error has occured.
			
			" & i
		try
			close access s
		end try
		return
	end try
	if i contains "<success code=\"200\"" then
		set apikey_verified to apikey
		tell application "System Events"
			tell contents of XML file ((path to preferences folder as text) & "prowl.savings.xml")
				tell XML element 1
					tell XML element "success"
						set resetdate to value of XML attribute "resetdate"
						set remaining to value of XML attribute "remaining"
					end tell
				end tell
			end tell
		end tell
		log "Using the API key " & apikey_verified & ", it was accepted with " & remaining & " notifications left until " & (do shell script "perl -e \"print scalar(gmtime(" & resetdate & ")), \"\"\"") & "."
		return {true, remaining, resetdate}
	else if i contains "<error code=\"406\">" then
		display dialog "Your IP has reached the API limit. Please wait until " & (do shell script "perl -e \"print scalar(gmtime(" & resetdate & ")), \"\\n\"\"" & ".") & ". (once you are whitelisted, you can NOT use this Applescipt-Prowl brigde again)"
		return
	else if i contains "<error code=\"500\">" then
		display dialog "Internal Server Error. Please try again later."
		return {false}
	else
		display dialog "The API key that was used was not valid. Please try again with another API key, or check to make sure your API key works." buttons {"OK"} default button 1
		log "Verification Declined"
		return {false}
	end if
end sendrequest

Nice script, but a bit big for me. I wanted to be able to send notifications from my Laptop even if elsewhere.

This handler will tell growl to send a message as application “Growl AppleScript To iPhone”. This application has been set up in the growl pref pane to use prowl instead of what I usually use, nano. Bit more hacky, bit of a user by user basis, but it works and it’s small.

on Prowl(message)
tell application "GrowlHelperApp"
	set the allNotificationsList to {"Test Notification"}
	set the enabledNotificationsList to {"Test Notification"}
	
	register as application "Growl AppleScript To iPhone" all notifications allNotificationsList default notifications enabledNotificationsList icon of application "Script Editor"
	
	
	notify with name "Test Notification" title "Test Notification" description "This is a test AppleScript notification." application name "Growl AppleScript To iPhone"
	
end tell
end