From 9375f31bd33f1174f70af84c5c110da17bc3ade0 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 15 Jun 2026 16:28:58 +0000
Subject: [PATCH 1/3] Update dependency SharpCompress to 0.49.1
---
Directory.Packages.props | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 6d2845d1e7..7ab5b5d53a 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -67,7 +67,7 @@
-
+
From f6bb086415988b144c4e944dae3292f9f0862d6b Mon Sep 17 00:00:00 2001
From: Bond_009
Date: Mon, 15 Jun 2026 18:52:20 +0200
Subject: [PATCH 2/3] fix build errors
---
.../ComicBookInfo/ComicBookInfoProvider.cs | 28 ++++++++-------
.../Books/ComicImageProvider.cs | 34 +++++++++++++------
2 files changed, 38 insertions(+), 24 deletions(-)
diff --git a/MediaBrowser.Providers/Books/ComicBookInfo/ComicBookInfoProvider.cs b/MediaBrowser.Providers/Books/ComicBookInfo/ComicBookInfoProvider.cs
index 4fcbb3ce40..787d2ad878 100644
--- a/MediaBrowser.Providers/Books/ComicBookInfo/ComicBookInfoProvider.cs
+++ b/MediaBrowser.Providers/Books/ComicBookInfo/ComicBookInfoProvider.cs
@@ -49,24 +49,26 @@ public class ComicBookInfoProvider : IComicProvider
try
{
Stream stream = AsyncFile.OpenRead(path);
-
await using (stream.ConfigureAwait(false))
- await using (var archive = await ZipArchive.CreateAsync(stream, ZipArchiveMode.Read, false, null, cancellationToken).ConfigureAwait(false))
{
- if (archive.Comment is null)
+ var archive = await ZipArchive.CreateAsync(stream, ZipArchiveMode.Read, false, null, cancellationToken).ConfigureAwait(false);
+ await using (archive.ConfigureAwait(false))
{
- _logger.LogInformation("missing ComicBookInfo in archive comment: {Path}", info.Path);
- return new MetadataResult { HasMetadata = false };
- }
+ if (archive.Comment is null)
+ {
+ _logger.LogInformation("missing ComicBookInfo in archive comment: {Path}", info.Path);
+ return new MetadataResult { HasMetadata = false };
+ }
- var comicBookMetadata = JsonSerializer.Deserialize(archive.Comment, JsonDefaults.Options);
- if (comicBookMetadata is null)
- {
- _logger.LogError("ComicBookInfo deserialization failure: {Path}", info.Path);
- return new MetadataResult { HasMetadata = false };
- }
+ var comicBookMetadata = JsonSerializer.Deserialize(archive.Comment, JsonDefaults.Options);
+ if (comicBookMetadata is null)
+ {
+ _logger.LogError("ComicBookInfo deserialization failure: {Path}", info.Path);
+ return new MetadataResult { HasMetadata = false };
+ }
- return SaveMetadata(comicBookMetadata);
+ return SaveMetadata(comicBookMetadata);
+ }
}
}
catch (Exception ex)
diff --git a/MediaBrowser.Providers/Books/ComicImageProvider.cs b/MediaBrowser.Providers/Books/ComicImageProvider.cs
index 01ab22a520..2716d45637 100644
--- a/MediaBrowser.Providers/Books/ComicImageProvider.cs
+++ b/MediaBrowser.Providers/Books/ComicImageProvider.cs
@@ -9,6 +9,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.IO;
using Microsoft.Extensions.Logging;
using SharpCompress.Archives;
@@ -44,7 +45,7 @@ public class ComicImageProvider : IDynamicImageProvider
if (_comicBookExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{
- return LoadCover(item);
+ return LoadCoverAsync(item, cancellationToken);
}
return Task.FromResult(new DynamicImageResponse { HasImage = false });
@@ -67,7 +68,8 @@ public class ComicImageProvider : IDynamicImageProvider
/// with no image if nothing is found.
///
/// Item to check for covers.
- private async Task LoadCover(BaseItem item)
+ /// The cancellation token.
+ private async Task LoadCoverAsync(BaseItem item, CancellationToken cancellationToken)
{
var memoryStream = new MemoryStream();
@@ -75,14 +77,22 @@ public class ComicImageProvider : IDynamicImageProvider
{
ImageFormat imageFormat;
- using (Stream stream = File.OpenRead(item.Path))
- using (var archive = ArchiveFactory.Open(stream))
+ using (Stream stream = AsyncFile.OpenRead(item.Path))
{
- // throw exception to log results if no cover is found
- (var cover, imageFormat) = FindCoverEntryInArchive(archive) ?? throw new InvalidOperationException("no supported cover found");
+ var archive = await ArchiveFactory.OpenAsyncArchive(stream, cancellationToken: cancellationToken).ConfigureAwait(false);
+ await using (archive.ConfigureAwait(false))
+ {
+ // throw exception to log results if no cover is found
+ (var cover, imageFormat) = await FindCoverEntryInArchiveAsync(archive).ConfigureAwait(false)
+ ?? throw new InvalidOperationException("no supported cover found");
- // copy the cover to memory stream
- await cover.OpenEntryStream().CopyToAsync(memoryStream).ConfigureAwait(false);
+ // copy the cover to memory stream
+ var coverStream = await cover.OpenEntryStreamAsync(cancellationToken).ConfigureAwait(false);
+ await using (coverStream.ConfigureAwait(false))
+ {
+ await coverStream.CopyToAsync(memoryStream, cancellationToken).ConfigureAwait(false);
+ }
+ }
}
// reset stream position after copying
@@ -102,7 +112,7 @@ public class ComicImageProvider : IDynamicImageProvider
///
/// The archive to search.
/// The search result.
- private (IArchiveEntry CoverEntry, ImageFormat ImageFormat)? FindCoverEntryInArchive(IArchive archive)
+ private async ValueTask<(IArchiveEntry CoverEntry, ImageFormat ImageFormat)?> FindCoverEntryInArchiveAsync(IAsyncArchive archive)
{
IArchiveEntry? cover;
@@ -110,7 +120,7 @@ public class ComicImageProvider : IDynamicImageProvider
// in many cases the cover will simply be the first image in the archive
foreach (var extension in _coverExtensions)
{
- cover = archive.Entries.FirstOrDefault(e => e.Key == "cover" + extension);
+ cover = await archive.EntriesAsync.FirstOrDefaultAsync(e => e.Key == "cover" + extension).ConfigureAwait(false);
if (cover is not null)
{
@@ -120,7 +130,9 @@ public class ComicImageProvider : IDynamicImageProvider
}
}
- cover = archive.Entries.OrderBy(x => x.Key).FirstOrDefault(x => _coverExtensions.Contains(Path.GetExtension(x.Key), StringComparison.OrdinalIgnoreCase));
+ cover = await archive.EntriesAsync.OrderBy(x => x.Key)
+ .FirstOrDefaultAsync(x => _coverExtensions.Contains(Path.GetExtension(x.Key), StringComparison.OrdinalIgnoreCase))
+ .ConfigureAwait(false);
if (cover is not null)
{
From ac92da233b0896ba33ad0da8b2761236a4ce7465 Mon Sep 17 00:00:00 2001
From: Bond_009
Date: Mon, 15 Jun 2026 20:41:30 +0200
Subject: [PATCH 3/3] await instead of returning Task
---
MediaBrowser.Providers/Books/ComicImageProvider.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/MediaBrowser.Providers/Books/ComicImageProvider.cs b/MediaBrowser.Providers/Books/ComicImageProvider.cs
index 2716d45637..34936cff13 100644
--- a/MediaBrowser.Providers/Books/ComicImageProvider.cs
+++ b/MediaBrowser.Providers/Books/ComicImageProvider.cs
@@ -39,16 +39,16 @@ public class ComicImageProvider : IDynamicImageProvider
public string Name => "Comic Book Archive Cover Extractor";
///
- public Task GetImage(BaseItem item, ImageType type, CancellationToken cancellationToken)
+ public async Task GetImage(BaseItem item, ImageType type, CancellationToken cancellationToken)
{
var extension = Path.GetExtension(item.Path);
if (_comicBookExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{
- return LoadCoverAsync(item, cancellationToken);
+ return await LoadCoverAsync(item, cancellationToken).ConfigureAwait(false);
}
- return Task.FromResult(new DynamicImageResponse { HasImage = false });
+ return new DynamicImageResponse { HasImage = false };
}
///