Friday, September 5, 2008

More applescripts for Delicious Library 2

Some more applescripts for Delicious Library 2. Applescripts go into ~/Library/Scripts/Applications/Delicious Library 2/.

You can download an archive of these scripts here

1) A short hotkey script to allow you to toggle the played/read checkbox. The settings are to put it into the Edit menu. You can reassign the hotkey/menu choice to your liking.

-- Menu Title: [3] "Toggle Experienced Flag"
-- Menu Keyboard Shortcut: command-`
-- Menu Path: [3]

-- Copy and paste everything into Script Editor (use spotlight to find it).
-- Then save to home/Library/Scripts/Applications/Delicious Library 2
-- You can edit the menu keyboard shortcut to be whatever you want.

tell first document of application "Delicious Library 2"
set selectedItems to selected media
set itemsRef to a reference to selectedItems
repeat with mediaItem in itemsRef
set playedStatus to experienced of mediaItem
set experienced of mediaItem to not playedStatus
end repeat
end tell

2) Translate retrieved Amazon title to a Series. More comments at the bottom.

-- Menu Title: [0], "Translate Amazon Name to Series"
-- Menu Keyboard Shortcut: command-option-1
-- Menu Path: [3], "Series Scripts"
-- Maintain a sqlite3 db to track Amazon returned titles and the series they are translated to. Then for future additions, guess the desired series based on previous entries.

-- Attempt to put the database in the scripts directory. do shell script seems to start in user's home.
set databasedir to "'Library/Scripts/Applications/Delicious Library 2/'"
set database to "seriestranslate.db"
set sqlcmd to "cd " & databasedir & "; sqlite3 " & database & " "

-- Create tables if they don't exist
do shell script sqlcmd & "'create table if not exists translate( dl2id text primary key, series text, amazonname text); create index if not exists amazonname_index on translate(amazonname desc);'"

tell first document of application "Delicious Library 2"
set selectedItems to selected media
set selectedItemsRef to a reference to selectedItems
repeat with mediaItem in selectedItemsRef
set itemId to id of mediaItem
set itemSeries to series of mediaItem
set itemAmazonName to name of mediaItem
if itemSeries is missing value or itemSeries is "" then
-- itemSeries doesn't exist so find a new one
set query to "select series from translate where amazonname < \"" & my sql_escape(itemAmazonName) & "\" order by amazonname desc limit 1;"
set seriesName to do shell script sqlcmd & quoted form of query
set query to "replace into translate (dl2id, series, amazonname) values (\"" & my sql_escape(itemId) & "\",\"" & my sql_escape(seriesName) & "\",\"" & my sql_escape(itemAmazonName) & "\");"
do shell script sqlcmd & quoted form of query
set series of mediaItem to seriesName
-- series name already exists so update existing record
-- we don't update name because it may have changed since we retrieved it from Amazon.
set query to "update translate set series = \"" & my sql_escape(itemSeries) & "\" where dl2id == \"" & my sql_escape(itemId) & "\";"
do shell script sqlcmd & quoted form of query
end if
end repeat
end tell

on sql_escape(sqltext)
set AppleScript's text item delimiters to "\""
set the item_list to every text item of sqltext
set AppleScript's text item delimiters to the "\"\""
set sqltext to the item_list as string
set AppleScript's text item delimiters to ""
return sqltext
end sql_escape

Amazon does not populate (usually) the Series field in the information it sends back and it's not really DL2's place to guess from the other information what is appropriate to put there. On the other hand, Amazon's titles for volumes in a series and its formatting does not always agree with my preferences. They've gotten somewhat more consistent recently, but there's no guarantee that whatever Amazon sends back is what I would want to use as my title.

Thus the scripts in my earlier post which let me reset the title based on the Series and NumberInSeries fields.

This script fills in the last part which is to automatically set the Series field based on the title that Amazon returns.

The algorithm is as follows:
1) Maintain a sorted list sorted on the title/name that Amazon returns. In the second column of the list, associate what series the user has decided goes with this title.

2) When you get a new item, search to see where in the list it goes and then get the series information from the entry before it and copy it for this entry.

Example: Your list starts off like:
Eyeshield 21, Volume 1 | Eyeshield 21
Naruto, Volume 1 | Naruto

You then introduce Naruto, Volume 2. This inserts after Naruto, Volume 1 and we copy its series value, "Naruto," which happens to be correct in this case.

The first assumption is that Amazon is reasonably consistent. Volumes in a series will at minimum all have the series name at the front. For example, everything Naruto is "Naruto, xxxxxx". This is true for the majority of the manga I collect.

The second assumption is that I collect manga from earlier volumes to later volumes. So I'm going to get volume 1 before I get volume 10. Given how this algorithm works, it's not that critical that this is strictly followed, but it would be a worst case scenario if for some reason, you collected a series backwards.

This algorithm has an advantage that you don't have to make any assumption as to the precise formatting of the Amazon title. As long as Amazon is reasonably consistent across the volumes, it will work.

The other advantage is that you can arbitrarily rename a series based on your preference. For example, Monster by Naoki Urasawa is officially "Naoki Urasawa's Monster" in the US for whatever licensing reasons. I say screw that, I want the series to be called "Monster" in my library. And this algorithm has no problem with that. Or if you would prefer "Neon Genesis Evangelion" to be filed as "Evangelion." Again, no problem.

So now that the why is done, here's how to use the script.

First off, the script will create a sqlite3 database file in your Delicious Library 2 scripts directory. If you want to put this elsewhere, you can modify the appropriate variables at the top.

When you have new items, select them and run the script. If the series have never been seen before, they will either leave the series values blank or fill in incorrect information due to how the algorithm just uses blind sorting.

Correct the entries that are incorrect, select them again and rerun the script.

At this point, any new items in the series should automatically set with your preferred series name (subject to the assumptions listed above).

If you're satisfied with the series values, you can then run the other two scripts to set the series number and then rename the title.