using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Plex; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Core.Plex; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; namespace ErsatzTV.Application.Plex; public class GetPlexConnectionParametersHandler : PlexBaseConnectionHandler, IRequestHandler> { private readonly ILogger _logger; private readonly IMediaSourceRepository _mediaSourceRepository; private readonly IMemoryCache _memoryCache; private readonly IPlexSecretStore _plexSecretStore; private readonly IPlexServerApiClient _plexServerApiClient; public GetPlexConnectionParametersHandler( IMemoryCache memoryCache, IPlexServerApiClient plexServerApiClient, IMediaSourceRepository mediaSourceRepository, IPlexSecretStore plexSecretStore, ILogger logger) : base(plexServerApiClient, mediaSourceRepository, logger) { _memoryCache = memoryCache; _plexServerApiClient = plexServerApiClient; _mediaSourceRepository = mediaSourceRepository; _plexSecretStore = plexSecretStore; _logger = logger; } public async Task> Handle( GetPlexConnectionParameters request, CancellationToken cancellationToken) { if (_memoryCache.TryGetValue(request, out PlexConnectionParametersViewModel parameters)) { return parameters; } Option maybeMediaSource = await _mediaSourceRepository.GetPlex(request.PlexMediaSourceId); foreach (PlexMediaSource mediaSource in maybeMediaSource) { Option maybeToken = await _plexSecretStore.GetServerAuthToken(mediaSource.ClientIdentifier); foreach (PlexServerAuthToken token in maybeToken) { // try to keep the same connection Option maybeActiveConnection = mediaSource.Connections.Filter(c => c.IsActive).HeadOrNone(); foreach (PlexConnection activeConnection in maybeActiveConnection) { if (await _plexServerApiClient.Ping(activeConnection, token, cancellationToken)) { _logger.LogDebug("Plex connection is still active at {Uri}", activeConnection.Uri); var p = new PlexConnectionParametersViewModel(new Uri(activeConnection.Uri), token.AuthToken); _memoryCache.Set(request, p, TimeSpan.FromSeconds(30)); return p; } } _logger.LogInformation("Plex connection is no longer active, searching for a new connection"); // check all connections for a working one Option maybeConnection = await FindConnectionToActivate(mediaSource, token); foreach (PlexConnection connection in maybeConnection) { var p = new PlexConnectionParametersViewModel(new Uri(connection.Uri), token.AuthToken); _memoryCache.Set(request, p, TimeSpan.FromMinutes(30)); return p; } return BaseError.New($"Plex media source {request.PlexMediaSourceId} requires an active connection"); } return BaseError.New($"Plex media source {request.PlexMediaSourceId} requires a token"); } return BaseError.New($"Plex media source {request.PlexMediaSourceId} does not exist."); } }