Applescript, encoding URLS, and smart rules

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.

Here’s a JavaScript version of the script (note: I used the “Title” to find the appropriate note in Agenda, so whoever prefers to use the “Identifier” has to change this).
It is a simple script, that CAN NOT be used in a smart rule (but from the context of this thread, I didn’t see the need for a smart rule anyway). Tested it with one DT record only.

(() => {
let app=Application("DEVONthink 3");
app.includeStandardAdditions = true;
let sel = app.selection();
sel.forEach(rec => {
  let URL = rec.referenceURL();
  let nameEncoded = encodeURIComponent(rec.name());
/* Change "title=Example%20Note" to "Identifier=xxx" if needed */
  rec.comment = referenceURL();
  let agendaNote = `agenda://x-callback-url/append-to-note?title=Example%20Note&text=[${nameEncoded}](${URL})`
  app.openLocation(agendaNote);
});
})();
3 Likes

Thanks for this, @chrillek.

I came across this page in Apple’s own Scripting Guide, last updated in 2016, which explains how to URL encode/decode with “pure” AppleScript.

Today, URLs can contain Unicode characters. Which the code you linked to doesn’t handle. For example, encodeCharacter("个") returns “63”. The correct value is “%E4%B8%AA”, i.e. three encoded characters, not one.
And it’s a more work to encode a complete string then a single character.

A better alternative (if you insist on using AppleScript, that is :wink: )would be the stringByAddingPercentEncodingWithAllowedCharacters method of the NSString class (or a similar method), which you can access through the ASObjC bridge. Still more than a single line of code, I guess, but at least you should get the correct result.

1 Like

FWIW, if you can use the satimage addition, it has an escapeURL command which returns the url encoding for any characters you feed it.

set x to "悪㎯个"

escapeURL x
--> "%E6%82%AA%E3%8E%AF%E4%B8%AA"

Of course, you can feed it just a single character as well.

set x to "个"
escapeURL x
--> "%E4%B8%AA"

As an aside, if you only have a character or two to encode, you can get the url encoding using the Character Viewer (aka Emoji & Symbols). From within the viewer, search for the character.

Right-click on the resulting character and you should see a Copy character info command. Click on it and then paste into an empty textedit window. You should see a result like this below.

个
CJK UNIFIED IDEOGRAPH-4E2A
Unicode: U+4E2A, UTF-8: E4 B8 AA

Take the hex numbers in the UTF-8 section, insert % and remove the spaces. You now have the url encoding for the character.

It works in both directions. If you search for E4 B8 AA then it will display the following:

Character
E4 B8 AA
Character code
个

Unfortunately, other than by using satimage’s escapeURL command, I don’t know how to programmatically get the UTF-8 code so it’s not as versatile as it might be (or maybe it’s just me that’s not).