Help with DTP3-Bookends integration

I spent a long time exploring the many scripts available on the forum for linking Bookends and DevonThink Pro 3. Some of those involve putting a DTP UUID into field user20 in Bookends. However, rather than use one of those scripts I decided that the most reliable and usable method was to use the built-in “File | Import | References from Bookends” option. However it would be useful if, having imported references into DTP3, I could place the DevonThink UUID into a field in the corresponding Bookends entry. This can be done easily in the following way:

(1) Select a reference in DTP3 (this is an RTF created by the Import References from Bookends menu item)
(2) Copy item link
(3) Click on the URL (which takes me to the reference in bookends)
(4) Paste into the chosen Bookends field (eg user 20)
(5) Use the Bookends field to return to the reference in DTP3
Then move to the next reference.

But when there are lots of references it is tedious doing this one reference at a time.

Starting with some other scripts on the forum and in DTP3, I tried writing an Applescript to do this for a batch of references but it did not work. I have inserted comments at the point where I assume I went wrong, but maybe there are more basic problems. Advice would be welcome. I can’t help thinking it ought to be an easy script to write.

tell application id "DNtp"
	set theSelection to the selection
	if theSelection is {} then error "Please select some contents."
	repeat with theRecord in theSelection
		set recordUUID to uuid of theRecord
		set BookendsID to URL of theRecord
		tell application "Bookends"
			tell front library window
				--select reference corresponding to BookendsID
				--paste recordUUID into user20 [or another field] of selected reference
			end tell
		end tell
	end repeat
end tell

By what exactly didn’t work or what happened?

Btw: I think you should use selected records instead of selection and probably not nest tell blocks. Though I don’t really know AppleScript.

In this case it doesn’t matter whether selected records or selection is used. The first one is a relationship and supports things like selected record 1 or queries like UUID of selected records, the second one is a property (and dating back to version 1.x) and doesn’t support such things.

In addition, nested tell blocks are not unusual and shouldn’t cause any problems.

In a nested tell block, where does a command like close go to – the inner or the outer app?

Whatever tell block you’re in.

tell application id "DNtp"
	tell application "Finder"
		close window 1
	end tell
end tell

closes the Finder window, not DT’s.

If your purpose is to jump back and forth between Bookends and DT, ryanjamurphy’s script (Suggestions for annotations between DT, Bookends and Obsidian - #6 by jtaekman) very effective. You don’t even need to put the url to user20 field.

It’s not as simple as you imagine, though not horribly complex either.
Here is a learning edition script that does what you mentioned…

set od to AppleScript's text item delimiters
-- Remember to cache the text item delimiters, otherwise weird things can happen later on in a script.

tell application id "DNtp"
	-- Check if a Bookends Library is open.
	-- Note: Launching a Bookends URL will not open the containing library. It has to be opened manually.
	tell application "Bookends"
		if not (exists library window 1) then
			display alert "Please open the required Bookends library" buttons {"Quit"}
		end if
	end tell
	if (selected records) is {} then return -- Don't do anything with nothing selected
	repeat with theRecord in (selected records)
		set isMissing to false -- Assume a record will be found
		set {recURL, recUUID} to {URL, reference URL} of theRecord -- Get the Bookends URL and DEVONthink's item link.
		-- Parse the Bookends ID from its url scheme
		set AppleScript's text item delimiters to "/" -- URLs are separated  by forward slashes so split the URL on them.
		set bookendsID to last text item of recURL -- Grab the ID from the end of the URL.
		set AppleScript's text item delimiters to od -- Remember to reset the delimiters after use.
		if recURL begins with "bookends" then -- Only process documents with a Bookends URL.
			tell application "Bookends"
				try -- Bookends errors instead of returning a missing value so we have to use a try block
					set matchedDoc to (first publication item of library window 1 whose (id is bookendsID))
					set user20 of matchedDoc to recUUID
				on error
					set isMissing to true -- If no document is found, set the variable.
				end try
			end tell
		end if
		if isMissing then log message info "A matching Bookends document couldn't be found." record theRecord
		-- If the document is missing, log it in DEVONthink's Window > Log.
	end repeat
end tell

One reason it is more complicated is that you are allowing for the possibility that recURL may not contain a Bookends link but something else, and you are checking for that. The other reason is that I did not know how the recURL related to the BE identifier.

I shall study this carefully and see what I can do with it.

Thank you very much.

You’re welcome :slight_smile:

The basics of scripting is often simple. The error-trapping is what usually complicates things. It’s easy to create a script with a stacked deck, handling specific documents in controlled conditions. Thinking outside the current situation, especially if you’re deploying or sharing a script, requires a lot more consideration. So yes, you shouldn’t assume there’s a valid URL or any URL at all.

And in this case, the URL is required to find a match in Bookends. Also, you need to know the Bookends URL is not the item’s id. Only the last part of the URL. That’s why it needed to be parsed out.

When I first ran this, I got a “missing variable od” error and hope I did the right thing changing od to “” to return to the default delimiter, but with that change the script seems to do just what I was hoping. Thank you again. If that was not correct, what should it be?

I don’t want to do it in this case, but am I right to think that if I wanted to append to the BE field instead of overwriting whatever is there, I could replace the line

set user20 of matchedDoc to recUUID

with something like

set user20 of matchedDoc to user20 & recUUID

You are of course right to think of the possibility that the script might inadvertently be used on a file that does not have suitable data.

Thanks for the suggestion but I did try this script a few months ago but did not find that it worked as I hoped. I forget why, but it may be that it did not deal with BE references that did not have attachments. I think I broke it into two scripts, one to go in each direction.

What I did not say is that a supplementary reason for wanting the DTP UUID in a BE field is so that I can include it in data exported to third app.

1 Like

The very first line sets the od variable.

set od to AppleScript's text item delimiters

set user20 of matchedDoc to user20 & recUUID

Essentially, but you should add a space – & " " & or & linefeed & – or it will run the strings together.

Very sorry. My cutting and pasting missed that line.

Thanks again.