diff --git a/src/chrome/content/book.js b/src/chrome/content/book.js index 08b4efc..a783a89 100644 --- a/src/chrome/content/book.js +++ b/src/chrome/content/book.js @@ -1,14 +1,32 @@ Book = { - generateAuthors (author) { + generateAuthor(author) { + if (!Utilities.safeGetFromJson(author, ["name"])) { + return null; + } + + fullName = Utilities.safeGetFromJson(author, ["name"]); + + if (fullName.includes(',')) { + const [lastName, firstName] = fullName.split(',').map(part => part.trim()); + return { firstName, lastName, "creatorType": "author" }; + } + + const lastSpaceIndex = fullName.lastIndexOf(' '); + if (lastSpaceIndex !== -1) { + const lastName = fullName.slice(lastSpaceIndex + 1).trim(); + const firstName = fullName.slice(0, lastSpaceIndex).trim(); + return { firstName, lastName, "creatorType": "author" }; + } + + return { firstName: fullName, lastName: '', "creatorType": "author" }; + }, + + generateAuthors (authors) { var newAuthorList = []; - if (author) { - author.forEach(element => { + if (authors) { + authors.forEach(author => { newAuthorList.push( - { - "firstName": element["given"], - "lastName": element["family"], - "creatorType": "author" - } + this.generateAuthor(author) ) }); } @@ -28,26 +46,24 @@ Book = { }, getMetaData (item) { - var doi = item.getField('DOI'); - if (item.itemTypeID !== Zotero.ItemTypes.getID('journalArticle')) { - Utilities.publishError("Unsupported Item Type", "Only Journal Article is supported.") - return; + var isbn = item.getField('ISBN').replace(/-/g, ''); + if (item.itemTypeID !== Zotero.ItemTypes.getID('book')) { + // Utilities.publishError("Unsupported Item Type", "Only Book is supported.") + return null; } - if (!doi) { + if (!isbn) { // Utilities.publishError("DOI not found", "DOI is required to retrieve metadata.") - return; + return null; } - var url = 'http://dx.doi.org/' + doi; - const headers = new Headers({'Accept': 'application/vnd.citationstyles.csl+json'}); - var requestInfo = { method: 'GET', headers }; + var url = 'https://openlibrary.org/api/books?jscmd=data&format=json&bibkeys=ISBN:' + isbn; + var requestInfo = { method: 'GET' }; return Utilities.fetchWithTimeout(url, requestInfo, 3000) .then(response => { if (!response.ok) { Utilities.publishError("Error retrieving metadata", - "Please check if DOI is correct and if you have network access to dx.doi.org."); + "Please check if ISBN is correct and if you have network access to openlibrary.org."); return null; - } return response.text() }) @@ -58,26 +74,22 @@ Book = { return null; } }) + .then(dataJson => { - var Title = Utilities.safeGetFromJson(dataJson, ["title"]); - var Authors = this.generateAuthors(Utilities.safeGetFromJson(dataJson, ["author"])); - var Publication = Utilities.safeGetFromJson(dataJson, ["container-title"]); - var Volume = Utilities.safeGetFromJson(dataJson, ["volume"]); - var Issue = Utilities.safeGetFromJson(dataJson, ["issue"]); - var Pages = Utilities.safeGetFromJson(dataJson, ["page"]); - var PublishDate = this.generateDate(Utilities.safeGetFromJson(dataJson, ["published", "date-parts"])); - var JournalAbbr = Utilities.safeGetFromJson(dataJson, ["container-title-short"]); - var Language = Utilities.safeGetFromJson(dataJson, ["language"]); + var KeyISBN = 'ISBN:' + isbn; + var Title = Utilities.safeGetFromJson(dataJson, [KeyISBN, "title"]); + var Authors = this.generateAuthors(Utilities.safeGetFromJson(dataJson, [KeyISBN, "authors"])); + var Publisher = Utilities.safeGetFromJson(dataJson, [KeyISBN, "publishers","0","name"]); + var PublishPlace = Utilities.safeGetFromJson(dataJson, [KeyISBN, "publish_places","0","name"]); + var PublishDate = Utilities.safeGetFromJson(dataJson, [KeyISBN, "publish_date"]); + var Pages = Utilities.safeGetFromJson(dataJson, [KeyISBN, "number_of_pages"]); return { "Title": Title ? Title : "", "Authors": Authors ? Authors : "", - "Publication": Publication ? Publication : "", - "Volume": Volume ? Volume : "", - "Issue": Issue ? Issue : "", - "Pages": Pages ? Pages : "", + "Publisher": Publisher ? Publisher : "", + "PublishPlace": PublishPlace ? PublishPlace : "", "PublishDate": PublishDate ? PublishDate : "", - "JournalAbbr": JournalAbbr ? JournalAbbr : "", - "Language": Language ? Language : "" + "Pages": Pages ? Pages : "" }; }); }, @@ -88,15 +100,12 @@ Book = { return 1; } - if (!Utilities.isEmpty(metaData["Title"])) item.setField('title',metaData["Title"]); - if (!Utilities.isEmpty(metaData["Authors"])) item.setCreators(metaData["Authors"]); - if (!Utilities.isEmpty(metaData["Publication"])) item.setField('publicationTitle',metaData["Publication"]); - if (!Utilities.isEmpty(metaData["Volume"])) item.setField('volume',metaData["Volume"]); - if (!Utilities.isEmpty(metaData["Issue"])) item.setField('issue',metaData["Issue"]); - if (!Utilities.isEmpty(metaData["Pages"])) item.setField('pages',metaData["Pages"]); - if (!Utilities.isEmpty(metaData["PublishDate"])) item.setField('date',metaData["PublishDate"]); - if (!Utilities.isEmpty(metaData["JournalAbbr"])) item.setField('journalAbbreviation',metaData["JournalAbbr"]); - if (!Utilities.isEmpty(metaData["Language"])) item.setField('language',metaData["Language"]); + if (!Utilities.isEmpty(metaData["Title"])) item.setField('title',metaData["Title"]); + if (!Utilities.isEmpty(metaData["Authors"])) item.setCreators(metaData["Authors"]); + if (!Utilities.isEmpty(metaData["Publisher"])) item.setField('publisher',metaData["Publisher"]); + if (!Utilities.isEmpty(metaData["PublishPlace"])) item.setField('place',metaData["PublishPlace"]); + if (!Utilities.isEmpty(metaData["PublishDate"])) item.setField('date',metaData["PublishDate"]); + if (!Utilities.isEmpty(metaData["Pages"])) item.setField('numPages',metaData["Pages"]); await item.saveTx(); return 0; }, diff --git a/src/chrome/content/error.js b/src/chrome/content/error.js new file mode 100644 index 0000000..17b41c9 --- /dev/null +++ b/src/chrome/content/error.js @@ -0,0 +1,34 @@ +class TimeoutError extends Error { + constructor(message) { + super(message); + this.name = "TimeoutError"; + } +} + +class UnsupportedItemTypeError extends Error { + constructor(message) { + super(message); + this.name = "UnsupportedItemTypeError"; + } +} + +class TimeoutError extends Error { + constructor(message) { + super(message); + this.name = "TimeoutError"; + } +} + +class TimeoutError extends Error { + constructor(message) { + super(message); + this.name = "TimeoutError"; + } +} + +class TimeoutError extends Error { + constructor(message) { + super(message); + this.name = "TimeoutError"; + } +} diff --git a/src/chrome/content/journal.js b/src/chrome/content/journal.js index 815779e..e398fd9 100644 --- a/src/chrome/content/journal.js +++ b/src/chrome/content/journal.js @@ -1,14 +1,14 @@ Journal = { - generateAuthors (author) { + generateAuthors (authors) { var newAuthorList = []; - if (author) { - author.forEach(element => { + if (authors) { + authors.forEach(author => { newAuthorList.push( - { - "firstName": element["given"], - "lastName": element["family"], - "creatorType": "author" - } + { + "firstName": author["given"], + "lastName": author["family"], + "creatorType": "author" + } ) }); } @@ -30,12 +30,12 @@ Journal = { getMetaData (item) { var doi = item.getField('DOI'); if (item.itemTypeID !== Zotero.ItemTypes.getID('journalArticle')) { - Utilities.publishError("Unsupported Item Type", "Only Journal Article is supported.") - return; + // Utilities.publishError("Unsupported Item Type", "Only Journal Article is supported.") + return null; } if (!doi) { // Utilities.publishError("DOI not found", "DOI is required to retrieve metadata.") - return; + return null; } var url = 'http://dx.doi.org/' + doi; @@ -99,36 +99,5 @@ Journal = { if (!Utilities.isEmpty(metaData["Language"])) item.setField('language',metaData["Language"]); await item.saveTx(); return 0; - }, - - async updateSelectedItemsMetadata() { - var items = Zotero.getActiveZoteroPane().getSelectedItems(); - var itemCount = items.length; - if (itemCount === 0) { - Utilities.publishSuccess("Finished", "No item is selected.") - } - var progressHandle = Utilities.initializeProgress("Updating metadata for " + itemCount + " items...") - - var pool = new ThreadPool(5); - var progress = 0; - var successCount = 0; - var failedCount = 0; - for (let i = 0; i < itemCount; i++) { - pool.submit(async () => { - var status = await this.updateMetadata(items[i]); - if (status === 0) { - successCount++; - } else if(status === 1) { - failedCount++; - } - progress++; - var progressMapped = Math.round(progress / itemCount * 100); - await Utilities.publishProgress(progressHandle, progressMapped, progress + " out of " + itemCount + " finished updating."); - }); - } - - pool.execute(); - await pool.wait(); - await Utilities.publishSuccess("Finished", successCount + " items updated, " + failedCount + " items failed."); } } \ No newline at end of file diff --git a/src/chrome/content/utilities.js b/src/chrome/content/utilities.js index cd78129..9e542e0 100644 --- a/src/chrome/content/utilities.js +++ b/src/chrome/content/utilities.js @@ -8,6 +8,7 @@ Utilities = { progressWindowError.show(); progressWindowError.startCloseTimer(3000); }, + publishSuccess(title, message) { var progressWindowSuccess = new Zotero.ProgressWindow({closeOnClick:true}); var successIcon = "chrome://zotero/skin/tick.png"; @@ -16,6 +17,7 @@ Utilities = { progressWindowSuccess.show(); progressWindowSuccess.startCloseTimer(3000); }, + initializeProgress(title, message) { var progressWindowProgress = new Zotero.ProgressWindow({closeOnClick:true}); var loadingIcon = "chrome://zotero/skin/spinner-16px.png"; @@ -25,9 +27,9 @@ Utilities = { progressWindowProgress.progress.setText(message); progressWindowProgress.show(); return progressWindowProgress; - }, - publishProgress(handle, progress, message) { + + publishProgress(handle, progress, message, title = null) { var validatedProgress = Math.min(Math.max(progress, 0), 100); handle.progress.setProgress(validatedProgress); handle.progress.setText(message); @@ -35,6 +37,9 @@ Utilities = { var successIcon = "chrome://zotero/skin/tick.png"; handle.progress.setIcon(successIcon); } + if (title) { + handle.changeHeadline(title); + } handle.show(); }, diff --git a/src/chrome/content/zotmeta.js b/src/chrome/content/zotmeta.js index 2e96144..5ed65dd 100644 --- a/src/chrome/content/zotmeta.js +++ b/src/chrome/content/zotmeta.js @@ -29,7 +29,7 @@ ZotMeta = { menuitem.setAttribute('type', 'button'); menuitem.setAttribute('data-l10n-id', 'update-metadata'); menuitem.addEventListener('command', () => { - Journal.updateSelectedItemsMetadata(); + this.updateSelectedItemsMetadata(); }); doc.getElementById('zotero-itemmenu').appendChild(menuitem); this.storeAddedElement(menuitem); @@ -81,4 +81,43 @@ ZotMeta = { this.removeFromWindow(win); } }, + + async updateSelectedItemsMetadata() { + var items = Zotero.getActiveZoteroPane().getSelectedItems(); + var itemCount = items.length; + if (itemCount === 0) { + Utilities.publishSuccess("Finished", "No item is selected.") + } + var progressHandle = Utilities.initializeProgress("Updating metadata for " + itemCount + " items...") + + var pool = new ThreadPool(5); + var progress = 0; + var successCount = 0; + var failedCount = 0; + for (let i = 0; i < itemCount; i++) { + pool.submit(async () => { + var item = items[i]; + var status; + if (item.itemTypeID === Zotero.ItemTypes.getID('book')) { + status = await Book.updateMetadata(item); + } else if (item.itemTypeID === Zotero.ItemTypes.getID('journalArticle')) { + status = await Journal.updateMetadata(item); + } else { + status = 1; + } + if (status === 0) { + successCount++; + } else if(status === 1) { + failedCount++; + } + progress++; + var progressMapped = Math.round(progress / itemCount * 100); + Utilities.publishProgress(progressHandle, progressMapped, progress + " out of " + itemCount + " finished updating."); + }); + } + + pool.execute(); + await pool.wait(); + Utilities.publishProgress(progressHandle, 100, successCount + " items updated, " + failedCount + " items failed.", "Finished"); + } };