using System; using System.Linq; using Jellyfin.Api.Helpers; using MediaBrowser.Controller.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using Microsoft.AspNetCore.Http; namespace Jellyfin.Api.Extensions { /// /// Dto Extensions. /// public static class DtoExtensions { /// /// Add Dto Item fields. /// /// /// Converted from IHasItemFields. /// Legacy order: 1. /// /// DtoOptions object. /// Comma delimited string of fields. /// Modified DtoOptions object. internal static DtoOptions AddItemFields(this DtoOptions dtoOptions, string? fields) { if (string.IsNullOrEmpty(fields)) { dtoOptions.Fields = Array.Empty(); } else { dtoOptions.Fields = fields.Split(',') .Select(v => { if (Enum.TryParse(v, true, out ItemFields value)) { return (ItemFields?)value; } return null; }) .Where(i => i.HasValue) .Select(i => i!.Value) .ToArray(); } return dtoOptions; } /// /// Add additional fields depending on client. /// /// /// Use in place of GetDtoOptions. /// Legacy order: 2. /// /// DtoOptions object. /// Current request. /// Modified DtoOptions object. internal static DtoOptions AddClientFields( this DtoOptions dtoOptions, HttpRequest request) { dtoOptions.Fields ??= Array.Empty(); string? client = ClaimHelpers.GetClient(request.HttpContext.User); // No client in claim if (string.IsNullOrEmpty(client)) { return dtoOptions; } if (!dtoOptions.ContainsField(ItemFields.RecursiveItemCount)) { if (client.IndexOf("kodi", StringComparison.OrdinalIgnoreCase) != -1 || client.IndexOf("wmc", StringComparison.OrdinalIgnoreCase) != -1 || client.IndexOf("media center", StringComparison.OrdinalIgnoreCase) != -1 || client.IndexOf("classic", StringComparison.OrdinalIgnoreCase) != -1) { int oldLen = dtoOptions.Fields.Length; var arr = new ItemFields[oldLen + 1]; dtoOptions.Fields.CopyTo(arr, 0); arr[oldLen] = ItemFields.RecursiveItemCount; dtoOptions.Fields = arr; } } if (!dtoOptions.ContainsField(ItemFields.ChildCount)) { if (client.IndexOf("kodi", StringComparison.OrdinalIgnoreCase) != -1 || client.IndexOf("wmc", StringComparison.OrdinalIgnoreCase) != -1 || client.IndexOf("media center", StringComparison.OrdinalIgnoreCase) != -1 || client.IndexOf("classic", StringComparison.OrdinalIgnoreCase) != -1 || client.IndexOf("roku", StringComparison.OrdinalIgnoreCase) != -1 || client.IndexOf("samsung", StringComparison.OrdinalIgnoreCase) != -1 || client.IndexOf("androidtv", StringComparison.OrdinalIgnoreCase) != -1) { int oldLen = dtoOptions.Fields.Length; var arr = new ItemFields[oldLen + 1]; dtoOptions.Fields.CopyTo(arr, 0); arr[oldLen] = ItemFields.ChildCount; dtoOptions.Fields = arr; } } return dtoOptions; } /// /// Add additional DtoOptions. /// /// /// Converted from IHasDtoOptions. /// Legacy order: 3. /// /// DtoOptions object. /// Enable images. /// Enable user data. /// Image type limit. /// Enable image types. /// Modified DtoOptions object. internal static DtoOptions AddAdditionalDtoOptions( this DtoOptions dtoOptions, bool? enableImages, bool? enableUserData, int? imageTypeLimit, string? enableImageTypes) { dtoOptions.EnableImages = enableImages ?? true; if (imageTypeLimit.HasValue) { dtoOptions.ImageTypeLimit = imageTypeLimit.Value; } if (enableUserData.HasValue) { dtoOptions.EnableUserData = enableUserData.Value; } if (!string.IsNullOrWhiteSpace(enableImageTypes)) { dtoOptions.ImageTypes = enableImageTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(v => (ImageType)Enum.Parse(typeof(ImageType), v, true)) .ToArray(); } return dtoOptions; } /// /// Check if DtoOptions contains field. /// /// DtoOptions object. /// Field to check. /// Field existence. internal static bool ContainsField(this DtoOptions dtoOptions, ItemFields field) => dtoOptions.Fields != null && dtoOptions.Fields.Contains(field); } }