From e6aa7aecbbb4ce635b1591ebdd3305acd69aa27a Mon Sep 17 00:00:00 2001
From: AshleyDeo <35739765+AshleyDeo@users.noreply.github.com>
Date: Tue, 23 Jul 2024 13:44:48 -0400
Subject: [PATCH 1/2] Update opf and add isbn
Reads all authors for multi-author book.
Add google books id from opf
Add ISBN as External Id. Uses WorldCat.org as external link
---
.../Providers/ISBNExternalId.cs | 26 +++++++++++++++++++
.../Providers/OpfReader.cs | 21 +++++++++++----
2 files changed, 42 insertions(+), 5 deletions(-)
create mode 100644 Jellyfin.Plugin.Bookshelf/Providers/ISBNExternalId.cs
diff --git a/Jellyfin.Plugin.Bookshelf/Providers/ISBNExternalId.cs b/Jellyfin.Plugin.Bookshelf/Providers/ISBNExternalId.cs
new file mode 100644
index 00000000..3ea08d92
--- /dev/null
+++ b/Jellyfin.Plugin.Bookshelf/Providers/ISBNExternalId.cs
@@ -0,0 +1,26 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace Jellyfin.Plugin.Bookshelf.Providers
+{
+ ///
+ public class ISBNExternalId : IExternalId
+ {
+ ///
+ public string ProviderName => "ISBN";
+
+ ///
+ public string Key => "ISBN";
+
+ ///
+ public ExternalIdMediaType? Type => null;
+
+ ///
+ public string? UrlFormatString => "https://search.worldcat.org/search?q=bn:{0}";
+
+ ///
+ public bool Supports(IHasProviderIds item) => item is Book;
+ }
+}
diff --git a/Jellyfin.Plugin.Bookshelf/Providers/OpfReader.cs b/Jellyfin.Plugin.Bookshelf/Providers/OpfReader.cs
index 3768242f..7dc5abec 100644
--- a/Jellyfin.Plugin.Bookshelf/Providers/OpfReader.cs
+++ b/Jellyfin.Plugin.Bookshelf/Providers/OpfReader.cs
@@ -104,11 +104,7 @@ public MetadataResult ReadOpfData(
var book = CreateBookFromOpf();
var bookResult = new MetadataResult { Item = book, HasMetadata = true };
- ReadStringInto("//dc:creator", author =>
- {
- var person = new PersonInfo { Name = author, Type = PersonKind.Author };
- bookResult.AddPerson(person);
- });
+ FindAuthors(bookResult);
ReadStringInto("//dc:language", language => bookResult.ResultLanguage = language);
@@ -126,6 +122,7 @@ private Book CreateBookFromOpf()
ReadStringInto("//dc:publisher", publisher => book.AddStudio(publisher));
ReadStringInto("//dc:identifier[@opf:scheme='ISBN']", isbn => book.SetProviderId("ISBN", isbn));
ReadStringInto("//dc:identifier[@opf:scheme='AMAZON']", amazon => book.SetProviderId("Amazon", amazon));
+ ReadStringInto("//dc:identifier[@opf:scheme='GOOGLE']", google => book.SetProviderId("GoogleBooks", google));
ReadStringInto("//dc:date", date =>
{
@@ -222,6 +219,20 @@ private string FindMainTitle()
return titleSort;
}
+ private void FindAuthors(MetadataResult book)
+ {
+ var resultElement = _document.SelectNodes("//dc:creator[@opf:role='aut']", _namespaceManager);
+ if (resultElement != null && resultElement.Count > 0)
+ {
+ foreach (XmlElement author in resultElement)
+ {
+ var authorName = author.InnerText;
+ var person = new PersonInfo { Name = authorName, Type = PersonKind.Author };
+ book.AddPerson(person);
+ }
+ }
+ }
+
private void ReadStringInto(string xPath, Action commitResult)
{
var resultElement = _document.SelectSingleNode(xPath, _namespaceManager);
From c0d2177afd61b41b11d60ff432e7e8ffb0f65b39 Mon Sep 17 00:00:00 2001
From: AshleyDeo <35739765+AshleyDeo@users.noreply.github.com>
Date: Tue, 23 Jul 2024 21:07:25 -0400
Subject: [PATCH 2/2] Parse opf roles
---
.../Providers/OpfReader.cs | 40 +++++++++++++++++--
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/Jellyfin.Plugin.Bookshelf/Providers/OpfReader.cs b/Jellyfin.Plugin.Bookshelf/Providers/OpfReader.cs
index 7dc5abec..a7b6dfff 100644
--- a/Jellyfin.Plugin.Bookshelf/Providers/OpfReader.cs
+++ b/Jellyfin.Plugin.Bookshelf/Providers/OpfReader.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -221,18 +223,48 @@ private string FindMainTitle()
private void FindAuthors(MetadataResult book)
{
- var resultElement = _document.SelectNodes("//dc:creator[@opf:role='aut']", _namespaceManager);
+ var resultElement = _document.SelectNodes("//dc:creator", _namespaceManager);
if (resultElement != null && resultElement.Count > 0)
{
- foreach (XmlElement author in resultElement)
+ foreach (XmlElement creator in resultElement)
{
- var authorName = author.InnerText;
- var person = new PersonInfo { Name = authorName, Type = PersonKind.Author };
+ var creatorName = creator.InnerText;
+ string? role = creator.GetAttribute("opf:role");
+ var person = new PersonInfo { Name = creatorName, Type = GetRole(role) };
book.AddPerson(person);
}
}
}
+ private PersonKind GetRole(string role)
+ {
+ switch (role)
+ {
+ case "arr":
+ return PersonKind.Arranger;
+ case "art":
+ return PersonKind.Artist;
+ case "aut":
+ case "aqt":
+ case "aft":
+ case "aui":
+ default:
+ return PersonKind.Author;
+ case "edt":
+ return PersonKind.Editor;
+ case "ill":
+ return PersonKind.Illustrator;
+ case "lyr":
+ return PersonKind.Lyricist;
+ case "mus":
+ return PersonKind.AlbumArtist;
+ case "oth":
+ return PersonKind.Unknown;
+ case "trl":
+ return PersonKind.Translator;
+ }
+ }
+
private void ReadStringInto(string xPath, Action commitResult)
{
var resultElement = _document.SelectSingleNode(xPath, _namespaceManager);