using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Plugin.WatchedTogether.Services;
///
/// Keeps group membership consistent with the set of users that actually exist.
///
///
/// Jellyfin raises no user-deleted event that carries the removed id, so instead of subscribing to
/// deletions this reconciles configuration against live users at startup. Stale entries are also
/// skipped at read time by , so this is about keeping
/// stored configuration tidy and disabling groups that have fallen below two members.
///
public sealed class UserLifecycleService : IHostedService
{
private readonly IUserManager _userManager;
private readonly IGroupService _groupService;
private readonly ILogger _logger;
///
/// Initializes a new instance of the class.
///
/// The user manager.
/// The group service.
/// The logger.
public UserLifecycleService(
IUserManager userManager,
IGroupService groupService,
ILogger logger)
{
_userManager = userManager;
_groupService = groupService;
_logger = logger;
}
///
public Task StartAsync(CancellationToken cancellationToken)
{
try
{
Reconcile();
}
#pragma warning disable CA1031 // Reconciliation must never prevent the server from starting.
catch (Exception ex)
#pragma warning restore CA1031
{
_logger.LogError(ex, "Failed to reconcile Watched Together groups at startup");
}
return Task.CompletedTask;
}
///
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
///
/// Removes references to users that no longer exist.
///
private void Reconcile()
{
var config = Plugin.Instance?.Configuration;
if (config is null || config.Groups.Count == 0)
{
return;
}
var liveIds = _userManager.UsersIds.ToHashSet();
var referenced = config.Groups
.SelectMany(g => g.MemberUserIds.Append(g.SharedUserId))
.Distinct()
.ToList();
foreach (var id in referenced.Where(id => !liveIds.Contains(id)))
{
_logger.LogInformation("Pruning deleted user {UserId} from Watched Together groups", id);
_groupService.PruneDeletedUser(id);
}
}
}