Applescript, encoding URLS, and smart rules

I am trying to create a smart rule that will append the name and link of a document in a specific folder into a note in Agenda. I have to use agenda’s url scheme to update the specified note. I have an applescript that mostly works, but I cannot figure out how to URL encode (there can be spaces in the document name, so these need to be URL encoded).

Does anyone have any experience with url encoding in AppleScript? Or does anyone have a better way of doing this? (basically I am just updating a list of invoices that need to be paid as I receive them, so as invoices appear in my invoices folder Agenda will be updated with a list of what has been added in the folder)

set theText to "hallo welt überall"

set theText_encoded to my urlEncode(theText)

on urlEncode(str)
	local str
	try
		return (do shell script "/bin/echo " & quoted form of str & ¬
			" | perl -MURI::Escape -lne 'print uri_escape($_)'")
	on error eMsg number eNum
		error "Can't urlEncode: " & eMsg number eNum
	end try
end urlEncode

That’s not my handler, it’s from http://applescript.bratis-lover.net but the site is down for a long time

And I’ve never used this one before but it should do it fine, I think

Or you could use the foundation framework:

use framework "Foundation"

on urlEncode(str)
	local nsStr
	set nsStr to current application's NSString's stringWithString:(str)
	set characterSet to current application's NSCharacterSet's URLQueryAllowedCharacterSet()
	return (nsStr's stringByAddingPercentEncodingWithAllowedCharacters:characterSet) as text
end urlEncode
1 Like

I was searching for a way to do it in AppleScriptObjC, thanks! :slight_smile:

Thank you @pete31 and @cgrunenberg. Those both look useful, but I cannot get either to work. I don’t expect anyone to troubleshoot my novice attempts at applescript, but if you see an obvious rookie mistake here, I’d be interested to hear what it is.

on performSmartRule(theRecords)
	tell application id "DNtp"
		set theSelection to the selection
		repeat with theRecord in theSelection
			set the comment of theRecord to "x-devonthink-item://" & uuid of theRecord
			set agendaNote to "agenda://x-callback-url/append-to-note?identifier=8DE495E1-6F45-41E0-9D34-30960408B0F4&text=" & "[" & uuid of theRecord & "]" & "(" & "x-devonthink-item://" & uuid of theRecord & ")"
			display dialog (display dialog agendaNote)
			set theURL to urlEncode(agendaNote)
			display dialog theURL
			open location theURL
		end repeat
	end tell
end performSmartRule

on urlEncode(str)
	local str
	try
		return (do shell script "/bin/echo " & quoted form of str & ¬
			" | perl -MURI::Escape -lne 'print uri_escape($_)'")
	on error eMsg number eNum
		error "Can't urlEncode: " & eMsg number eNum
	end try
end urlEncode

The rule runs, but nothing seems to happen after display dialog (display dialog agendaNote)

Try this…

on performSmartRule(theRecords)
tell application id "DNtp"
	set theSelection to the selection
	repeat with theRecord in theSelection
		set recordURL to reference URL of theRecord
		-- The UUID is the alphanumeric portion of the reference URL
		-- The rererence URL is the entire item link
		
		set recordName to name of theRecord
		-- Get the name of the record
		
		set the comment of theRecord to recordURL
		-- Set the comment of the record to the item link
		
		set agendaNote to "agenda://x-callback-url/append-to-note?identifier=D5F1A1A4-D77D-4AE2-95CC-708AA6F1A006&text=" & "[" & (my urlencode(recordName)) & "](" & recordURL & ")"
		-- The recordName is passed to the URLEncode handler 
		
		open location agendaNote
	end repeat
end tell

on urlencode(str)
	local str
	try
		return (do shell script "/bin/echo " & quoted form of str & ¬
			" | perl -MURI::Escape -lne 'print uri_escape($_)'")
	on error eMsg number eNum
		error "Can't urlEncode: " & eMsg number eNum
	end try
end urlencode
end performSmartRule

And the output…

Note: I would get in the habit of adding comments to your code, especially as you’re thinking through something. Actually, a pen and pad of paper is a fantastic set of tools for scripting.

Thanks, @Bluefrog, especially for the tip on adding comments.

I get an error that says "Expected “end” but found “on”.

May I add that URI::Encode is not necessarily available? At least on my Big Sur installation, it does not exist.
If the whole thing doesn’t have to work in a smart rule, I could try to provide a JavaScript version. It provides a built-in method to encode URIs.

Do you mean MURI::Escape? Or am I overlooking a reference to URI::Encode in Jim’s script?

@bangersandmash from what you’ve posted I can’t see any obvious reason - would you post the whole script you are using - or is it exactly cut&paste from what Jim posted?

perl -MURI::Escape
tells the Perl interpreter to load the M odule (hence -M) URI::Escape. So: No, I mean URI::Escape. If you’re still on Catalina, give it a try:

perl -MURI::Escape -e "print 'hello';"

on the command line.

Ar, I’ve just seen it:

end performSmartRule needs to go after end tell rather than after end urlencode

ja, but you wrote URI::Encode, so I was confused (and see my next post, maybe you were too :smiley: but thanks for the -M info - it’s little things like that which make it clear I’ve not got a clue :wink: )

That works on both Catalina and Big Sur

Ahh. I wasn’t running it in a smart rule a d wasn’t paying attention when I tacked that on.

Hi @Blanc, I copied and pasted what @BLUEFROG posted

Yeah, I tried that, had the same problem and posted the solution a couple of posts up. You might have missed that, because I went a little OT, which is why I’m pointing you to the solution again.

Thanks everyone, for your help. I can’t explain how, or why, but this is what finally worked (urlencode has to go first, for some reason):

on urlencode(str)
	local str
	try
		return (do shell script "/bin/echo " & quoted form of str & ¬
			" | perl -MURI::Escape -lne 'print uri_escape($_)'")
	on error eMsg number eNum
		error "Can't urlEncode: " & eMsg number eNum
	end try
end urlencode
on performSmartRule(theRecords)
	tell application id "DNtp"
		set theSelection to the selection
		repeat with theRecord in theSelection
			set recordURL to reference URL of theRecord
			-- The UUID is the alphanumeric portion of the reference URL
			-- The rererence URL is the entire item link
			
			set recordName to name of theRecord
			-- Get the name of the record
			
			set the comment of theRecord to recordURL
			-- Set the comment of the record to the item link
			
			set agendaNote to "agenda://x-callback-url/append-to-note?identifier=8DE495E1-6F45-41E0-9D34-30960408B0F4&text=" & "[" & (my urlencode(recordName)) & "](" & recordURL & ")"
			-- The recordName is passed to the URLEncode handler 
			
			open location agendaNote
		end repeat
		
	end tell
	
end performSmartRule

There’s currently a moderate tropical storm over the Indian Ocean, that’ll be why.

:joy: 100%, that must be it, @Blanc. Thanks again for your help.

1 Like

Argh. Of course. encode is JavaScript. Sorry, I was distracted.