The rerun request mapping's catch-all routed Playlist/RerunFirstRun/RerunRerun/ SearchQuery/Fake* to MediaItemId, so POST/PUT with those persisted a wrong-kind id and returned 201 instead of 422. Guard both verbs with IsSupportedSelectionType. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
77 lines
3.5 KiB
C#
77 lines
3.5 KiB
C#
using ErsatzTV.Application.MediaCollections;
|
|
using ErsatzTV.Application.MediaItems;
|
|
using ErsatzTV.Core.Domain;
|
|
|
|
namespace ErsatzTV.Controllers.Api.Requests;
|
|
|
|
// A rerun collection is a tagged union: CollectionType selects which of Collection /
|
|
// MultiCollection / SmartCollection / MediaItem is populated. The Create/Update handlers
|
|
// read ONLY the `.Id` (or `.MediaItemId`) off the chosen VM — verified in
|
|
// CreateRerunCollectionHandler.Validate / UpdateRerunCollectionHandler.ApplyUpdateRequest,
|
|
// both of which do `request.Collection?.Id`, `request.MultiCollection?.Id`,
|
|
// `request.SmartCollection?.Id`, `request.MediaItem?.MediaItemId` and nothing else. So we
|
|
// construct a minimal VM carrying just the selected id (defaults elsewhere) rather than
|
|
// doing extra lookup queries. The remaining VMs are left null (the handler expects that).
|
|
internal static class RerunCollectionRequestMapping
|
|
{
|
|
/// <summary>
|
|
/// The only <see cref="CollectionType" /> values valid as a rerun collection's selected
|
|
/// source. Excludes Playlist / RerunFirstRun / RerunRerun / SearchQuery / Fake* — those
|
|
/// are not media-item-backed collection types and must not be resolved via
|
|
/// <see cref="ResolveSelection" />. Callers (the controller) must check this first.
|
|
/// </summary>
|
|
public static bool IsSupportedSelectionType(CollectionType collectionType) =>
|
|
collectionType is CollectionType.Collection
|
|
or CollectionType.MultiCollection
|
|
or CollectionType.SmartCollection
|
|
or CollectionType.TelevisionShow
|
|
or CollectionType.TelevisionSeason
|
|
or CollectionType.Artist
|
|
or CollectionType.Movie
|
|
or CollectionType.Episode
|
|
or CollectionType.MusicVideo
|
|
or CollectionType.OtherVideo
|
|
or CollectionType.Song
|
|
or CollectionType.Image
|
|
or CollectionType.RemoteStream;
|
|
|
|
public static (MediaCollectionViewModel Collection,
|
|
MultiCollectionViewModel MultiCollection,
|
|
SmartCollectionViewModel SmartCollection,
|
|
NamedMediaItemViewModel MediaItem) ResolveSelection(CollectionType collectionType, int selectedId) =>
|
|
collectionType switch
|
|
{
|
|
CollectionType.Collection => (
|
|
new MediaCollectionViewModel(
|
|
CollectionType.Collection,
|
|
selectedId,
|
|
string.Empty,
|
|
false,
|
|
MediaItemState.Normal),
|
|
null,
|
|
null,
|
|
null),
|
|
CollectionType.MultiCollection => (
|
|
null,
|
|
new MultiCollectionViewModel(selectedId, string.Empty, [], []),
|
|
null,
|
|
null),
|
|
CollectionType.SmartCollection => (
|
|
null,
|
|
null,
|
|
new SmartCollectionViewModel(selectedId, string.Empty, string.Empty),
|
|
null),
|
|
|
|
// Any media-item-backed collection type (TelevisionShow, TelevisionSeason,
|
|
// Artist, Movie, Episode, MusicVideo, OtherVideo, Song, Image, ...) resolves to
|
|
// the MediaItem VM keyed by media item id. The caller (RerunCollectionController)
|
|
// has already validated CollectionType via IsSupportedSelectionType, so this
|
|
// catch-all only ever receives a real media-item type.
|
|
_ => (
|
|
null,
|
|
null,
|
|
null,
|
|
new NamedMediaItemViewModel(selectedId, string.Empty))
|
|
};
|
|
}
|