Stream custom live channels using your own media
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
3.8 KiB

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<GetPlexConnectionParameters,
Either<BaseError, PlexConnectionParametersViewModel>>
{
private readonly ILogger<GetPlexConnectionParametersHandler> _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<GetPlexConnectionParametersHandler> logger)
: base(plexServerApiClient, mediaSourceRepository, logger)
{
_memoryCache = memoryCache;
_plexServerApiClient = plexServerApiClient;
_mediaSourceRepository = mediaSourceRepository;
_plexSecretStore = plexSecretStore;
_logger = logger;
}
public async Task<Either<BaseError, PlexConnectionParametersViewModel>> Handle(
GetPlexConnectionParameters request,
CancellationToken cancellationToken)
{
if (_memoryCache.TryGetValue(request, out PlexConnectionParametersViewModel parameters))
{
return parameters;
}
Option<PlexMediaSource> maybeMediaSource = await _mediaSourceRepository.GetPlex(request.PlexMediaSourceId);
foreach (PlexMediaSource mediaSource in maybeMediaSource)
{
Option<PlexServerAuthToken> maybeToken =
await _plexSecretStore.GetServerAuthToken(mediaSource.ClientIdentifier);
foreach (PlexServerAuthToken token in maybeToken)
{
// try to keep the same connection
Option<PlexConnection> 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<PlexConnection> 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.");
}
}