Skip to content

Example: using Zowie with DEVONthink

Mike Hucka edited this page Jan 15, 2022 · 27 revisions

When using Zotero for reference management, you may on occasion want to work with the file attachments from outside of Zotero. For example, if you're a DEVONthink user, you will at some point discover the power of indexing your local Zotero database from DEVONthink. However, when viewing or manipulating the PDF files from outside of Zotero, you may run into the following problem: when looking at a given PDF file, how do you find out which Zotero entry it belongs to?

Using Zowie to write the Zotero select link into the Finder comments of every PDF file makes it possible to find that link outside of Zotero. For example, in the Finder, you can do Get Info on the file and find the Zotero in the Finder Comments. The Finder Comments are also visible in DEVONthink's Annotations & Reminders inspector:

Smart rule to run Zowie

In my DEVONthink setup, I index the Zotero storage folder where Zotero writes PDF attachments. Then, I use a smart rule in DEVONthink to run Zowie. The rule is set up to act on the indexed folder, and trigger when a file is added. Here is the rule definition:

Here is the script invoked by the smart rule. (The latest version of this script is always available in my devonthink-hacks repository – instead of copying the code below, make sure to check the repository for the latest version.)

-- ======================================================================
-- @file	Run Zowie on newly indexed PDF.applescript
-- @brief	Script for DEVONthink smart rule to run Zowie on new additions
-- @author	Michael Hucka <[email protected]>
-- @license MIT license; please see the file LICENSE in the repo
-- @repo	https://github.com/mhucka/devonthink-hacks
--
-- This is an AppleScript fragment that will only work as the script
-- executed by a Smart Rule in DEVONthink. For more information, see
-- https://github.com/mhucka/devonthink-hacks/zowie-scripts
-- ======================================================================

on performSmartRule(selectedRecords)
	tell application "System Events"
		-- In my environment, Zotero takes time to upload a newly-added
		-- PDF to the cloud. The following delay is needed to give time
		-- for the upload to take place, so that when Zowie runs and
		-- queries Zotero via the network API, the data will be there.
		delay 15
	end tell
	tell application id "DNtp"
		try
			repeat with _record in selectedRecords
				set raw_path to the path of _record
		
				-- A problem for shell strings is embedded single quotes.
				-- Combo of changing text delimiters & using AppleScript
				-- "quoted form of" seems to do the trick.
				set AppleScript's text item delimiters to "\\\\"
				set quoted_file_path to quoted form of raw_path
		
				-- Now run Zowie. The PATH setting adds common locations
				-- where Zowie may be installed on the user's computer.
				set result to do shell script ¬
					"PATH=$PATH:$HOME/.local/bin:/usr/local/bin" ¬
					& " zowie -s -q " & quoted_file_path
		
				-- Display a notification if Zowie returned a msg.
				if result  "" then
					display notification result
				else
					-- If all went well, tell DEVONthink explicitly to set
					-- the comment, because it does not consistently
					-- "notice" the addition of a comment after a file has
					-- already been indexed.
					set comment of _record to my finderComment(raw_path)

					-- Also force execution of smart rules with "on import"
					-- triggers. This is needed because some of my rules use
					-- the URL in the Finder comment, but DEVONthink smart
					-- rules won't trigger when the only change to a file is
					-- to the Finder comment.
					perform smart rule record _record trigger import event
				end if
			end repeat
		on error msg number code
			if the code is not -128 then
				display alert "DEVONthink" message msg as warning
			end if
		end try
	end tell
end performSmartRule

-- Function to ask the Finder to read the comment. 

on finderComment(f)
	tell application "Finder"
		return comment of (POSIX file f as alias)
	end tell
end finderComment

-- Function to make literal text substitutions.
-- The following function is based on code posted by user "mb21" on
-- 2016-06-26 at https://stackoverflow.com/a/38042023/743730

on substituted(search_string, replacement_string, this_text)
	set AppleScript's text item delimiters to the search_string
	set the item_list to every text item of this_text
	set AppleScript's text item delimiters to the replacement_string
	set this_text to the item_list as string
	set AppleScript's text item delimiters to ""
	return this_text
end substituted

Smart rule to copy Finder comment to the URL field

The nice thing about having the Zotero select link accessible from DEVONthink is that you can create smart rules to manipulate it further. For example, I use the following smart rule to copy the Zotero select link from the Finder Comments to the "URL" field of each PDF file from my Zotero storage folder indexed in DEVONthink:

where the following is the simple embedded script:

on performSmartRule(theRecords)
    tell application id "DNtp"
        repeat with theRecord in theRecords
            set URL of theRecord to (get comment of theRecord)
        end repeat
    end tell
end performSmartRule

Notice that the triggering event for "perform the action" is "every minute". The reason is the following: the file is already indexed and imported by DEVONthink, and what is done by the (other) smart rule to run Zowie is merely to change the Finder comment on the file. None of the other DEVONthink rule event type will be triggered by such a change, so all that we are left with is the option to run the URL-updating rule on a schedule.