I’d like to propose an alternative script, written in JavaScript. See below for explanations
(() => {
const DT = Application("DEVONthink 3");
const group = DT.currentGroup();
const groupDB = group.database();
const BE = Application("Bookends");
const window = BE.libraryWindows[0];
/* The fields to get from Bookends. Only those that are used in addCustomMetaData! */
const bookendFields = ["doi","pmid", "isbn", "url", "language", "publicationDateString",
"keywords", "authors", "editors", "publishers", "journal", "volume",
"pages", "user1", "abstract"];
/* Loop over all selected Bookends items */
window.selectedPublicationItems.forEach(item => {
/* Build the BE URL and skip this item if it's already imported */
const URL = `bookends://sonnysoftware.com/${item.id()}`;
if (DT.existsRecordWithURL(URL, {in: groupDB})) return;
/* Item is new – create a DT record using some of the BE data */
const record = DT.createRecordWith({
name: item.title(),
type: "rtf",
content: BE.format(item, {using: "Summary.fmt", as: "RTF"}),
rating: item.rating(),
comment: item.notes(),
tags: item.keywords().split('\n'),
creationDate: item.dateAdded(),
modificationDate: item.dateModified(),
URL: URL
}, {in: groupDB});
/* Copy content for all BE fields in 'bookendFields' to new record's custom meta data.
special handling for 'url' and 'user1', since those are named differently in DT */
bookendFields.forEach(key => {
if (key === "url") {
DT.addCustomMetaData(item.url(), {for: "link", to: record});
} else if (key === "user1") {
DT.addCustomMetaData(item.user1(), {for: "citation", to: record});
} else {
DT.addCustomMetaData(item[key](), {for: key, to: record});
}
DT.addCustomMetaData(BE.format(item, {using: "APA 6th Edition Markdown.fmt"}));
})
})
})()
In my opinion, this code is “better” because
- It’s a lot shorter, thus easier to understand (for some, I think),
- It’s less repetitive, thus easier to read,
- It uses an array of fields to get from Bookends and use as custom metadata in DT. That makes it easy to add/remove more fields
- It removes invariants from the loop over the Bookends records (the DT group and this group’s database)
- It checks if the record already exists before it does any other work and immediately skips to the next Bookends entry in this case.
- It’s commented
I think that some of that cannot be done in AppleScript, though. For example, it doesn’t seem to be (directly) possible to access a record’s element using a variable like in
set key to "rating"
set rating to key of theRef
But hoisting the invariants out of the repeat
loop is possible (and better, in my opinion). Also, checking for the existence of the record in DT would be possible before retrieving all the data from bookends.
One serious disadvantage, though: I couldn’t test the code, due to a lack of Bookends data. If someone can provide me with test data, I’d love to run the script on them.