Files
jellyfin-plugin-recently-ad…/Jellyfin.Plugin.RecentlyAddedGuard/Services/LibraryItemDateWriter.cs
T
Jonas MenzelandClaude Opus 5.5 d431486095
build / build (push) Successful in 1m10s
release / release (push) Failing after 1m36s
feat: Recently Added Guard plugin for Jellyfin 12.2
Keeps Radarr/Sonarr quality upgrades out of "Recently Added" by keeping
a ledger of the first date added per logical medium (movie or episode,
identified by provider ids and the series) and restoring it on upgrades.

- core logic without Jellyfin types (Reconciler, MediaKeys, GuardProcessor)
- thread-safe ledger with atomic, debounced persistence
- event processing via channel and background worker, seed on first start
- scheduled task "Ledger synchronisieren", status API, configuration page
- xUnit tests and a Jellyfin 12.2 integration test
- Gitea workflows: build/test, release with jprm and manifest branch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 23:10:02 +02:00

60 lines
2.0 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Plugin.RecentlyAddedGuard.Core;
using MediaBrowser.Controller.Library;
namespace Jellyfin.Plugin.RecentlyAddedGuard.Services;
/// <summary>
/// Writes "date added" through the library manager and remembers which items it is currently saving,
/// so the resulting <c>ItemUpdated</c> events can be ignored.
/// </summary>
public sealed class LibraryItemDateWriter : IItemDateWriter
{
private readonly ILibraryManager _libraryManager;
private readonly ConcurrentDictionary<Guid, byte> _inFlight = new();
/// <summary>
/// Initializes a new instance of the <see cref="LibraryItemDateWriter"/> class.
/// </summary>
/// <param name="libraryManager">The library manager.</param>
public LibraryItemDateWriter(ILibraryManager libraryManager)
{
_libraryManager = libraryManager;
}
/// <summary>
/// Checks whether the item is being saved by this writer right now.
/// </summary>
/// <param name="itemId">The item.</param>
/// <returns><c>true</c> while a correction of the item is in progress.</returns>
public bool IsWriting(Guid itemId) => _inFlight.ContainsKey(itemId);
/// <inheritdoc />
public async Task<bool> TrySetDateCreatedAsync(Guid itemId, DateTime dateCreated, CancellationToken cancellationToken)
{
var item = _libraryManager.GetItemById(itemId);
if (item is null)
{
return false;
}
_inFlight.TryAdd(itemId, 0);
try
{
item.DateCreated = dateCreated;
// MetadataEdit also lets the NFO saver (if enabled) write the restored <dateadded>.
await _libraryManager.UpdateItemAsync(item, item.GetParent(), ItemUpdateType.MetadataEdit, cancellationToken)
.ConfigureAwait(false);
return true;
}
finally
{
_inFlight.TryRemove(itemId, out _);
}
}
}