Skip to content

Instantly share code, notes, and snippets.

@mnot
Last active April 30, 2023 20:29
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mnot/0d7825bde9b9d3233f623c71765f20ca to your computer and use it in GitHub Desktop.
Save mnot/0d7825bde9b9d3233f623c71765f20ca to your computer and use it in GitHub Desktop.
Look up PDFs on crossref.org in DevonThink
-- Look up document metadata on CrossRef.org in DevonThink 3
--
-- Currently sets:
-- * Created date to the document's publication date
-- * Title in document properties
-- * Author in document properties (first author only)
-- * Crossref DOI URL in document properties
-- * A tag for the type of document
-- * Finder comments to a formatted citation (see below)
--
--
-- To install:
-- 0. Quit DevonThink
-- 1. Place this script in the DevonThink Scripts folder (`Scripts -> Open Scripts Folder`)
-- 2. In Terminal, navigate to that folder and run `osacompile -o Crossref\ Lookup.scpt crossref-lookup.applescript; rm crossref-lookup.applescript`
-- 3. Install JSON Helper: https://apps.apple.com/au/app/json-helper-for-applescript/id453114608?mt=12
-- 4. Install exiftool: `brew install exiftool` (using homebrew; see https://brew.sh)
-- 5. Give the script a keyboard shortcut (`System Preferences -> Keyboard -> Shortcuts -> App Shortcuts`) (optional)
--
-- To use:
-- 0. Open a PDF in DevonThink
-- 1. Using your cursor, select a paper's title, ISSN, or similar identifying information
-- 2. Trigger the script (e.g., using they keyboard shortcut
-- 3. Select the best fitting candidate from the list
-- 4. Click `OK`
--
-- To set your citation format:
-- 0. Look up your desired format here: <https://github.com/citation-style-language/styles>
-- 1. Set CitationName below to the name of the apppopriate file *without* the `.csl` extension
set CitationName to "australian-guide-to-legal-citation"
set UAString to "XRefLookup/1.0 (https://gist.github.com/mnot/0d7825bde9b9d3233f623c71765f20ca; mailto:mnot@mnot.net)"
tell application id "DNtp"
try
if not (exists think window 1) then error "No window open."
if not (exists content record) then error "No document selected."
on error error_message number error_number
if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
return
end try
set theRecord to content record
set query to the selected text of think window 1 as string
if query is "" then
set query to name of theRecord
end if
show progress indicator "Looking up references..." steps -1
set theJson to my crossrefLookup(query)
hide progress indicator
-- Populate and display a dialogue
try
set theItems to |items| of message of theJson
set theChoices to {}
repeat with a from 1 to length of theItems
set currentItem to item a of theItems
set titleList to title of currentItem
set title to item 1 of titleList
set dateString to my extractDate(currentItem)
set detailString to my extractAuthor(currentItem)
if not detailString is equal to "" then
set detailString to detailString & ", "
end if
set detailString to detailString & dateString
set theChoice to title & " (" & detailString & ")"
set end of theChoices to theChoice
end repeat
on error error_message number error_number
if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
return
end try
set theChoice to choose from list theChoices with prompt "Select:"
if theChoice is false then return
repeat with a from 1 to length of theChoices
set currentItem to item a of theChoices
if currentItem as string is equal to theChoice as string then
set chosenItem to item a of theItems
end if
end repeat
-- update document
set dateString to my extractDate(chosenItem)
set dateStruct to my appleDate(dateString)
try
set recordPath to path of theRecord
-- date
set the date of theRecord to dateStruct
-- tags
set typeTag to |type| of chosenItem
if typeTag is not in tags of theRecord then
set tagList to tags of theRecord
set end of tagList to typeTag
set tags of theRecord to tagList
end if
-- url
set uri to |URL| of chosenItem
set the URL of theRecord to uri
-- comment
set citation to my lookupCitation(uri)
set the comment of theRecord to citation
-- title
set recordTitle to item 1 of title of chosenItem
my setPDFMetadata("Title", recordTitle, recordPath)
-- author
set authorString to my extractAuthor(chosenItem)
my setPDFMetadata("Author", authorString, recordPath)
on error error_message number error_number
if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
end try
end tell
on crossrefLookup(query)
set apiURL to "https://api.crossref.org/works"
set shellScript to ("curl -A \"" & my UAString & "\" -G " & apiURL ¬
& " --data-urlencode query.bibliographic=" & quoted form of query ¬
& " -d rows=5 -d select=author,title,type,publisher,issued,subject,URL")
set apiResult to (do shell script shellScript)
-- parse json
tell application "JSON Helper"
set jsonResponse to read JSON from apiResult
end tell
if not status of jsonResponse is equal to "OK" then
error "API response not OK: " & message of jsonResponse
return
end if
return jsonResponse
end crossrefLookup
on extractDate(record_item)
try
set [iyear, imonth, iday] to item 1 of |date-parts| of issued of record_item
set dateString to ((iday as string) & "-" & imonth as string) & "-" & iyear as string
on error
try
set [iyear, imonth] to item 1 of |date-parts| of issued of record_item
set dateString to "01-" & (imonth as string) & "-" & iyear as string
on error
try
set iyear to item 1 of |date-parts| of issued of record_item
set dateString to "01-01-" & iyear as string
on error
set dateString to ""
end try
end try
end try
return dateString
end extractDate
on appleDate(date_string)
return date (date_string)
end appleDate
on extractAuthor(record_item)
set firstAuthor to ""
try
set author_entries to author of record_item
on error
return ""
end try
repeat with a from 1 to length of author_entries
set this_entry to item a of author_entries
if sequence of this_entry is equal to "first" then
set firstAuthor to this_entry
end if
end repeat
if firstAuthor is equal to "" then
return ""
end if
try
set authorString to |given| of firstAuthor & " " & family of firstAuthor
on error
try
set authorString to family of firstAuthor
on error
set authorString to |name| of firstAuthor
end try
end try
return authorString
end extractAuthor
on setPDFMetadata(mdKey, mdValue, recordPath)
set shellCommand to "/opt/homebrew/bin/exiftool -overwrite_original -" & mdKey & "=" & quoted form of mdValue & " " & quoted form of recordPath
set exifresult to do shell script shellCommand
end setPDFMetadata
on lookupCitation(uri)
set shellScript to ("curl -A \"" & my UAString & "\" " & ¬
"-LH \"Accept: text/bibliography; style=" & my CitationName & "\" " & uri)
set apiResult to (do shell script shellScript)
return apiResult
end lookupCitation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment