< Summary - Jellyfin

Information
Class: Jellyfin.Api.Controllers.LibraryController
Assembly: Jellyfin.Api
File(s): /srv/git/jellyfin/Jellyfin.Api/Controllers/LibraryController.cs
Line coverage
23%
Covered lines: 97
Uncovered lines: 315
Coverable lines: 412
Total lines: 1057
Line coverage: 23.5%
Branch coverage
14%
Covered branches: 27
Total branches: 192
Branch coverage: 14%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 10/5/2025 - 12:11:27 AM Line coverage: 23.4% (97/413) Branch coverage: 14% (27/192) Total lines: 104612/1/2025 - 12:11:46 AM Line coverage: 23.5% (97/412) Branch coverage: 14% (27/192) Total lines: 104512/29/2025 - 12:13:19 AM Line coverage: 23.5% (97/412) Branch coverage: 14% (27/192) Total lines: 1057 10/5/2025 - 12:11:27 AM Line coverage: 23.4% (97/413) Branch coverage: 14% (27/192) Total lines: 104612/1/2025 - 12:11:46 AM Line coverage: 23.5% (97/412) Branch coverage: 14% (27/192) Total lines: 104512/29/2025 - 12:13:19 AM Line coverage: 23.5% (97/412) Branch coverage: 14% (27/192) Total lines: 1057

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
GetFile(...)50%2275%
GetThemeSongs(...)16.66%1001836.66%
GetThemeVideos(...)16.66%1001836.66%
GetThemeMedia(...)37.5%9871.42%
DeleteItem(...)33.33%271252.94%
DeleteItems(...)44.44%461855.55%
GetItemCounts(...)0%620%
GetAncestors(...)20%301041.17%
GetPhysicalPaths()100%210%
GetMediaFolders(...)0%620%
PostUpdatedSeries(...)0%620%
PostUpdatedMovies(...)0%4260%
PostUpdatedMedia(...)0%2040%
GetSimilarItems(...)8.82%5543423.4%
GetLibraryOptionsInfo(...)0%2040%
GetCount(...)100%210%
TranslateParentItem(...)0%620%
GetRepresentativeItemTypes(...)0%210140%
IsSaverEnabledByDefault(...)0%2040%
IsMetadataFetcherEnabledByDefault(...)0%210140%
IsImageFetcherEnabledByDefault(...)0%342180%

File(s)

/srv/git/jellyfin/Jellyfin.Api/Controllers/LibraryController.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.ComponentModel.DataAnnotations;
 4using System.Globalization;
 5using System.IO;
 6using System.Linq;
 7using System.Threading;
 8using System.Threading.Tasks;
 9using Jellyfin.Api.Attributes;
 10using Jellyfin.Api.Extensions;
 11using Jellyfin.Api.Helpers;
 12using Jellyfin.Api.ModelBinders;
 13using Jellyfin.Api.Models.LibraryDtos;
 14using Jellyfin.Data.Enums;
 15using Jellyfin.Database.Implementations.Entities;
 16using Jellyfin.Database.Implementations.Enums;
 17using Jellyfin.Extensions;
 18using MediaBrowser.Common.Api;
 19using MediaBrowser.Common.Extensions;
 20using MediaBrowser.Controller.Configuration;
 21using MediaBrowser.Controller.Dto;
 22using MediaBrowser.Controller.Entities;
 23using MediaBrowser.Controller.Entities.Audio;
 24using MediaBrowser.Controller.Entities.Movies;
 25using MediaBrowser.Controller.Entities.TV;
 26using MediaBrowser.Controller.IO;
 27using MediaBrowser.Controller.Library;
 28using MediaBrowser.Controller.Providers;
 29using MediaBrowser.Model.Activity;
 30using MediaBrowser.Model.Configuration;
 31using MediaBrowser.Model.Dto;
 32using MediaBrowser.Model.Entities;
 33using MediaBrowser.Model.Globalization;
 34using MediaBrowser.Model.Net;
 35using MediaBrowser.Model.Querying;
 36using Microsoft.AspNetCore.Authorization;
 37using Microsoft.AspNetCore.Http;
 38using Microsoft.AspNetCore.Mvc;
 39using Microsoft.Extensions.Logging;
 40
 41namespace Jellyfin.Api.Controllers;
 42
 43/// <summary>
 44/// Library Controller.
 45/// </summary>
 46[Route("")]
 47public class LibraryController : BaseJellyfinApiController
 48{
 49    private readonly IProviderManager _providerManager;
 50    private readonly ILibraryManager _libraryManager;
 51    private readonly IUserManager _userManager;
 52    private readonly IDtoService _dtoService;
 53    private readonly IActivityManager _activityManager;
 54    private readonly ILocalizationManager _localization;
 55    private readonly ILibraryMonitor _libraryMonitor;
 56    private readonly ILogger<LibraryController> _logger;
 57    private readonly IServerConfigurationManager _serverConfigurationManager;
 58
 59    /// <summary>
 60    /// Initializes a new instance of the <see cref="LibraryController"/> class.
 61    /// </summary>
 62    /// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
 63    /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
 64    /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
 65    /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
 66    /// <param name="activityManager">Instance of the <see cref="IActivityManager"/> interface.</param>
 67    /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
 68    /// <param name="libraryMonitor">Instance of the <see cref="ILibraryMonitor"/> interface.</param>
 69    /// <param name="logger">Instance of the <see cref="ILogger{LibraryController}"/> interface.</param>
 70    /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</p
 1471    public LibraryController(
 1472        IProviderManager providerManager,
 1473        ILibraryManager libraryManager,
 1474        IUserManager userManager,
 1475        IDtoService dtoService,
 1476        IActivityManager activityManager,
 1477        ILocalizationManager localization,
 1478        ILibraryMonitor libraryMonitor,
 1479        ILogger<LibraryController> logger,
 1480        IServerConfigurationManager serverConfigurationManager)
 81    {
 1482        _providerManager = providerManager;
 1483        _libraryManager = libraryManager;
 1484        _userManager = userManager;
 1485        _dtoService = dtoService;
 1486        _activityManager = activityManager;
 1487        _localization = localization;
 1488        _libraryMonitor = libraryMonitor;
 1489        _logger = logger;
 1490        _serverConfigurationManager = serverConfigurationManager;
 1491    }
 92
 93    /// <summary>
 94    /// Get the original file of an item.
 95    /// </summary>
 96    /// <param name="itemId">The item id.</param>
 97    /// <response code="200">File stream returned.</response>
 98    /// <response code="404">Item not found.</response>
 99    /// <returns>A <see cref="FileStreamResult"/> with the original file.</returns>
 100    [HttpGet("Items/{itemId}/File")]
 101    [Authorize]
 102    [ProducesResponseType(StatusCodes.Status200OK)]
 103    [ProducesResponseType(StatusCodes.Status404NotFound)]
 104    [ProducesFile("video/*", "audio/*")]
 105    public ActionResult GetFile([FromRoute, Required] Guid itemId)
 106    {
 1107        var item = _libraryManager.GetItemById<BaseItem>(itemId, User.GetUserId());
 1108        if (item is null)
 109        {
 1110            return NotFound();
 111        }
 112
 0113        return PhysicalFile(item.Path, MimeTypes.GetMimeType(item.Path), true);
 114    }
 115
 116    /// <summary>
 117    /// Gets critic review for an item.
 118    /// </summary>
 119    /// <response code="200">Critic reviews returned.</response>
 120    /// <returns>The list of critic reviews.</returns>
 121    [HttpGet("Items/{itemId}/CriticReviews")]
 122    [Authorize]
 123    [Obsolete("This endpoint is obsolete.")]
 124    [ProducesResponseType(StatusCodes.Status200OK)]
 125    public ActionResult<QueryResult<BaseItemDto>> GetCriticReviews()
 126    {
 127        return new QueryResult<BaseItemDto>();
 128    }
 129
 130    /// <summary>
 131    /// Get theme songs for an item.
 132    /// </summary>
 133    /// <param name="itemId">The item id.</param>
 134    /// <param name="userId">Optional. Filter by user id, and attach user data.</param>
 135    /// <param name="inheritFromParent">Optional. Determines whether or not parent items should be searched for theme me
 136    /// <param name="sortBy">Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Ar
 137    /// <param name="sortOrder">Optional. Sort Order - Ascending, Descending.</param>
 138    /// <response code="200">Theme songs returned.</response>
 139    /// <response code="404">Item not found.</response>
 140    /// <returns>The item theme songs.</returns>
 141    [HttpGet("Items/{itemId}/ThemeSongs")]
 142    [Authorize]
 143    [ProducesResponseType(StatusCodes.Status200OK)]
 144    [ProducesResponseType(StatusCodes.Status404NotFound)]
 145    public ActionResult<ThemeMediaResult> GetThemeSongs(
 146        [FromRoute, Required] Guid itemId,
 147        [FromQuery] Guid? userId,
 148        [FromQuery] bool inheritFromParent = false,
 149        [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] ItemSortBy[]? sortBy = null,
 150        [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] SortOrder[]? sortOrder = null)
 151    {
 2152        userId = RequestHelpers.GetUserId(User, userId);
 2153        var user = userId.IsNullOrEmpty()
 2154            ? null
 2155            : _userManager.GetUserById(userId.Value);
 156
 2157        var item = itemId.IsEmpty()
 2158            ? (userId.IsNullOrEmpty()
 2159                ? _libraryManager.RootFolder
 2160                : _libraryManager.GetUserRootFolder())
 2161            : _libraryManager.GetItemById<BaseItem>(itemId, user);
 2162        if (item is null)
 163        {
 2164            return NotFound();
 165        }
 166
 0167        sortOrder ??= [];
 0168        sortBy ??= [];
 0169        var orderBy = RequestHelpers.GetOrderBy(sortBy, sortOrder);
 170
 171        IReadOnlyList<BaseItem> themeItems;
 172
 0173        while (true)
 174        {
 0175            themeItems = item.GetThemeSongs(user, orderBy);
 176
 0177            if (themeItems.Count > 0 || !inheritFromParent)
 178            {
 179                break;
 180            }
 181
 0182            var parent = item.GetParent();
 0183            if (parent is null)
 184            {
 185                break;
 186            }
 187
 0188            item = parent;
 189        }
 190
 0191        var dtoOptions = new DtoOptions();
 0192        var items = themeItems
 0193            .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
 0194            .ToArray();
 195
 0196        return new ThemeMediaResult
 0197        {
 0198            Items = items,
 0199            TotalRecordCount = items.Length,
 0200            OwnerId = item.Id
 0201        };
 202    }
 203
 204    /// <summary>
 205    /// Get theme videos for an item.
 206    /// </summary>
 207    /// <param name="itemId">The item id.</param>
 208    /// <param name="userId">Optional. Filter by user id, and attach user data.</param>
 209    /// <param name="inheritFromParent">Optional. Determines whether or not parent items should be searched for theme me
 210    /// <param name="sortBy">Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Ar
 211    /// <param name="sortOrder">Optional. Sort Order - Ascending, Descending.</param>
 212    /// <response code="200">Theme videos returned.</response>
 213    /// <response code="404">Item not found.</response>
 214    /// <returns>The item theme videos.</returns>
 215    [HttpGet("Items/{itemId}/ThemeVideos")]
 216    [Authorize]
 217    [ProducesResponseType(StatusCodes.Status200OK)]
 218    [ProducesResponseType(StatusCodes.Status404NotFound)]
 219    public ActionResult<ThemeMediaResult> GetThemeVideos(
 220        [FromRoute, Required] Guid itemId,
 221        [FromQuery] Guid? userId,
 222        [FromQuery] bool inheritFromParent = false,
 223        [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] ItemSortBy[]? sortBy = null,
 224        [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] SortOrder[]? sortOrder = null)
 225    {
 2226        userId = RequestHelpers.GetUserId(User, userId);
 2227        var user = userId.IsNullOrEmpty()
 2228            ? null
 2229            : _userManager.GetUserById(userId.Value);
 2230        var item = itemId.IsEmpty()
 2231            ? (userId.IsNullOrEmpty()
 2232                ? _libraryManager.RootFolder
 2233                : _libraryManager.GetUserRootFolder())
 2234            : _libraryManager.GetItemById<BaseItem>(itemId, user);
 2235        if (item is null)
 236        {
 2237            return NotFound();
 238        }
 239
 0240        sortOrder ??= [];
 0241        sortBy ??= [];
 0242        var orderBy = RequestHelpers.GetOrderBy(sortBy, sortOrder);
 243
 244        IEnumerable<BaseItem> themeItems;
 245
 0246        while (true)
 247        {
 0248            themeItems = item.GetThemeVideos(user, orderBy);
 249
 0250            if (themeItems.Any() || !inheritFromParent)
 251            {
 252                break;
 253            }
 254
 0255            var parent = item.GetParent();
 0256            if (parent is null)
 257            {
 258                break;
 259            }
 260
 0261            item = parent;
 262        }
 263
 0264        var dtoOptions = new DtoOptions();
 0265        var items = themeItems
 0266            .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
 0267            .ToArray();
 268
 0269        return new ThemeMediaResult
 0270        {
 0271            Items = items,
 0272            TotalRecordCount = items.Length,
 0273            OwnerId = item.Id
 0274        };
 275    }
 276
 277    /// <summary>
 278    /// Get theme songs and videos for an item.
 279    /// </summary>
 280    /// <param name="itemId">The item id.</param>
 281    /// <param name="userId">Optional. Filter by user id, and attach user data.</param>
 282    /// <param name="inheritFromParent">Optional. Determines whether or not parent items should be searched for theme me
 283    /// <param name="sortBy">Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Ar
 284    /// <param name="sortOrder">Optional. Sort Order - Ascending, Descending.</param>
 285    /// <response code="200">Theme songs and videos returned.</response>
 286    /// <response code="404">Item not found.</response>
 287    /// <returns>The item theme videos.</returns>
 288    [HttpGet("Items/{itemId}/ThemeMedia")]
 289    [Authorize]
 290    [ProducesResponseType(StatusCodes.Status200OK)]
 291    public ActionResult<AllThemeMediaResult> GetThemeMedia(
 292        [FromRoute, Required] Guid itemId,
 293        [FromQuery] Guid? userId,
 294        [FromQuery] bool inheritFromParent = false,
 295        [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] ItemSortBy[]? sortBy = null,
 296        [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] SortOrder[]? sortOrder = null)
 297    {
 1298        var themeSongs = GetThemeSongs(
 1299            itemId,
 1300            userId,
 1301            inheritFromParent,
 1302            sortBy,
 1303            sortOrder);
 304
 1305        var themeVideos = GetThemeVideos(
 1306            itemId,
 1307            userId,
 1308            inheritFromParent,
 1309            sortBy,
 1310            sortOrder);
 311
 1312        if (themeSongs.Result is StatusCodeResult { StatusCode: StatusCodes.Status404NotFound }
 1313            || themeVideos.Result is StatusCodeResult { StatusCode: StatusCodes.Status404NotFound })
 314        {
 1315            return NotFound();
 316        }
 317
 0318        return new AllThemeMediaResult
 0319        {
 0320            ThemeSongsResult = themeSongs.Value,
 0321            ThemeVideosResult = themeVideos.Value,
 0322            SoundtrackSongsResult = new ThemeMediaResult()
 0323        };
 324    }
 325
 326    /// <summary>
 327    /// Starts a library scan.
 328    /// </summary>
 329    /// <response code="204">Library scan started.</response>
 330    /// <returns>A <see cref="NoContentResult"/>.</returns>
 331    [HttpPost("Library/Refresh")]
 332    [Authorize(Policy = Policies.RequiresElevation)]
 333    [ProducesResponseType(StatusCodes.Status204NoContent)]
 334    public async Task<ActionResult> RefreshLibrary()
 335    {
 336        try
 337        {
 338            await _libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None).ConfigureAwait(fa
 339        }
 340        catch (Exception ex)
 341        {
 342            _logger.LogError(ex, "Error refreshing library");
 343        }
 344
 345        return NoContent();
 346    }
 347
 348    /// <summary>
 349    /// Deletes an item from the library and filesystem.
 350    /// </summary>
 351    /// <param name="itemId">The item id.</param>
 352    /// <response code="204">Item deleted.</response>
 353    /// <response code="401">Unauthorized access.</response>
 354    /// <response code="404">Item not found.</response>
 355    /// <returns>A <see cref="NoContentResult"/>.</returns>
 356    [HttpDelete("Items/{itemId}")]
 357    [Authorize]
 358    [ProducesResponseType(StatusCodes.Status204NoContent)]
 359    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
 360    [ProducesResponseType(StatusCodes.Status404NotFound)]
 361    public ActionResult DeleteItem(Guid itemId)
 362    {
 1363        var userId = User.GetUserId();
 1364        var isApiKey = User.GetIsApiKey();
 1365        var user = userId.IsEmpty() && isApiKey
 1366            ? null
 1367            : _userManager.GetUserById(userId);
 368
 1369        if (user is null && !isApiKey)
 370        {
 0371            return NotFound();
 372        }
 373
 1374        var item = _libraryManager.GetItemById<BaseItem>(itemId, user);
 1375        if (item is null)
 376        {
 1377            return NotFound();
 378        }
 379
 0380        if (user is not null && !item.CanDelete(user))
 381        {
 0382            return Unauthorized("Unauthorized access");
 383        }
 384
 0385        _libraryManager.DeleteItem(
 0386            item,
 0387            new DeleteOptions { DeleteFileLocation = true },
 0388            true);
 389
 0390        return NoContent();
 391    }
 392
 393    /// <summary>
 394    /// Deletes items from the library and filesystem.
 395    /// </summary>
 396    /// <param name="ids">The item ids.</param>
 397    /// <response code="204">Items deleted.</response>
 398    /// <response code="401">Unauthorized access.</response>
 399    /// <returns>A <see cref="NoContentResult"/>.</returns>
 400    [HttpDelete("Items")]
 401    [Authorize]
 402    [ProducesResponseType(StatusCodes.Status204NoContent)]
 403    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
 404    [ProducesResponseType(StatusCodes.Status404NotFound)]
 405    public ActionResult DeleteItems([FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] Guid[] ids)
 406    {
 1407        var isApiKey = User.GetIsApiKey();
 1408        var userId = User.GetUserId();
 1409        var user = !isApiKey && !userId.IsEmpty()
 1410            ? _userManager.GetUserById(userId) ?? throw new ResourceNotFoundException()
 1411            : null;
 412
 1413        if (!isApiKey && user is null)
 414        {
 0415            return Unauthorized("Unauthorized access");
 416        }
 417
 3418        foreach (var i in ids)
 419        {
 1420            var item = _libraryManager.GetItemById<BaseItem>(i, user);
 1421            if (item is null)
 422            {
 1423                return NotFound();
 424            }
 425
 0426            if (user is not null && !item.CanDelete(user))
 427            {
 0428                return Unauthorized("Unauthorized access");
 429            }
 430
 0431            _libraryManager.DeleteItem(
 0432                item,
 0433                new DeleteOptions { DeleteFileLocation = true },
 0434                true);
 435        }
 436
 0437        return NoContent();
 438    }
 439
 440    /// <summary>
 441    /// Get item counts.
 442    /// </summary>
 443    /// <param name="userId">Optional. Get counts from a specific user's library.</param>
 444    /// <param name="isFavorite">Optional. Get counts of favorite items.</param>
 445    /// <response code="200">Item counts returned.</response>
 446    /// <returns>Item counts.</returns>
 447    [HttpGet("Items/Counts")]
 448    [Authorize]
 449    [ProducesResponseType(StatusCodes.Status200OK)]
 450    public ActionResult<ItemCounts> GetItemCounts(
 451        [FromQuery] Guid? userId,
 452        [FromQuery] bool? isFavorite)
 453    {
 0454        userId = RequestHelpers.GetUserId(User, userId);
 0455        var user = userId.IsNullOrEmpty()
 0456            ? null
 0457            : _userManager.GetUserById(userId.Value);
 458
 0459        var counts = new ItemCounts
 0460        {
 0461            AlbumCount = GetCount(BaseItemKind.MusicAlbum, user, isFavorite),
 0462            EpisodeCount = GetCount(BaseItemKind.Episode, user, isFavorite),
 0463            MovieCount = GetCount(BaseItemKind.Movie, user, isFavorite),
 0464            SeriesCount = GetCount(BaseItemKind.Series, user, isFavorite),
 0465            SongCount = GetCount(BaseItemKind.Audio, user, isFavorite),
 0466            MusicVideoCount = GetCount(BaseItemKind.MusicVideo, user, isFavorite),
 0467            BoxSetCount = GetCount(BaseItemKind.BoxSet, user, isFavorite),
 0468            BookCount = GetCount(BaseItemKind.Book, user, isFavorite)
 0469        };
 470
 0471        return counts;
 472    }
 473
 474    /// <summary>
 475    /// Gets all parents of an item.
 476    /// </summary>
 477    /// <param name="itemId">The item id.</param>
 478    /// <param name="userId">Optional. Filter by user id, and attach user data.</param>
 479    /// <response code="200">Item parents returned.</response>
 480    /// <response code="404">Item not found.</response>
 481    /// <returns>Item parents.</returns>
 482    [HttpGet("Items/{itemId}/Ancestors")]
 483    [Authorize]
 484    [ProducesResponseType(StatusCodes.Status200OK)]
 485    [ProducesResponseType(StatusCodes.Status404NotFound)]
 486    public ActionResult<IEnumerable<BaseItemDto>> GetAncestors([FromRoute, Required] Guid itemId, [FromQuery] Guid? user
 487    {
 1488        userId = RequestHelpers.GetUserId(User, userId);
 1489        var user = userId.IsNullOrEmpty()
 1490            ? null
 1491            : _userManager.GetUserById(userId.Value);
 1492        var item = _libraryManager.GetItemById<BaseItem>(itemId, user);
 1493        if (item is null)
 494        {
 1495            return NotFound();
 496        }
 497
 0498        var baseItemDtos = new List<BaseItemDto>();
 499
 0500        var dtoOptions = new DtoOptions();
 0501        BaseItem? parent = item.GetParent();
 502
 0503        while (parent is not null)
 504        {
 0505            if (user is not null)
 506            {
 0507                parent = TranslateParentItem(parent, user);
 0508                if (parent is null)
 509                {
 510                    break;
 511                }
 512            }
 513
 0514            baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
 515
 0516            parent = parent.GetParent();
 517        }
 518
 0519        return baseItemDtos;
 520    }
 521
 522    /// <summary>
 523    /// Gets a list of physical paths from virtual folders.
 524    /// </summary>
 525    /// <response code="200">Physical paths returned.</response>
 526    /// <returns>List of physical paths.</returns>
 527    [HttpGet("Library/PhysicalPaths")]
 528    [Authorize(Policy = Policies.RequiresElevation)]
 529    [ProducesResponseType(StatusCodes.Status200OK)]
 530    public ActionResult<IEnumerable<string>> GetPhysicalPaths()
 531    {
 0532        return Ok(_libraryManager.RootFolder.Children
 0533            .SelectMany(c => c.PhysicalLocations));
 534    }
 535
 536    /// <summary>
 537    /// Gets all user media folders.
 538    /// </summary>
 539    /// <param name="isHidden">Optional. Filter by folders that are marked hidden, or not.</param>
 540    /// <response code="200">Media folders returned.</response>
 541    /// <returns>List of user media folders.</returns>
 542    [HttpGet("Library/MediaFolders")]
 543    [Authorize(Policy = Policies.RequiresElevation)]
 544    [ProducesResponseType(StatusCodes.Status200OK)]
 545    public ActionResult<QueryResult<BaseItemDto>> GetMediaFolders([FromQuery] bool? isHidden)
 546    {
 0547        var items = _libraryManager.GetUserRootFolder().Children
 0548            .Concat(_libraryManager.RootFolder.VirtualChildren)
 0549            .Where(i => _libraryManager.GetLibraryOptions(i).Enabled)
 0550            .OrderBy(i => i.SortName)
 0551            .ToList();
 552
 0553        if (isHidden.HasValue)
 554        {
 0555            var val = isHidden.Value;
 556
 0557            items = items.Where(i => i.IsHidden == val).ToList();
 558        }
 559
 0560        var dtoOptions = new DtoOptions();
 0561        var resultArray = _dtoService.GetBaseItemDtos(items, dtoOptions);
 0562        return new QueryResult<BaseItemDto>(resultArray);
 563    }
 564
 565    /// <summary>
 566    /// Reports that new episodes of a series have been added by an external source.
 567    /// </summary>
 568    /// <param name="tvdbId">The tvdbId.</param>
 569    /// <response code="204">Report success.</response>
 570    /// <returns>A <see cref="NoContentResult"/>.</returns>
 571    [HttpPost("Library/Series/Added", Name = "PostAddedSeries")]
 572    [HttpPost("Library/Series/Updated")]
 573    [Authorize]
 574    [ProducesResponseType(StatusCodes.Status204NoContent)]
 575    public ActionResult PostUpdatedSeries([FromQuery] string? tvdbId)
 576    {
 0577        var series = _libraryManager.GetItemList(new InternalItemsQuery
 0578        {
 0579            IncludeItemTypes = new[] { BaseItemKind.Series },
 0580            DtoOptions = new DtoOptions(false)
 0581            {
 0582                EnableImages = false
 0583            }
 0584        }).Where(i => string.Equals(tvdbId, i.GetProviderId(MediaBrowser.Model.Entities.MetadataProvider.Tvdb), StringCo
 585
 0586        foreach (var item in series)
 587        {
 0588            _libraryMonitor.ReportFileSystemChanged(item.Path);
 589        }
 590
 0591        return NoContent();
 592    }
 593
 594    /// <summary>
 595    /// Reports that new movies have been added by an external source.
 596    /// </summary>
 597    /// <param name="tmdbId">The tmdbId.</param>
 598    /// <param name="imdbId">The imdbId.</param>
 599    /// <response code="204">Report success.</response>
 600    /// <returns>A <see cref="NoContentResult"/>.</returns>
 601    [HttpPost("Library/Movies/Added", Name = "PostAddedMovies")]
 602    [HttpPost("Library/Movies/Updated")]
 603    [Authorize]
 604    [ProducesResponseType(StatusCodes.Status204NoContent)]
 605    public ActionResult PostUpdatedMovies([FromQuery] string? tmdbId, [FromQuery] string? imdbId)
 606    {
 0607        var movies = _libraryManager.GetItemList(new InternalItemsQuery
 0608        {
 0609            IncludeItemTypes = new[] { BaseItemKind.Movie },
 0610            DtoOptions = new DtoOptions(false)
 0611            {
 0612                EnableImages = false
 0613            }
 0614        });
 615
 0616        if (!string.IsNullOrWhiteSpace(imdbId))
 617        {
 0618            movies = movies.Where(i => string.Equals(imdbId, i.GetProviderId(MediaBrowser.Model.Entities.MetadataProvide
 619        }
 0620        else if (!string.IsNullOrWhiteSpace(tmdbId))
 621        {
 0622            movies = movies.Where(i => string.Equals(tmdbId, i.GetProviderId(MediaBrowser.Model.Entities.MetadataProvide
 623        }
 624        else
 625        {
 0626            movies = new List<BaseItem>();
 627        }
 628
 0629        foreach (var item in movies)
 630        {
 0631            _libraryMonitor.ReportFileSystemChanged(item.Path);
 632        }
 633
 0634        return NoContent();
 635    }
 636
 637    /// <summary>
 638    /// Reports that new movies have been added by an external source.
 639    /// </summary>
 640    /// <param name="dto">The update paths.</param>
 641    /// <response code="204">Report success.</response>
 642    /// <returns>A <see cref="NoContentResult"/>.</returns>
 643    [HttpPost("Library/Media/Updated")]
 644    [Authorize]
 645    [ProducesResponseType(StatusCodes.Status204NoContent)]
 646    public ActionResult PostUpdatedMedia([FromBody, Required] MediaUpdateInfoDto dto)
 647    {
 0648        foreach (var item in dto.Updates)
 649        {
 0650            _libraryMonitor.ReportFileSystemChanged(item.Path ?? throw new ArgumentException("Item path can't be null.")
 651        }
 652
 0653        return NoContent();
 654    }
 655
 656    /// <summary>
 657    /// Downloads item media.
 658    /// </summary>
 659    /// <param name="itemId">The item id.</param>
 660    /// <response code="200">Media downloaded.</response>
 661    /// <response code="404">Item not found.</response>
 662    /// <returns>A <see cref="FileResult"/> containing the media stream.</returns>
 663    /// <exception cref="ArgumentException">User can't download or item can't be downloaded.</exception>
 664    [HttpGet("Items/{itemId}/Download")]
 665    [Authorize(Policy = Policies.Download)]
 666    [ProducesResponseType(StatusCodes.Status200OK)]
 667    [ProducesResponseType(StatusCodes.Status404NotFound)]
 668    [ProducesFile("video/*", "audio/*")]
 669    public async Task<ActionResult> GetDownload([FromRoute, Required] Guid itemId)
 670    {
 671        var userId = User.GetUserId();
 672        var user = userId.IsEmpty()
 673            ? null
 674            : _userManager.GetUserById(userId);
 675        var item = _libraryManager.GetItemById<BaseItem>(itemId, user);
 676        if (item is null)
 677        {
 678            return NotFound();
 679        }
 680
 681        if (user is not null)
 682        {
 683            if (!item.CanDownload(user))
 684            {
 685                throw new ArgumentException("Item does not support downloading");
 686            }
 687        }
 688        else
 689        {
 690            if (!item.CanDownload())
 691            {
 692                throw new ArgumentException("Item does not support downloading");
 693            }
 694        }
 695
 696        if (user is not null)
 697        {
 698            await LogDownloadAsync(item, user).ConfigureAwait(false);
 699        }
 700
 701        // Quotes are valid in linux. They'll possibly cause issues here.
 702        var filename = Path.GetFileName(item.Path)?.Replace("\"", string.Empty, StringComparison.Ordinal);
 703
 704        var filePath = item.Path;
 705        if (item.IsFileProtocol)
 706        {
 707            // PhysicalFile does not work well with symlinks at the moment.
 708            var resolved = FileSystemHelper.ResolveLinkTarget(filePath, returnFinalTarget: true);
 709            if (resolved is not null && resolved.Exists)
 710            {
 711                filePath = resolved.FullName;
 712            }
 713        }
 714
 715        return PhysicalFile(filePath, MimeTypes.GetMimeType(filePath), filename, true);
 716    }
 717
 718    /// <summary>
 719    /// Gets similar items.
 720    /// </summary>
 721    /// <param name="itemId">The item id.</param>
 722    /// <param name="excludeArtistIds">Exclude artist ids.</param>
 723    /// <param name="userId">Optional. Filter by user id, and attach user data.</param>
 724    /// <param name="limit">Optional. The maximum number of records to return.</param>
 725    /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows mul
 726    /// <response code="200">Similar items returned.</response>
 727    /// <returns>A <see cref="QueryResult{BaseItemDto}"/> containing the similar items.</returns>
 728    [HttpGet("Artists/{itemId}/Similar", Name = "GetSimilarArtists")]
 729    [HttpGet("Items/{itemId}/Similar")]
 730    [HttpGet("Albums/{itemId}/Similar", Name = "GetSimilarAlbums")]
 731    [HttpGet("Shows/{itemId}/Similar", Name = "GetSimilarShows")]
 732    [HttpGet("Movies/{itemId}/Similar", Name = "GetSimilarMovies")]
 733    [HttpGet("Trailers/{itemId}/Similar", Name = "GetSimilarTrailers")]
 734    [Authorize]
 735    [ProducesResponseType(StatusCodes.Status200OK)]
 736    public ActionResult<QueryResult<BaseItemDto>> GetSimilarItems(
 737        [FromRoute, Required] Guid itemId,
 738        [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] Guid[] excludeArtistIds,
 739        [FromQuery] Guid? userId,
 740        [FromQuery] int? limit,
 741        [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] ItemFields[] fields)
 742    {
 6743        userId = RequestHelpers.GetUserId(User, userId);
 6744        var user = userId.IsNullOrEmpty()
 6745            ? null
 6746            : _userManager.GetUserById(userId.Value);
 6747        var item = itemId.IsEmpty()
 6748            ? (user is null
 6749                ? _libraryManager.RootFolder
 6750                : _libraryManager.GetUserRootFolder())
 6751            : _libraryManager.GetItemById<BaseItem>(itemId, user);
 6752        if (item is null)
 753        {
 6754            return NotFound();
 755        }
 756
 0757        if (item is Episode || (item is IItemByName && item is not MusicArtist))
 758        {
 0759            return new QueryResult<BaseItemDto>();
 760        }
 761
 0762        var dtoOptions = new DtoOptions { Fields = fields };
 763
 0764        var program = item as IHasProgramAttributes;
 0765        bool? isMovie = item is Movie || (program is not null && program.IsMovie) || item is Trailer;
 0766        bool? isSeries = item is Series || (program is not null && program.IsSeries);
 767
 0768        var includeItemTypes = new List<BaseItemKind>();
 0769        if (isMovie.Value)
 770        {
 0771            includeItemTypes.Add(BaseItemKind.Movie);
 0772            if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
 773            {
 0774                includeItemTypes.Add(BaseItemKind.Trailer);
 0775                includeItemTypes.Add(BaseItemKind.LiveTvProgram);
 776            }
 777        }
 0778        else if (isSeries.Value)
 779        {
 0780            includeItemTypes.Add(BaseItemKind.Series);
 781        }
 782        else
 783        {
 784            // For non series and movie types these columns are typically null
 785            // isSeries = null;
 0786            isMovie = null;
 0787            includeItemTypes.Add(item.GetBaseItemKind());
 788        }
 789
 0790        var query = new InternalItemsQuery(user)
 0791        {
 0792            Genres = item.Genres,
 0793            Tags = item.Tags,
 0794            Limit = limit,
 0795            IncludeItemTypes = includeItemTypes.ToArray(),
 0796            DtoOptions = dtoOptions,
 0797            EnableTotalRecordCount = !isMovie ?? true,
 0798            EnableGroupByMetadataKey = isMovie ?? false,
 0799            ExcludeItemIds = [itemId],
 0800            OrderBy = [(ItemSortBy.Random, SortOrder.Ascending)]
 0801        };
 802
 803        // ExcludeArtistIds
 0804        if (excludeArtistIds.Length != 0)
 805        {
 0806            query.ExcludeArtistIds = excludeArtistIds;
 807        }
 808
 0809        var itemsResult = _libraryManager.GetItemList(query);
 810
 0811        var returnList = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user);
 812
 0813        return new QueryResult<BaseItemDto>(
 0814            query.StartIndex,
 0815            itemsResult.Count,
 0816            returnList);
 817    }
 818
 819    /// <summary>
 820    /// Gets the library options info.
 821    /// </summary>
 822    /// <param name="libraryContentType">Library content type.</param>
 823    /// <param name="isNewLibrary">Whether this is a new library.</param>
 824    /// <response code="200">Library options info returned.</response>
 825    /// <returns>Library options info.</returns>
 826    [HttpGet("Libraries/AvailableOptions")]
 827    [Authorize(Policy = Policies.FirstTimeSetupOrDefault)]
 828    [ProducesResponseType(StatusCodes.Status200OK)]
 829    public ActionResult<LibraryOptionsResultDto> GetLibraryOptionsInfo(
 830        [FromQuery] CollectionType? libraryContentType,
 831        [FromQuery] bool isNewLibrary = false)
 832    {
 0833        var result = new LibraryOptionsResultDto();
 834
 0835        var types = GetRepresentativeItemTypes(libraryContentType);
 0836        var typesList = types.ToList();
 837
 0838        var plugins = _providerManager.GetAllMetadataPlugins()
 0839            .Where(i => types.Contains(i.ItemType, StringComparison.OrdinalIgnoreCase))
 0840            .OrderBy(i => typesList.IndexOf(i.ItemType))
 0841            .ToList();
 842
 0843        result.MetadataSavers = plugins
 0844            .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MetadataSaver))
 0845            .Select(i => new LibraryOptionInfoDto
 0846            {
 0847                Name = i.Name,
 0848                DefaultEnabled = IsSaverEnabledByDefault(i.Name, types, isNewLibrary)
 0849            })
 0850            .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
 0851            .ToArray();
 852
 0853        result.MetadataReaders = plugins
 0854            .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.LocalMetadataProvider))
 0855            .Select(i => new LibraryOptionInfoDto
 0856            {
 0857                Name = i.Name,
 0858                DefaultEnabled = true
 0859            })
 0860            .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
 0861            .ToArray();
 862
 0863        result.SubtitleFetchers = plugins
 0864            .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.SubtitleFetcher))
 0865            .Select(i => new LibraryOptionInfoDto
 0866            {
 0867                Name = i.Name,
 0868                DefaultEnabled = true
 0869            })
 0870            .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
 0871            .ToArray();
 872
 0873        result.LyricFetchers = plugins
 0874            .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.LyricFetcher))
 0875            .Select(i => new LibraryOptionInfoDto
 0876            {
 0877                Name = i.Name,
 0878                DefaultEnabled = true
 0879            })
 0880            .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
 0881            .ToArray();
 882
 0883        result.MediaSegmentProviders = plugins
 0884            .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MediaSegmentProvider))
 0885            .Select(i => new LibraryOptionInfoDto
 0886            {
 0887                Name = i.Name,
 0888                DefaultEnabled = true
 0889            })
 0890            .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
 0891            .ToArray();
 892
 0893        var typeOptions = new List<LibraryTypeOptionsDto>();
 894
 0895        foreach (var type in types)
 896        {
 0897            TypeOptions.DefaultImageOptions.TryGetValue(type, out var defaultImageOptions);
 898
 0899            typeOptions.Add(new LibraryTypeOptionsDto
 0900            {
 0901                Type = type,
 0902
 0903                MetadataFetchers = plugins
 0904                    .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
 0905                    .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MetadataFetcher))
 0906                    .Select(i => new LibraryOptionInfoDto
 0907                    {
 0908                        Name = i.Name,
 0909                        DefaultEnabled = IsMetadataFetcherEnabledByDefault(i.Name, type, isNewLibrary)
 0910                    })
 0911                    .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
 0912                    .ToArray(),
 0913
 0914                ImageFetchers = plugins
 0915                    .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
 0916                    .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.ImageFetcher))
 0917                    .Select(i => new LibraryOptionInfoDto
 0918                    {
 0919                        Name = i.Name,
 0920                        DefaultEnabled = IsImageFetcherEnabledByDefault(i.Name, type, isNewLibrary)
 0921                    })
 0922                    .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
 0923                    .ToArray(),
 0924
 0925                SupportedImageTypes = plugins
 0926                    .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
 0927                    .SelectMany(i => i.SupportedImageTypes ?? Array.Empty<ImageType>())
 0928                    .Distinct()
 0929                    .ToArray(),
 0930
 0931                DefaultImageOptions = defaultImageOptions ?? Array.Empty<ImageOption>()
 0932            });
 933        }
 934
 0935        result.TypeOptions = typeOptions.ToArray();
 936
 0937        return result;
 938    }
 939
 940    private int GetCount(BaseItemKind itemKind, User? user, bool? isFavorite)
 941    {
 0942        var query = new InternalItemsQuery(user)
 0943        {
 0944            IncludeItemTypes = new[] { itemKind },
 0945            Limit = 0,
 0946            Recursive = true,
 0947            IsVirtualItem = false,
 0948            IsFavorite = isFavorite,
 0949            DtoOptions = new DtoOptions(false)
 0950            {
 0951                EnableImages = false
 0952            }
 0953        };
 954
 0955        return _libraryManager.GetItemsResult(query).TotalRecordCount;
 956    }
 957
 958    private BaseItem? TranslateParentItem(BaseItem item, User user)
 959    {
 0960        return item.GetParent() is AggregateFolder
 0961            ? _libraryManager.GetUserRootFolder().GetChildren(user, true)
 0962                .FirstOrDefault(i => i.PhysicalLocations.Contains(item.Path))
 0963            : item;
 964    }
 965
 966    private async Task LogDownloadAsync(BaseItem item, User user)
 967    {
 968        try
 969        {
 970            await _activityManager.CreateAsync(new ActivityLog(
 971                string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("UserDownloadingItemWithVal
 972                "UserDownloadingContent",
 973                User.GetUserId())
 974            {
 975                ShortOverview = string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("AppDeviceV
 976                ItemId = item.Id.ToString("N", CultureInfo.InvariantCulture)
 977            }).ConfigureAwait(false);
 978        }
 979        catch
 980        {
 981            // Logged at lower levels
 982        }
 983    }
 984
 985    private static string[] GetRepresentativeItemTypes(CollectionType? contentType)
 986    {
 0987        return contentType switch
 0988        {
 0989            CollectionType.boxsets => new[] { "BoxSet" },
 0990            CollectionType.playlists => new[] { "Playlist" },
 0991            CollectionType.movies => new[] { "Movie" },
 0992            CollectionType.tvshows => new[] { "Series", "Season", "Episode" },
 0993            CollectionType.books => new[] { "Book" },
 0994            CollectionType.music => new[] { "MusicArtist", "MusicAlbum", "Audio", "MusicVideo" },
 0995            CollectionType.homevideos => new[] { "Video", "Photo" },
 0996            CollectionType.photos => new[] { "Video", "Photo" },
 0997            CollectionType.musicvideos => new[] { "MusicVideo" },
 0998            _ => new[] { "Series", "Season", "Episode", "Movie" }
 0999        };
 1000    }
 1001
 1002    private bool IsSaverEnabledByDefault(string name, string[] itemTypes, bool isNewLibrary)
 1003    {
 01004        if (isNewLibrary)
 1005        {
 01006            return false;
 1007        }
 1008
 01009        var metadataOptions = _serverConfigurationManager.Configuration.MetadataOptions
 01010            .Where(i => itemTypes.Contains(i.ItemType ?? string.Empty, StringComparison.OrdinalIgnoreCase))
 01011            .ToArray();
 1012
 01013        return metadataOptions.Length == 0 || metadataOptions.Any(i => !i.DisabledMetadataSavers.Contains(name, StringCo
 1014    }
 1015
 1016    private bool IsMetadataFetcherEnabledByDefault(string name, string type, bool isNewLibrary)
 1017    {
 01018        if (isNewLibrary)
 1019        {
 01020            if (string.Equals(name, "TheMovieDb", StringComparison.OrdinalIgnoreCase))
 1021            {
 01022                return !(string.Equals(type, "Season", StringComparison.OrdinalIgnoreCase)
 01023                         || string.Equals(type, "Episode", StringComparison.OrdinalIgnoreCase)
 01024                         || string.Equals(type, "MusicVideo", StringComparison.OrdinalIgnoreCase));
 1025            }
 1026
 01027            return string.Equals(name, "TheTVDB", StringComparison.OrdinalIgnoreCase)
 01028                   || string.Equals(name, "TheAudioDB", StringComparison.OrdinalIgnoreCase)
 01029                   || string.Equals(name, "MusicBrainz", StringComparison.OrdinalIgnoreCase);
 1030        }
 1031
 01032        var metadataOptions = _serverConfigurationManager.GetMetadataOptionsForType(type);
 01033        return metadataOptions is null || !metadataOptions.DisabledMetadataFetchers.Contains(name, StringComparison.Ordi
 1034    }
 1035
 1036    private bool IsImageFetcherEnabledByDefault(string name, string type, bool isNewLibrary)
 1037    {
 01038        if (isNewLibrary)
 1039        {
 01040            if (string.Equals(name, "TheMovieDb", StringComparison.OrdinalIgnoreCase))
 1041            {
 01042                return !string.Equals(type, "Series", StringComparison.OrdinalIgnoreCase)
 01043                       && !string.Equals(type, "Season", StringComparison.OrdinalIgnoreCase)
 01044                       && !string.Equals(type, "Episode", StringComparison.OrdinalIgnoreCase)
 01045                       && !string.Equals(type, "MusicVideo", StringComparison.OrdinalIgnoreCase);
 1046            }
 1047
 01048            return string.Equals(name, "TheTVDB", StringComparison.OrdinalIgnoreCase)
 01049                   || string.Equals(name, "Screen Grabber", StringComparison.OrdinalIgnoreCase)
 01050                   || string.Equals(name, "TheAudioDB", StringComparison.OrdinalIgnoreCase)
 01051                   || string.Equals(name, "Image Extractor", StringComparison.OrdinalIgnoreCase);
 1052        }
 1053
 01054        var metadataOptions = _serverConfigurationManager.GetMetadataOptionsForType(type);
 01055        return metadataOptions is null || !metadataOptions.DisabledImageFetchers.Contains(name, StringComparison.Ordinal
 1056    }
 1057}

Methods/Properties

.ctor(MediaBrowser.Controller.Providers.IProviderManager,MediaBrowser.Controller.Library.ILibraryManager,MediaBrowser.Controller.Library.IUserManager,MediaBrowser.Controller.Dto.IDtoService,MediaBrowser.Model.Activity.IActivityManager,MediaBrowser.Model.Globalization.ILocalizationManager,MediaBrowser.Controller.Library.ILibraryMonitor,Microsoft.Extensions.Logging.ILogger`1<Jellyfin.Api.Controllers.LibraryController>,MediaBrowser.Controller.Configuration.IServerConfigurationManager)
GetFile(System.Guid)
GetThemeSongs(System.Guid,System.Nullable`1<System.Guid>,System.Boolean,Jellyfin.Data.Enums.ItemSortBy[],Jellyfin.Database.Implementations.Enums.SortOrder[])
GetThemeVideos(System.Guid,System.Nullable`1<System.Guid>,System.Boolean,Jellyfin.Data.Enums.ItemSortBy[],Jellyfin.Database.Implementations.Enums.SortOrder[])
GetThemeMedia(System.Guid,System.Nullable`1<System.Guid>,System.Boolean,Jellyfin.Data.Enums.ItemSortBy[],Jellyfin.Database.Implementations.Enums.SortOrder[])
DeleteItem(System.Guid)
DeleteItems(System.Guid[])
GetItemCounts(System.Nullable`1<System.Guid>,System.Nullable`1<System.Boolean>)
GetAncestors(System.Guid,System.Nullable`1<System.Guid>)
GetPhysicalPaths()
GetMediaFolders(System.Nullable`1<System.Boolean>)
PostUpdatedSeries(System.String)
PostUpdatedMovies(System.String,System.String)
PostUpdatedMedia(Jellyfin.Api.Models.LibraryDtos.MediaUpdateInfoDto)
GetSimilarItems(System.Guid,System.Guid[],System.Nullable`1<System.Guid>,System.Nullable`1<System.Int32>,MediaBrowser.Model.Querying.ItemFields[])
GetLibraryOptionsInfo(System.Nullable`1<Jellyfin.Data.Enums.CollectionType>,System.Boolean)
GetCount(Jellyfin.Data.Enums.BaseItemKind,Jellyfin.Database.Implementations.Entities.User,System.Nullable`1<System.Boolean>)
TranslateParentItem(MediaBrowser.Controller.Entities.BaseItem,Jellyfin.Database.Implementations.Entities.User)
GetRepresentativeItemTypes(System.Nullable`1<Jellyfin.Data.Enums.CollectionType>)
IsSaverEnabledByDefault(System.String,System.String[],System.Boolean)
IsMetadataFetcherEnabledByDefault(System.String,System.String,System.Boolean)
IsImageFetcherEnabledByDefault(System.String,System.String,System.Boolean)