dependencies and code cleanup (#2117)
* fix validation in new form layout * pin mediatr to last oss version * update dependencies * cleanup code in core * cleanup code in ffmpeg * cleanup code in infra * cleanup code in scanner * cleanup code in application * cleanup main code * cleanup test code * solution-wide code cleanup
This commit is contained in:
@@ -8,10 +8,8 @@ namespace ErsatzTV.Controllers.Api;
|
||||
public class LibrariesController(IMediator mediator)
|
||||
{
|
||||
[HttpPost("/api/libraries/{id:int}/scan")]
|
||||
public async Task<IActionResult> ResetPlayout(int id)
|
||||
{
|
||||
return await mediator.Send(new QueueLibraryScanByLibraryId(id))
|
||||
public async Task<IActionResult> ResetPlayout(int id) =>
|
||||
await mediator.Send(new QueueLibraryScanByLibraryId(id))
|
||||
? new OkResult()
|
||||
: new NotFoundResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ namespace ErsatzTV.Controllers;
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public class ArtworkController : ControllerBase
|
||||
{
|
||||
private readonly IChannelLogoGenerator _channelLogoGenerator;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IMediator _mediator;
|
||||
private readonly IChannelLogoGenerator _channelLogoGenerator;
|
||||
|
||||
public ArtworkController(
|
||||
IMediator mediator,
|
||||
@@ -37,22 +37,23 @@ public class ArtworkController : ControllerBase
|
||||
[HttpHead("/artwork/{id}")]
|
||||
[HttpGet("/artwork/{id}")]
|
||||
// This route redirect to the proper artwork from its Id
|
||||
public async Task<IActionResult> RedirectArtwork(int id, CancellationToken cancellationToken) {
|
||||
public async Task<IActionResult> RedirectArtwork(int id, CancellationToken cancellationToken)
|
||||
{
|
||||
Either<BaseError, Artwork> artwork =
|
||||
await _mediator.Send(new GetArtwork(id), cancellationToken);
|
||||
|
||||
return artwork.Match<IActionResult>(
|
||||
Left: _ => new NotFoundResult(),
|
||||
Right: r => r.ArtworkKind switch
|
||||
{
|
||||
ArtworkKind.Poster => new RedirectResult("/artwork/posters/" + r.Path),
|
||||
ArtworkKind.Thumbnail => new RedirectResult("/artwork/thumbnails/" + r.Path),
|
||||
ArtworkKind.Logo => new RedirectResult("/iptv/logos/" + r.Path),
|
||||
ArtworkKind.FanArt => new RedirectResult("/artwork/fanart/" + r.Path),
|
||||
ArtworkKind.Watermark => new RedirectResult("/artwork/watermarks/" + r.Path),
|
||||
_ => new NotFoundResult()
|
||||
}
|
||||
);
|
||||
{
|
||||
ArtworkKind.Poster => new RedirectResult("/artwork/posters/" + r.Path),
|
||||
ArtworkKind.Thumbnail => new RedirectResult("/artwork/thumbnails/" + r.Path),
|
||||
ArtworkKind.Logo => new RedirectResult("/iptv/logos/" + r.Path),
|
||||
ArtworkKind.FanArt => new RedirectResult("/artwork/fanart/" + r.Path),
|
||||
ArtworkKind.Watermark => new RedirectResult("/artwork/watermarks/" + r.Path),
|
||||
_ => new NotFoundResult()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
[HttpHead("/iptv/artwork/posters/{fileName}")]
|
||||
@@ -63,17 +64,25 @@ public class ArtworkController : ControllerBase
|
||||
public async Task<IActionResult> GetPoster(string fileName, CancellationToken cancellationToken)
|
||||
{
|
||||
Either<BaseError, CachedImagePathViewModel> cachedImagePath =
|
||||
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.Poster, string.Empty, 440), cancellationToken);
|
||||
await _mediator.Send(
|
||||
new GetCachedImagePath(fileName, ArtworkKind.Poster, string.Empty, 440),
|
||||
cancellationToken);
|
||||
return cachedImagePath.Match<IActionResult>(
|
||||
Left: _ => new NotFoundResult(),
|
||||
Right: r => new PhysicalFileResult(r.FileName, r.MimeType));
|
||||
}
|
||||
|
||||
[HttpGet("/artwork/watermarks/{fileName}")]
|
||||
public async Task<IActionResult> GetWatermark(string fileName, [FromQuery] string contentType, CancellationToken cancellationToken)
|
||||
public async Task<IActionResult> GetWatermark(
|
||||
string fileName,
|
||||
[FromQuery]
|
||||
string contentType,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
Either<BaseError, CachedImagePathViewModel> cachedImagePath =
|
||||
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.Watermark, contentType), cancellationToken);
|
||||
await _mediator.Send(
|
||||
new GetCachedImagePath(fileName, ArtworkKind.Watermark, contentType),
|
||||
cancellationToken);
|
||||
return cachedImagePath.Match<IActionResult>(
|
||||
Left: _ => new NotFoundResult(),
|
||||
Right: r => new PhysicalFileResult(r.FileName, r.MimeType));
|
||||
@@ -155,7 +164,9 @@ public class ArtworkController : ControllerBase
|
||||
public async Task<IActionResult> GetThumbnail(string fileName, CancellationToken cancellationToken)
|
||||
{
|
||||
Either<BaseError, CachedImagePathViewModel> cachedImagePath =
|
||||
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.Thumbnail, string.Empty, 220), cancellationToken);
|
||||
await _mediator.Send(
|
||||
new GetCachedImagePath(fileName, ArtworkKind.Thumbnail, string.Empty, 220),
|
||||
cancellationToken);
|
||||
return cachedImagePath.Match<IActionResult>(
|
||||
Left: _ => new NotFoundResult(),
|
||||
Right: r => new PhysicalFileResult(r.FileName, r.MimeType));
|
||||
@@ -263,8 +274,8 @@ public class ArtworkController : ControllerBase
|
||||
|
||||
[HttpGet(ChannelLogoGenerator.GetRoute)]
|
||||
public IActionResult GenerateChannelLogo(
|
||||
string text, // param name = ChannelLogoGenerator.GetRouteQueryParamName
|
||||
CancellationToken cancellationToken) =>
|
||||
string text, // param name = ChannelLogoGenerator.GetRouteQueryParamName
|
||||
CancellationToken cancellationToken) =>
|
||||
_channelLogoGenerator
|
||||
.GenerateChannelLogo(text, 100, 200, cancellationToken).Match<IActionResult>(
|
||||
Left: _ => new RedirectResult("/iptv/images/ersatztv-500.png"),
|
||||
|
||||
@@ -84,7 +84,9 @@ public class IptvController : ControllerBase
|
||||
string mode = null)
|
||||
{
|
||||
Option<ChannelViewModel> maybeChannel = await _mediator.Send(new GetChannelByNumber(channelNumber));
|
||||
if (maybeChannel.IsNone || await maybeChannel.Map(c => c.ActiveMode).IfNoneAsync(ChannelActiveMode.Inactive) is ChannelActiveMode.Inactive)
|
||||
if (maybeChannel.IsNone ||
|
||||
await maybeChannel.Map(c => c.ActiveMode).IfNoneAsync(ChannelActiveMode.Inactive) is ChannelActiveMode
|
||||
.Inactive)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
@@ -119,37 +121,36 @@ public class IptvController : ControllerBase
|
||||
};
|
||||
|
||||
return await _mediator.Send(request)
|
||||
.Map(
|
||||
result => result.Match<IActionResult>(
|
||||
processModel =>
|
||||
.Map(result => result.Match<IActionResult>(
|
||||
processModel =>
|
||||
{
|
||||
Command command = processModel.Process;
|
||||
|
||||
_logger.LogInformation("Starting ts stream for channel {ChannelNumber}", channelNumber);
|
||||
_logger.LogDebug("ffmpeg arguments {FFmpegArguments}", command.Arguments);
|
||||
var process = new FFmpegProcess
|
||||
{
|
||||
Command command = processModel.Process;
|
||||
|
||||
_logger.LogInformation("Starting ts stream for channel {ChannelNumber}", channelNumber);
|
||||
_logger.LogDebug("ffmpeg arguments {FFmpegArguments}", command.Arguments);
|
||||
var process = new FFmpegProcess
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = command.TargetFilePath,
|
||||
Arguments = command.Arguments,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = false,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
HttpContext.Response.RegisterForDispose(process);
|
||||
|
||||
foreach ((string key, string value) in command.EnvironmentVariables)
|
||||
{
|
||||
process.StartInfo.Environment[key] = value;
|
||||
FileName = command.TargetFilePath,
|
||||
Arguments = command.Arguments,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = false,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
HttpContext.Response.RegisterForDispose(process);
|
||||
|
||||
process.Start();
|
||||
return new FileStreamResult(process.StandardOutput.BaseStream, "video/mp2t");
|
||||
},
|
||||
error => BadRequest(error.Value)));
|
||||
foreach ((string key, string value) in command.EnvironmentVariables)
|
||||
{
|
||||
process.StartInfo.Environment[key] = value;
|
||||
}
|
||||
|
||||
process.Start();
|
||||
return new FileStreamResult(process.StandardOutput.BaseStream, "video/mp2t");
|
||||
},
|
||||
error => BadRequest(error.Value)));
|
||||
}
|
||||
|
||||
[HttpHead("iptv/session/{channelNumber}/hls.m3u8")]
|
||||
@@ -174,7 +175,9 @@ public class IptvController : ControllerBase
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
_logger.LogWarning("Unable to locate session worker for channel {Channel}; will redirect to start session", channelNumber);
|
||||
_logger.LogWarning(
|
||||
"Unable to locate session worker for channel {Channel}; will redirect to start session",
|
||||
channelNumber);
|
||||
return RedirectToAction(nameof(GetHttpLiveStreamingVideo), new { channelNumber });
|
||||
}
|
||||
|
||||
@@ -186,7 +189,9 @@ public class IptvController : ControllerBase
|
||||
string mode = "mixed")
|
||||
{
|
||||
Option<ChannelViewModel> maybeChannel = await _mediator.Send(new GetChannelByNumber(channelNumber));
|
||||
if (maybeChannel.IsNone || await maybeChannel.Map(c => c.ActiveMode).IfNoneAsync(ChannelActiveMode.Inactive) is ChannelActiveMode.Inactive)
|
||||
if (maybeChannel.IsNone ||
|
||||
await maybeChannel.Map(c => c.ActiveMode).IfNoneAsync(ChannelActiveMode.Inactive) is ChannelActiveMode
|
||||
.Inactive)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
@@ -260,10 +265,9 @@ public class IptvController : ControllerBase
|
||||
Request.Host.ToString(),
|
||||
channelNumber,
|
||||
mode))
|
||||
.Map(
|
||||
r => r.Match<IActionResult>(
|
||||
playlist => Content(playlist, "application/vnd.apple.mpegurl"),
|
||||
error => BadRequest(error.Value)));
|
||||
.Map(r => r.Match<IActionResult>(
|
||||
playlist => Content(playlist, "application/vnd.apple.mpegurl"),
|
||||
error => BadRequest(error.Value)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,9 +316,10 @@ public class IptvController : ControllerBase
|
||||
"Failed to return ffmpeg multi-variant playlist; falling back to generated playlist");
|
||||
}
|
||||
|
||||
Option<ResolutionAndBitrateViewModel> maybeResolutionAndBitrate = await _mediator.Send(new GetChannelResolutionAndBitrate(channelNumber));
|
||||
Option<ResolutionAndBitrateViewModel> maybeResolutionAndBitrate =
|
||||
await _mediator.Send(new GetChannelResolutionAndBitrate(channelNumber));
|
||||
string resolution = string.Empty;
|
||||
string bitrate = "10000000";
|
||||
var bitrate = "10000000";
|
||||
foreach (ResolutionAndBitrateViewModel res in maybeResolutionAndBitrate)
|
||||
{
|
||||
resolution = $",RESOLUTION={res.Width}x{res.Height}";
|
||||
|
||||
Reference in New Issue
Block a user