Need help turning working script into smart rule capable version

Hi,

I’ve been trying and not succeeding at modifiying a script so that it can run via a smart rule.

The script adds the obsidian URL of an indexed item to a custom metadata field. It works when I select the item in DevonThink and run the script, but the version I modified to run it through a smart rule doesn’t produce any effect when that smart rule is applied. There are also no visible errors.

I tried different variations but can’t get it to work. Would really appreciate some hints :slight_smile:

Here’s the non smart rule version (working for selected items):

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions


on urlEncode(input) -- with thanks to @BlueM on Stack Overflow: https://stackoverflow.com/a/43562220
	tell current application's NSString to set rawUrl to stringWithString_(input)
	set theEncodedURL to rawUrl's stringByAddingPercentEscapesUsingEncoding:4 -- 4 is NSUTF8StringEncoding
	return theEncodedURL as Unicode text
end urlEncode

tell application id "DNtp"
	
	set selectedItems to get the selection
	set theSelection to the first item in selectedItems
	set recordFilename to proposed filename of theSelection as string
	set URLEncodedFilename to my urlEncode(recordFilename)
	set URLEncodedVaultName to my urlEncode("B10")
	set newobsidianURL to "obsidian://open?vault=" & URLEncodedVaultName & "&file=" & URLEncodedFilename
	add custom meta data newobsidianURL for "obsidianurl" to theSelection

end tell

And this is the attempted smart rule-compatible version (not working):

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions


on urlEncode(input) -- with thanks to @BlueM on Stack Overflow: https://stackoverflow.com/a/43562220
	tell current application's NSString to set rawUrl to stringWithString_(input)
	set theEncodedURL to rawUrl's stringByAddingPercentEscapesUsingEncoding:4 -- 4 is NSUTF8StringEncoding
	return theEncodedURL as Unicode text
end urlEncode

on performSmartRule(theRecords)
	tell application id "DNtp"
		repeat with thisRecord in theRecords
			set recordFilename to proposed filename of thisRecord as string
			set URLEncodedFilename to my urlEncode(recordFilename)
			set URLEncodedVaultName to my urlEncode("B10")
			set newobsidianURL to "obsidian://open?vault=" & URLEncodedVaultName & "&file=" & URLEncodedFilename
			add custom meta data newobsidianURL for "obsidianurl" to thisRecord
			
			
		end repeat
	end tell
end performSmartRule

It’s one of these weird side-effects when using scripting additions and/or frameworks. This revision works (and uses filename instead of proposed filename which might be not be identical to the current filename)

on urlEncode(input)
	run script "encodeURIComponent(" & (the quoted form of input) & ");" in "JavaScript"
end urlEncode

on performSmartRule(theRecords)
	tell application id "DNtp"
		repeat with thisRecord in theRecords
			set recordFilename to filename of thisRecord
			set URLEncodedFilename to my urlEncode(recordFilename)
			set URLEncodedVaultName to my urlEncode("B10")
			set newobsidianURL to "obsidian://open?vault=" & URLEncodedVaultName & "&file=" & URLEncodedFilename
			add custom meta data newobsidianURL for "obsidianurl" to thisRecord
		end repeat
	end tell
end performSmartRule
1 Like

Much appreciated, @cgrunenberg !

However, while now the script does take effect, for some reason it’s not processing all records in the smart rule scope. I’ve run the modified version multiple times, and it always correctly processes the same 20 records, but does not change the remaining 200 or so.

I’m trying to identify some kind of a pattern that distinguishes the records where it worked from the others, but currently can’t identify anything obvious.

// Edit for future readers of this thread: The version above works as intended. This issue was caused by apostrophe’s in my file names, which the URL encoding can’t handle.

Anything logged to Windows > Log?

Indeed, there is:

That seems to indicate that your 21st file contains a character in its name that the URLEncode handler can’t handle

Also, you might want to encode the vault name only once outside the loop since it never changes.

1 Like

Thanks for translating that for me :sweat_smile:

I was able to fix the issue by removing all characters from records’ filenames.

Super happy that it’s working now, big thanks to both of you @chrillek and @cgrunenberg!

Yeah, makes sense :+1:

In fact, don’t URLencode it at all. B10 first contain any special characters that would require URLencoding.
I’d, of course, wrote the whole snippet in JavaScript and avoid three script call that way, as well as quoting the string first.

Interesting. I have got to get started learning some JavaScript.

While I understand that it’s the more capable coding language compared to AppleScript, I find that the latter is just way more accessible and “readable” for non-techies.

2 Likes

:100: :smiley:

This can also be done with a DEVONthink built-in command, e.g.,…

set URLEncodedFilename to do JavaScript "encodeURIComponent(" & quoted form of (recordFilename) & ");"

However, the handler is nice if you’re having to process multiple properties.

Readable – perhaps, for English speaking people. Writeable – not so. Not even in the minds of the people who invented it. And, personally, I find the habit of beginning variable names with “the” the opposite of “readable”. Three meaningless characters that have to be mentally skipped to get to the relevant part.

function performsmartrule(records) {
  const app = Application ("DEVONthink 3");
  records.forEach( r => {
     const obsidianURL =`obsidian://open?vault=${encodeURIComponent(r.name)}&file=B10`;
     app.addCustomMetaData(obsidianURL, {for: "obsidianurl", to: r})
  })
}

Not tested, since I’m away from my Mac.

2 Likes

I’ve noticed some mysterious behavior in Obsidian, where links with (and without) the file extension open on Mac but on iOS they only open if there is no file extension.

Is there a way to modify the script such that the filename without extension is used for the URL encoding, instead of the full filename? I tried “filename without extension” but that leads to invalid code.

Instead of this link generated by the current script: obsidian://open?vault=B10&file=Specialties%20of%20the%20Stoic%20philosophers.md

I would like to generate this one: obsidian://open?vault=B10&file=Specialties%20of%20the%20Stoic%20philosophers

Have you talked to them about this?

Honestly, my first intuition was that there’s probably a simple way to exclude the extension via the script and be done :wink: It’s part of a pattern where I use DevonThink to address the bugs and inadequacies in certain other applications…

If that’s not possible in this case, then I would contact the Obsidian people in hopes that they address this in some future update.

How so? That would’ve been my first idea.

Alternatively, I’d chop off the extension in JavaScript with
const noExtension = r.name().replace(/(.*)\.*/,"$1")
In AppleScript, you’d use some set text delimiter magic.

In any case, treating an extension as if it were not there seems like a bug to me – what if you have two files that differ only in the existence of an extension?

After checking the AppleScript dictionary for DevonThink (note to self: make that a habit before asking in the forum :innocent: ), I found that the error was in this line of the modified script I was experimenting with:

set recordFilename to filename without extension of thisRecord

For the script to run, it needs to be instead:

set recordFilename to name without extension of thisRecord

The script now works as expected.

To be honest, I realized that this was user error and the links for Obsidian on iOS actually work correctly. When I set up the Obsidian sync vault on my iPhone, I gave a slightly different name to one of the vaults than on the Mac. So when the link with extension didn’t work it was because it was related to the incorrectly named sync vault, and when it worked without extension I was coincidentally testing with a link for the vault that was named correctly. So my conclusion that the extension is the issue was premature and ultimately false. Some efforts modifying the script were therefore in vain, but hey… I learned something once again! :slight_smile:

Interesting alternative, which I wasn’t aware of and will keep in mind for future scripting scenarios. Thanks for the hint.

That’s far more common than people may thing :smiley: