diff --git a/ErsatzTV.Core/Api/ScriptedPlayout/AddAllRequestModel.cs b/ErsatzTV.Core/Api/ScriptedPlayout/AddAllRequestModel.cs index b53662da9..9be7b0b48 100644 --- a/ErsatzTV.Core/Api/ScriptedPlayout/AddAllRequestModel.cs +++ b/ErsatzTV.Core/Api/ScriptedPlayout/AddAllRequestModel.cs @@ -1,9 +1,17 @@ +using System.ComponentModel; + namespace ErsatzTV.Core.Api.ScriptedPlayout; public record AddAllRequestModel { + [Description("The 'key' for the content that should be added")] public string Content { get; set; } + + [Description("Flags this content as filler, which influences EPG grouping")] public string FillerKind { get; set; } + + [Description("Overrides the title used in the EPG")] public string CustomTitle { get; set; } + public bool DisableWatermarks { get; set; } } diff --git a/ErsatzTV.Core/Api/ScriptedPlayout/AddCountRequestModel.cs b/ErsatzTV.Core/Api/ScriptedPlayout/AddCountRequestModel.cs index 6191ca563..b279cc590 100644 --- a/ErsatzTV.Core/Api/ScriptedPlayout/AddCountRequestModel.cs +++ b/ErsatzTV.Core/Api/ScriptedPlayout/AddCountRequestModel.cs @@ -1,10 +1,19 @@ +using System.ComponentModel; + namespace ErsatzTV.Core.Api.ScriptedPlayout; public record AddCountRequestModel { + [Description("The 'key' for the content that should be added")] public string Content { get; set; } + public int Count { get; set; } + + [Description("Flags this content as filler, which influences EPG grouping")] public string FillerKind { get; set; } + + [Description("Overrides the title used in the EPG")] public string CustomTitle { get; set; } + public bool DisableWatermarks { get; set; } } diff --git a/ErsatzTV.Core/Api/ScriptedPlayout/AddDurationRequestModel.cs b/ErsatzTV.Core/Api/ScriptedPlayout/AddDurationRequestModel.cs index 9416dec74..7b0aa438b 100644 --- a/ErsatzTV.Core/Api/ScriptedPlayout/AddDurationRequestModel.cs +++ b/ErsatzTV.Core/Api/ScriptedPlayout/AddDurationRequestModel.cs @@ -1,15 +1,38 @@ +using System.ComponentModel; + namespace ErsatzTV.Core.Api.ScriptedPlayout; public record AddDurationRequestModel { + [Description("The 'key' for the content that should be added")] public string Content { get; set; } + + [Description("The amount of time to add using the referenced content")] public string Duration { get; set; } + + [Description( + "The 'key' for the content that should be used to fill any remaining unscheduled time. One item will be selected to be looped and trimmed to exactly fit.")] public string Fallback { get; set; } + + [Description("Controls whether content will be trimmed to exactly fit the specified duration")] public bool Trim { get; set; } + + [Description( + "When trim is false, this is the number of times to discard items from the collection to find something that fits in the remaining duration")] public int DiscardAttempts { get; set; } + + [Description("When false, allows content to run over the specified duration before completing this request")] public bool StopBeforeEnd { get; set; } = true; + + [Description( + "When true, afer scheduling everything that will fit, any remaining time from the specified duration will be unscheduled (offline)")] public bool OfflineTail { get; set; } + + [Description("Flags this content as filler, which influences EPG grouping")] public string FillerKind { get; set; } + + [Description("Overrides the title used in the EPG")] public string CustomTitle { get; set; } + public bool DisableWatermarks { get; set; } } diff --git a/ErsatzTV.Core/Api/ScriptedPlayout/PadToNextRequestModel.cs b/ErsatzTV.Core/Api/ScriptedPlayout/PadToNextRequestModel.cs index 63a668534..2115ebf9f 100644 --- a/ErsatzTV.Core/Api/ScriptedPlayout/PadToNextRequestModel.cs +++ b/ErsatzTV.Core/Api/ScriptedPlayout/PadToNextRequestModel.cs @@ -1,15 +1,38 @@ +using System.ComponentModel; + namespace ErsatzTV.Core.Api.ScriptedPlayout; public record PadToNextRequestModel { + [Description("The 'key' for the content that should be added")] public string Content { get; set; } + + [Description("The minutes interval")] public int Minutes { get; set; } + + [Description( + "The 'key' for the content that should be used to fill any remaining unscheduled time. One item will be selected to be looped and trimmed to exactly fit.")] public string Fallback { get; set; } + + [Description("Controls whether content will be trimmed to exactly fit the specified interval")] public bool Trim { get; set; } + + [Description( + "When trim is false, this is the number of times to discard items from the collection to find something that fits in the remaining interval")] public int DiscardAttempts { get; set; } + + [Description("When false, allows content to run over the specified interval before completing this request")] public bool StopBeforeEnd { get; set; } = true; + + [Description( + "When true, afer scheduling everything that will fit, any remaining time from the specified interval will be unscheduled (offline)")] public bool OfflineTail { get; set; } = true; + + [Description("Flags this content as filler, which influences EPG grouping")] public string FillerKind { get; set; } + + [Description("Overrides the title used in the EPG")] public string CustomTitle { get; set; } + public bool DisableWatermarks { get; set; } } diff --git a/ErsatzTV.Core/Api/ScriptedPlayout/PadUntilRequestModel.cs b/ErsatzTV.Core/Api/ScriptedPlayout/PadUntilRequestModel.cs index 7405d8a10..f9643c863 100644 --- a/ErsatzTV.Core/Api/ScriptedPlayout/PadUntilRequestModel.cs +++ b/ErsatzTV.Core/Api/ScriptedPlayout/PadUntilRequestModel.cs @@ -1,16 +1,43 @@ +using System.ComponentModel; + namespace ErsatzTV.Core.Api.ScriptedPlayout; public record PadUntilRequestModel { + [Description("The 'key' for the content that should be added")] public string Content { get; set; } + + [Description("The time of day that content should be added until")] public string When { get; set; } + + [Description( + "Only used when the current playout time is already after the specified pad until time. When true, content will be scheduled until the specified time of day (the next day). When false, no content will be scheduled by this request.")] public bool Tomorrow { get; set; } + + [Description( + "The 'key' for the content that should be used to fill any remaining unscheduled time. One item will be selected to be looped and trimmed to exactly fit.")] public string Fallback { get; set; } + + [Description("Controls whether content will be trimmed to exactly fit until the specified time")] public bool Trim { get; set; } + + [Description( + "When trim is false, this is the number of times to discard items from the collection to find something that fits until the specified time")] public int DiscardAttempts { get; set; } + + [Description( + "When false, allows content to run over the specified the specified time before completing this request")] public bool StopBeforeEnd { get; set; } = true; + + [Description( + "When true, afer scheduling everything that will fit, any remaining time from the specified interval will be unscheduled (offline)")] public bool OfflineTail { get; set; } + + [Description("Flags this content as filler, which influences EPG grouping")] public string FillerKind { get; set; } + + [Description("Overrides the title used in the EPG")] public string CustomTitle { get; set; } + public bool DisableWatermarks { get; set; } } diff --git a/ErsatzTV/Controllers/Api/ScriptedScheduleController.cs b/ErsatzTV/Controllers/Api/ScriptedScheduleController.cs index 874fe26b9..d91bc8991 100644 --- a/ErsatzTV/Controllers/Api/ScriptedScheduleController.cs +++ b/ErsatzTV/Controllers/Api/ScriptedScheduleController.cs @@ -13,6 +13,8 @@ namespace ErsatzTV.Controllers.Api; public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedPlayoutBuilderService) : ControllerBase { [HttpGet("context", Name = "GetContext")] + [Tags("Metadata")] + [EndpointSummary("Get the current context")] public ActionResult GetContext([FromRoute] Guid buildId) { ISchedulingEngine engine = scriptedPlayoutBuilderService.GetEngine(buildId); @@ -25,6 +27,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("add_collection", Name = "AddCollection")] + [Tags("Content")] + [EndpointSummary("Add a collection")] public async Task AddCollection( [FromRoute] Guid buildId, @@ -48,6 +52,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("add_marathon", Name = "AddMarathon")] + [Tags("Content")] + [EndpointSummary("Add a marathon")] public async Task AddMarathon([FromRoute] Guid buildId, [FromBody] AddMarathonRequestModel request) { ISchedulingEngine engine = scriptedPlayoutBuilderService.GetEngine(buildId); @@ -73,6 +79,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("add_multi_collection", Name = "AddMultiCollection")] + [Tags("Content")] + [EndpointSummary("Add a multi-collection")] public async Task AddMultiCollection( [FromRoute] Guid buildId, @@ -96,6 +104,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("add_playlist", Name = "AddPlaylist")] + [Tags("Content")] + [EndpointSummary("Add a playlist")] public async Task AddPlaylist( [FromRoute] Guid buildId, @@ -114,6 +124,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("add_smart_collection", Name = "AddSmartCollection")] + [Tags("Content")] + [EndpointSummary("Add a smart collection")] public async Task AddSmartCollection( [FromRoute] Guid buildId, @@ -137,6 +149,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("add_show", Name = "AddShow")] + [Tags("Content")] + [EndpointSummary("Add a show")] public async Task AddShow( [FromRoute] Guid buildId, @@ -160,6 +174,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("add_all", Name = "AddAll")] + [Tags("Scheduling")] + [EndpointSummary("Add all content")] public ActionResult AddAll([FromRoute] Guid buildId, [FromBody] AddAllRequestModel request) { ISchedulingEngine engine = scriptedPlayoutBuilderService.GetEngine(buildId); @@ -179,6 +195,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("add_count", Name = "AddCount")] + [Tags("Scheduling")] + [EndpointSummary("Add a specific number of content items")] public ActionResult AddCount( [FromRoute] Guid buildId, @@ -207,6 +225,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("add_duration", Name = "AddDuration")] + [Tags("Scheduling")] + [EndpointSummary("Add content for a specific duration")] public ActionResult AddDuration( [FromRoute] Guid buildId, @@ -240,6 +260,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("pad_to_next", Name = "PadToNext")] + [Tags("Scheduling")] + [EndpointSummary("Add content until a specific minutes interval")] public ActionResult PadToNext( [FromRoute] Guid buildId, [FromBody] PadToNextRequestModel request) @@ -271,6 +293,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("pad_until", Name = "PadUntil")] + [Tags("Scheduling")] + [EndpointSummary("Add content until a specified time")] public ActionResult PadUntil( [FromRoute] Guid buildId, [FromBody] PadUntilRequestModel request) @@ -303,6 +327,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("start_epg_group", Name = "StartEpgGroup")] + [Tags("Control")] + [EndpointSummary("Start a new EPG group")] public IActionResult StartEpgGroup([FromRoute] Guid buildId, [FromBody] StartEpgGroupRequestModel request) { ISchedulingEngine engine = scriptedPlayoutBuilderService.GetEngine(buildId); @@ -316,6 +342,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("stop_epg_group", Name = "StopEpgGroup")] + [Tags("Control")] + [EndpointSummary("Finish the current EPG group")] public IActionResult StopEpgGroup([FromRoute] Guid buildId) { ISchedulingEngine engine = scriptedPlayoutBuilderService.GetEngine(buildId); @@ -329,6 +357,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("graphics_on", Name = "GraphicsOn")] + [Tags("Control")] + [EndpointSummary("Turn on graphics elements")] public async Task GraphicsOn( [FromRoute] Guid buildId, @@ -347,6 +377,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("graphics_off", Name = "GraphicsOff")] + [Tags("Control")] + [EndpointSummary("Turn off graphics elements")] public async Task GraphicsOff( [FromRoute] Guid buildId, @@ -365,6 +397,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("watermark_on", Name = "WatermarkOn")] + [Tags("Control")] + [EndpointSummary("Turn on watermarks")] public async Task WatermarkOn([FromRoute] Guid buildId, [FromBody] WatermarkOnRequestModel request) { ISchedulingEngine engine = scriptedPlayoutBuilderService.GetEngine(buildId); @@ -378,6 +412,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("watermark_off", Name = "WatermarkOff")] + [Tags("Control")] + [EndpointSummary("Turn off watermarks")] public async Task WatermarkOff([FromRoute] Guid buildId, [FromBody] WatermarkOffRequestModel request) { ISchedulingEngine engine = scriptedPlayoutBuilderService.GetEngine(buildId); @@ -391,6 +427,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("skip_items", Name = "SkipItems")] + [Tags("Control")] + [EndpointSummary("Skip a specific number of items")] public IActionResult SkipItems([FromRoute] Guid buildId, [FromBody] SkipItemsRequestModel request) { ISchedulingEngine engine = scriptedPlayoutBuilderService.GetEngine(buildId); @@ -404,6 +442,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("skip_to_item", Name = "SkipToItem")] + [Tags("Control")] + [EndpointSummary("Skip to a specific episode")] public IActionResult SkipToItem([FromRoute] Guid buildId, [FromBody] SkipToItemRequestModel request) { ISchedulingEngine engine = scriptedPlayoutBuilderService.GetEngine(buildId); @@ -417,6 +457,8 @@ public class ScriptedScheduleController(IScriptedPlayoutBuilderService scriptedP } [HttpPost("wait_until", Name = "WaitUntil")] + [Tags("Control")] + [EndpointSummary("Wait until the specified time")] public ActionResult WaitUntil( [FromRoute] Guid buildId, diff --git a/ErsatzTV/Startup.cs b/ErsatzTV/Startup.cs index 60fa56c12..b43c34abf 100644 --- a/ErsatzTV/Startup.cs +++ b/ErsatzTV/Startup.cs @@ -599,7 +599,11 @@ public class Startup endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); endpoints.MapOpenApi().CacheOutput(); - endpoints.MapScalarApiReference(); + endpoints.MapScalarApiReference(options => + { + options.AddDocument("scripted-schedule", "Scripted Schedule", "openapi/scripted-schedule.json"); + options.HideClientButton = true; + }); }); });