diff options
| author | Joshua M. Boniface <joshua@boniface.me> | 2025-08-03 17:27:17 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-03 17:27:17 -0400 |
| commit | 4b6fb6c4bb2478badad068ce18aabe0c2955db48 (patch) | |
| tree | 15f986ee62327cceb8f5c8f009bcf08d10cfaa66 /Jellyfin.Server/Filters/AdditionalModelFilter.cs | |
| parent | e7bc86ebb8496615e0b3f73eb4f13ab4c0913dc8 (diff) | |
| parent | db7465e83d9cc07134a0bffad7ed17b1c7b873da (diff) | |
Merge branch 'master' into master
Diffstat (limited to 'Jellyfin.Server/Filters/AdditionalModelFilter.cs')
| -rw-r--r-- | Jellyfin.Server/Filters/AdditionalModelFilter.cs | 107 |
1 files changed, 73 insertions, 34 deletions
diff --git a/Jellyfin.Server/Filters/AdditionalModelFilter.cs b/Jellyfin.Server/Filters/AdditionalModelFilter.cs index bf38f741c..421eeecda 100644 --- a/Jellyfin.Server/Filters/AdditionalModelFilter.cs +++ b/Jellyfin.Server/Filters/AdditionalModelFilter.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Server.Filters public class AdditionalModelFilter : IDocumentFilter { // Array of options that should not be visible in the api spec. - private static readonly Type[] _ignoredConfigurations = { typeof(MigrationOptions) }; + private static readonly Type[] _ignoredConfigurations = { typeof(MigrationOptions), typeof(MediaBrowser.Model.Branding.BrandingOptions) }; private readonly IServerConfigurationManager _serverConfigurationManager; /// <summary> @@ -92,17 +92,51 @@ namespace Jellyfin.Server.Filters continue; } - // Additional discriminator needed for GroupUpdate models... - if (messageType == SessionMessageType.SyncPlayGroupUpdate && type != typeof(SyncPlayGroupUpdateCommandMessage)) - { - continue; - } - var schema = context.SchemaGenerator.GenerateSchema(type, context.SchemaRepository); outboundWebSocketSchemas.Add(schema); outboundWebSocketDiscriminators.Add(messageType.ToString()!, schema.Reference.ReferenceV3); } + // Add custom "SyncPlayGroupUpdateMessage" schema because Swashbuckle cannot generate it for us + var syncPlayGroupUpdateMessageSchema = new OpenApiSchema + { + Type = "object", + Description = "Untyped sync play command.", + Properties = new Dictionary<string, OpenApiSchema> + { + { + "Data", new OpenApiSchema + { + AllOf = + [ + new OpenApiSchema { Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = nameof(GroupUpdate<object>) } } + ], + Description = "Group update data", + Nullable = false, + } + }, + { "MessageId", new OpenApiSchema { Type = "string", Format = "uuid", Description = "Gets or sets the message id." } }, + { + "MessageType", new OpenApiSchema + { + Enum = Enum.GetValues<SessionMessageType>().Select(type => new OpenApiString(type.ToString())).ToList<IOpenApiAny>(), + AllOf = + [ + new OpenApiSchema { Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = nameof(SessionMessageType) } } + ], + Description = "The different kinds of messages that are used in the WebSocket api.", + Default = new OpenApiString(nameof(SessionMessageType.SyncPlayGroupUpdate)), + ReadOnly = true + } + }, + }, + AdditionalPropertiesAllowed = false, + Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "SyncPlayGroupUpdateMessage" } + }; + context.SchemaRepository.AddDefinition("SyncPlayGroupUpdateMessage", syncPlayGroupUpdateMessageSchema); + outboundWebSocketSchemas.Add(syncPlayGroupUpdateMessageSchema); + outboundWebSocketDiscriminators[nameof(SessionMessageType.SyncPlayGroupUpdate)] = syncPlayGroupUpdateMessageSchema.Reference.ReferenceV3; + var outboundWebSocketMessageSchema = new OpenApiSchema { Type = "object", @@ -140,41 +174,46 @@ namespace Jellyfin.Server.Filters }); // Manually generate sync play GroupUpdate messages. - if (!context.SchemaRepository.Schemas.TryGetValue(nameof(GroupUpdate), out var groupUpdateSchema)) - { - groupUpdateSchema = context.SchemaGenerator.GenerateSchema(typeof(GroupUpdate), context.SchemaRepository); - } - - var groupUpdateOfGroupInfoSchema = context.SchemaGenerator.GenerateSchema(typeof(GroupUpdate<GroupInfoDto>), context.SchemaRepository); - var groupUpdateOfGroupStateSchema = context.SchemaGenerator.GenerateSchema(typeof(GroupUpdate<GroupStateUpdate>), context.SchemaRepository); - var groupUpdateOfStringSchema = context.SchemaGenerator.GenerateSchema(typeof(GroupUpdate<string>), context.SchemaRepository); - var groupUpdateOfPlayQueueSchema = context.SchemaGenerator.GenerateSchema(typeof(GroupUpdate<PlayQueueUpdate>), context.SchemaRepository); + var groupUpdateTypes = typeof(GroupUpdate<>).Assembly.GetTypes() + .Where(t => t.BaseType != null + && t.BaseType.IsGenericType + && t.BaseType.GetGenericTypeDefinition() == typeof(GroupUpdate<>)) + .ToList(); - groupUpdateSchema.OneOf = new List<OpenApiSchema> + var groupUpdateSchemas = new List<OpenApiSchema>(); + var groupUpdateDiscriminators = new Dictionary<string, string>(); + foreach (var type in groupUpdateTypes) { - groupUpdateOfGroupInfoSchema, - groupUpdateOfGroupStateSchema, - groupUpdateOfStringSchema, - groupUpdateOfPlayQueueSchema - }; + var groupUpdateType = (GroupUpdateType?)type.GetProperty(nameof(GroupUpdate<object>.Type))?.GetCustomAttribute<DefaultValueAttribute>()?.Value; + if (groupUpdateType is null) + { + continue; + } + + var schema = context.SchemaGenerator.GenerateSchema(type, context.SchemaRepository); + groupUpdateSchemas.Add(schema); + groupUpdateDiscriminators[groupUpdateType.ToString()!] = schema.Reference.ReferenceV3; + } - groupUpdateSchema.Discriminator = new OpenApiDiscriminator + var groupUpdateSchema = new OpenApiSchema { - PropertyName = nameof(GroupUpdate.Type), - Mapping = new Dictionary<string, string> + Type = "object", + Description = "Represents the list of possible group update types", + Reference = new OpenApiReference + { + Id = nameof(GroupUpdate<object>), + Type = ReferenceType.Schema + }, + OneOf = groupUpdateSchemas, + Discriminator = new OpenApiDiscriminator { - { GroupUpdateType.UserJoined.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 }, - { GroupUpdateType.UserLeft.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 }, - { GroupUpdateType.GroupJoined.ToString(), groupUpdateOfGroupInfoSchema.Reference.ReferenceV3 }, - { GroupUpdateType.GroupLeft.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 }, - { GroupUpdateType.StateUpdate.ToString(), groupUpdateOfGroupStateSchema.Reference.ReferenceV3 }, - { GroupUpdateType.PlayQueue.ToString(), groupUpdateOfPlayQueueSchema.Reference.ReferenceV3 }, - { GroupUpdateType.NotInGroup.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 }, - { GroupUpdateType.GroupDoesNotExist.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 }, - { GroupUpdateType.LibraryAccessDenied.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 } + PropertyName = nameof(GroupUpdate<object>.Type), + Mapping = groupUpdateDiscriminators } }; + context.SchemaRepository.Schemas[nameof(GroupUpdate<object>)] = groupUpdateSchema; + context.SchemaGenerator.GenerateSchema(typeof(ServerDiscoveryInfo), context.SchemaRepository); foreach (var configuration in _serverConfigurationManager.GetConfigurationStores()) |
