102 lines
3.8 KiB
C#
102 lines
3.8 KiB
C#
using ErsatzTV.Application.Artworks;
|
|
using ErsatzTV.Application.MediaCollections;
|
|
using ErsatzTV.Core;
|
|
using ErsatzTV.Core.Api.Channels;
|
|
using ErsatzTV.Core.Api.LibraryBrowse;
|
|
using ErsatzTV.Core.Domain;
|
|
using LanguageExt;
|
|
using MediatR;
|
|
|
|
namespace ErsatzTV.Application.Channels;
|
|
|
|
public class CreateAutoTunedChannelsHandler(ISender mediator)
|
|
: IRequestHandler<CreateAutoTunedChannels, AutoTuneResult>
|
|
{
|
|
private const string NumberTakenError = "Channel number must be unique";
|
|
private const string DefaultGroup = "Auto-Tuned";
|
|
|
|
public async Task<AutoTuneResult> Handle(
|
|
CreateAutoTunedChannels request,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
string group = string.IsNullOrWhiteSpace(request.Group) ? DefaultGroup : request.Group.Trim();
|
|
var outcomes = new List<AutoTuneChannelOutcome>();
|
|
|
|
foreach (AutoTuneChannelSelection selection in request.Channels ?? [])
|
|
{
|
|
outcomes.Add(await CreateOne(request.TemplateId, group, selection, cancellationToken));
|
|
}
|
|
|
|
return new AutoTuneResult(outcomes);
|
|
}
|
|
|
|
private async Task<AutoTuneChannelOutcome> CreateOne(
|
|
int templateId,
|
|
string group,
|
|
AutoTuneChannelSelection selection,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
string name = (selection.Name ?? string.Empty).Trim();
|
|
if (name.Length is 0 or > 50)
|
|
{
|
|
return new AutoTuneChannelOutcome(name, AutoTuneOutcomeStatus.Failed, null, "Invalid channel name");
|
|
}
|
|
|
|
string query = AutoTuneAxisMap.GenerateQuery(selection.Axis, selection.Value);
|
|
PlaybackOrder order = AutoTuneAxisMap.PlaybackOrderFor(selection.Axis);
|
|
|
|
// 1. Create the smart collection that drives this channel.
|
|
Either<BaseError, SmartCollectionViewModel> scResult =
|
|
await mediator.Send(new CreateSmartCollection(query, name), cancellationToken);
|
|
|
|
SmartCollectionViewModel smartCollection = null;
|
|
foreach (BaseError error in scResult.LeftToSeq())
|
|
{
|
|
return new AutoTuneChannelOutcome(
|
|
name, AutoTuneOutcomeStatus.Failed, null, $"Smart collection: {error.Value}");
|
|
}
|
|
|
|
foreach (SmartCollectionViewModel vm in scResult.RightToSeq())
|
|
{
|
|
smartCollection = vm;
|
|
}
|
|
|
|
// 2. Create the channel from a single-item lineup referencing the smart collection.
|
|
var command = new CreateChannelFromLineup(
|
|
name,
|
|
selection.Number,
|
|
group,
|
|
string.Empty,
|
|
ArtworkContentTypeModel.None,
|
|
IsEnabled: true,
|
|
ShowInEpg: true,
|
|
templateId,
|
|
new CreateChannelFromLineupAdvancedOptions(PlaybackOrder: order),
|
|
[
|
|
new CreateChannelFromLineupItem(
|
|
LibraryBrowseMediaType.SmartCollection,
|
|
CollectionType.SmartCollection,
|
|
CollectionId: null,
|
|
MultiCollectionId: null,
|
|
SmartCollectionId: smartCollection.Id,
|
|
RerunCollectionId: null,
|
|
MediaItemId: null,
|
|
PlaylistId: null)
|
|
]);
|
|
|
|
Either<BaseError, CreateChannelFromLineupResponseModel> channelResult =
|
|
await mediator.Send(command, cancellationToken);
|
|
|
|
foreach (BaseError error in channelResult.LeftToSeq())
|
|
{
|
|
AutoTuneOutcomeStatus status = error.Value.Contains(NumberTakenError, StringComparison.Ordinal)
|
|
? AutoTuneOutcomeStatus.Skipped
|
|
: AutoTuneOutcomeStatus.Failed;
|
|
return new AutoTuneChannelOutcome(name, status, null, error.Value);
|
|
}
|
|
|
|
int channelId = channelResult.Match(Left: _ => 0, Right: r => r.ChannelId);
|
|
return new AutoTuneChannelOutcome(name, AutoTuneOutcomeStatus.Created, channelId, null);
|
|
}
|
|
}
|