aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers/Books/OpenPackagingFormat/EpubProvider.cs
diff options
context:
space:
mode:
authordkanada <dkanada@users.noreply.github.com>2025-11-22 16:25:59 +0900
committerdkanada <dkanada@users.noreply.github.com>2025-11-22 16:25:59 +0900
commit6963d9588080f23d351a95051696b6c692afc2c5 (patch)
tree877b873958fd5386cb53107a121c14c630b92543 /MediaBrowser.Providers/Books/OpenPackagingFormat/EpubProvider.cs
parentaa4ddd139a7c01889a99561fc314121ba198dd70 (diff)
extract local metadata from OPF and EPUB files
Diffstat (limited to 'MediaBrowser.Providers/Books/OpenPackagingFormat/EpubProvider.cs')
-rw-r--r--MediaBrowser.Providers/Books/OpenPackagingFormat/EpubProvider.cs100
1 files changed, 100 insertions, 0 deletions
diff --git a/MediaBrowser.Providers/Books/OpenPackagingFormat/EpubProvider.cs b/MediaBrowser.Providers/Books/OpenPackagingFormat/EpubProvider.cs
new file mode 100644
index 0000000000..bc77e5928d
--- /dev/null
+++ b/MediaBrowser.Providers/Books/OpenPackagingFormat/EpubProvider.cs
@@ -0,0 +1,100 @@
+using System;
+using System.IO;
+using System.IO.Compression;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Xml;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.IO;
+using Microsoft.Extensions.Logging;
+
+namespace MediaBrowser.Providers.Books.OpenPackagingFormat
+{
+ /// <summary>
+ /// Provides book metadata from OPF content in an EPUB item.
+ /// </summary>
+ public class EpubProvider : ILocalMetadataProvider<Book>
+ {
+ private readonly IFileSystem _fileSystem;
+ private readonly ILogger<EpubProvider> _logger;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="EpubProvider"/> class.
+ /// </summary>
+ /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
+ /// <param name="logger">Instance of the <see cref="ILogger{EpubProvider}"/> interface.</param>
+ public EpubProvider(IFileSystem fileSystem, ILogger<EpubProvider> logger)
+ {
+ _fileSystem = fileSystem;
+ _logger = logger;
+ }
+
+ /// <inheritdoc />
+ public string Name => "EPUB Metadata";
+
+ /// <inheritdoc />
+ public Task<MetadataResult<Book>> GetMetadata(ItemInfo info, IDirectoryService directoryService, CancellationToken cancellationToken)
+ {
+ var path = GetEpubFile(info.Path)?.FullName;
+
+ if (path is null)
+ {
+ return Task.FromResult(new MetadataResult<Book> { HasMetadata = false });
+ }
+
+ var result = ReadEpubAsZip(path, cancellationToken);
+
+ if (result is null)
+ {
+ return Task.FromResult(new MetadataResult<Book> { HasMetadata = false });
+ }
+ else
+ {
+ return Task.FromResult(result);
+ }
+ }
+
+ private FileSystemMetadata? GetEpubFile(string path)
+ {
+ var fileInfo = _fileSystem.GetFileSystemInfo(path);
+
+ if (fileInfo.IsDirectory)
+ {
+ return null;
+ }
+
+ if (!string.Equals(Path.GetExtension(fileInfo.FullName), ".epub", StringComparison.OrdinalIgnoreCase))
+ {
+ return null;
+ }
+
+ return fileInfo;
+ }
+
+ private MetadataResult<Book>? ReadEpubAsZip(string path, CancellationToken cancellationToken)
+ {
+ using var epub = ZipFile.OpenRead(path);
+
+ var opfFilePath = EpubUtils.ReadContentFilePath(epub);
+ if (opfFilePath == null)
+ {
+ return null;
+ }
+
+ var opf = epub.GetEntry(opfFilePath);
+ if (opf == null)
+ {
+ return null;
+ }
+
+ using var opfStream = opf.Open();
+
+ var opfDocument = new XmlDocument();
+ opfDocument.Load(opfStream);
+
+ var utilities = new OpfReader<EpubProvider>(opfDocument, _logger);
+ return utilities.ReadOpfData(cancellationToken);
+ }
+ }
+}