aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller/Entities')
-rw-r--r--MediaBrowser.Controller/Entities/AggregateFolder.cs4
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs12
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs4
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs68
-rw-r--r--MediaBrowser.Controller/Entities/CollectionFolder.cs3
-rw-r--r--MediaBrowser.Controller/Entities/Extensions.cs8
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs68
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs3
-rw-r--r--MediaBrowser.Controller/Entities/Movies/Movie.cs21
-rw-r--r--MediaBrowser.Controller/Entities/TV/Episode.cs17
-rw-r--r--MediaBrowser.Controller/Entities/TV/Season.cs19
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs51
-rw-r--r--MediaBrowser.Controller/Entities/TagExtensions.cs4
-rw-r--r--MediaBrowser.Controller/Entities/Trailer.cs20
-rw-r--r--MediaBrowser.Controller/Entities/UserRootFolder.cs4
-rw-r--r--MediaBrowser.Controller/Entities/UserView.cs4
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs4
17 files changed, 118 insertions, 196 deletions
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs
index b225f22df..40cdd6c91 100644
--- a/MediaBrowser.Controller/Entities/AggregateFolder.cs
+++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs
@@ -155,11 +155,11 @@ namespace MediaBrowser.Controller.Entities
return base.GetNonCachedChildren(directoryService).Concat(_virtualChildren);
}
- protected override async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
+ protected override async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, bool allowRemoveRoot, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
ClearCache();
- await base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, refreshOptions, directoryService, cancellationToken)
+ await base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, allowRemoveRoot, refreshOptions, directoryService, cancellationToken)
.ConfigureAwait(false);
ClearCache();
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index 237345206..a0aae8769 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -169,8 +169,7 @@ namespace MediaBrowser.Controller.Entities.Audio
var childUpdateType = ItemUpdateType.None;
- // Refresh songs only and not m3u files in album folder
- foreach (var item in items.OfType<Audio>())
+ foreach (var item in items)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -183,14 +182,13 @@ namespace MediaBrowser.Controller.Entities.Audio
progress.Report(percent * 95);
}
- // get album LUFS
- LUFS = items.OfType<Audio>().Max(item => item.LUFS);
-
var parentRefreshOptions = refreshOptions;
if (childUpdateType > ItemUpdateType.None)
{
- parentRefreshOptions = new MetadataRefreshOptions(refreshOptions);
- parentRefreshOptions.MetadataRefreshMode = MetadataRefreshMode.FullRefresh;
+ parentRefreshOptions = new MetadataRefreshOptions(refreshOptions)
+ {
+ MetadataRefreshMode = MetadataRefreshMode.FullRefresh
+ };
}
// Refresh current item
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index 11cdf8444..1ab6c9706 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -110,7 +110,7 @@ namespace MediaBrowser.Controller.Entities.Audio
return base.IsSaveLocalMetadataEnabled();
}
- protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
+ protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, bool allowRemoveRoot, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
if (IsAccessedByName)
{
@@ -118,7 +118,7 @@ namespace MediaBrowser.Controller.Entities.Audio
return Task.CompletedTask;
}
- return base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, refreshOptions, directoryService, cancellationToken);
+ return base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, false, refreshOptions, directoryService, cancellationToken);
}
public override List<string> GetUserDataKeys()
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index ac9698ec9..7b6f364f7 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -135,7 +135,14 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value>The LUFS Value.</value>
[JsonIgnore]
- public float LUFS { get; set; }
+ public float? LUFS { get; set; }
+
+ /// <summary>
+ /// Gets or sets the gain required for audio normalization.
+ /// </summary>
+ /// <value>The gain required for audio normalization.</value>
+ [JsonIgnore]
+ public float? NormalizationGain { get; set; }
/// <summary>
/// Gets or sets the channel identifier.
@@ -745,9 +752,6 @@ namespace MediaBrowser.Controller.Entities
public virtual bool SupportsAncestors => true;
[JsonIgnore]
- public virtual bool StopRefreshIfLocalMetadataFound => true;
-
- [JsonIgnore]
protected virtual bool SupportsOwnedItems => !ParentId.IsEmpty() && IsFileProtocol;
[JsonIgnore]
@@ -833,7 +837,7 @@ namespace MediaBrowser.Controller.Entities
return CanDelete() && IsAuthorizedToDelete(user, allCollectionFolders);
}
- public bool CanDelete(User user)
+ public virtual bool CanDelete(User user)
{
var allCollectionFolders = LibraryManager.GetUserRootFolder().Children.OfType<Folder>().ToList();
@@ -1602,6 +1606,12 @@ namespace MediaBrowser.Controller.Entities
return false;
}
+ var parent = GetParents().FirstOrDefault() ?? this;
+ if (parent is UserRootFolder or AggregateFolder)
+ {
+ return true;
+ }
+
var allowedTagsPreference = user.GetPreference(PreferenceKind.AllowedTags);
if (allowedTagsPreference.Length != 0 && !allowedTagsPreference.Any(i => allTags.Contains(i, StringComparison.OrdinalIgnoreCase)))
{
@@ -1766,14 +1776,11 @@ namespace MediaBrowser.Controller.Entities
int curLen = current.Length;
if (curLen == 0)
{
- Studios = new[] { name };
+ Studios = [name];
}
else
{
- var newArr = new string[curLen + 1];
- current.CopyTo(newArr, 0);
- newArr[curLen] = name;
- Studios = newArr;
+ Studios = [..current, name];
}
}
}
@@ -1795,9 +1802,7 @@ namespace MediaBrowser.Controller.Entities
var genres = Genres;
if (!genres.Contains(name, StringComparison.OrdinalIgnoreCase))
{
- var list = genres.ToList();
- list.Add(name);
- Genres = list.ToArray();
+ Genres = [..genres, name];
}
}
@@ -1944,14 +1949,15 @@ namespace MediaBrowser.Controller.Entities
return;
}
- // Remove it from the item
- RemoveImage(info);
-
+ // Remove from file system
if (info.IsLocalFile)
{
FileSystem.DeleteFile(info.Path);
}
+ // Remove from item
+ RemoveImage(info);
+
await UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
}
@@ -1967,12 +1973,7 @@ namespace MediaBrowser.Controller.Entities
public void AddImage(ItemImageInfo image)
{
- var current = ImageInfos;
- var currentCount = current.Length;
- var newArr = new ItemImageInfo[currentCount + 1];
- current.CopyTo(newArr, 0);
- newArr[currentCount] = image;
- ImageInfos = newArr;
+ ImageInfos = [..ImageInfos, image];
}
public virtual Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken)
@@ -2496,11 +2497,6 @@ namespace MediaBrowser.Controller.Entities
return new[] { Id };
}
- public virtual List<ExternalUrl> GetRelatedUrls()
- {
- return new List<ExternalUrl>();
- }
-
public virtual double? GetRefreshProgress()
{
return null;
@@ -2548,14 +2544,24 @@ namespace MediaBrowser.Controller.Entities
StringComparison.OrdinalIgnoreCase);
}
- public IReadOnlyList<BaseItem> GetThemeSongs()
+ public IReadOnlyList<BaseItem> GetThemeSongs(User user = null)
+ {
+ return GetThemeSongs(user, Array.Empty<(ItemSortBy, SortOrder)>());
+ }
+
+ public IReadOnlyList<BaseItem> GetThemeSongs(User user, IEnumerable<(ItemSortBy SortBy, SortOrder SortOrder)> orderBy)
+ {
+ return LibraryManager.Sort(GetExtras().Where(e => e.ExtraType == Model.Entities.ExtraType.ThemeSong), user, orderBy).ToArray();
+ }
+
+ public IReadOnlyList<BaseItem> GetThemeVideos(User user = null)
{
- return GetExtras().Where(e => e.ExtraType == Model.Entities.ExtraType.ThemeSong).ToArray();
+ return GetThemeVideos(user, Array.Empty<(ItemSortBy, SortOrder)>());
}
- public IReadOnlyList<BaseItem> GetThemeVideos()
+ public IReadOnlyList<BaseItem> GetThemeVideos(User user, IEnumerable<(ItemSortBy SortBy, SortOrder SortOrder)> orderBy)
{
- return GetExtras().Where(e => e.ExtraType == Model.Entities.ExtraType.ThemeVideo).ToArray();
+ return LibraryManager.Sort(GetExtras().Where(e => e.ExtraType == Model.Entities.ExtraType.ThemeVideo), user, orderBy).ToArray();
}
/// <summary>
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index 676a47c88..4ead477f8 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -316,11 +316,12 @@ namespace MediaBrowser.Controller.Entities
/// <param name="progress">The progress.</param>
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
/// <param name="refreshChildMetadata">if set to <c>true</c> [refresh child metadata].</param>
+ /// <param name="allowRemoveRoot">remove item even this folder is root.</param>
/// <param name="refreshOptions">The refresh options.</param>
/// <param name="directoryService">The directory service.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
+ protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, bool allowRemoveRoot, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs
index 3005bee0a..c56603a3e 100644
--- a/MediaBrowser.Controller/Entities/Extensions.cs
+++ b/MediaBrowser.Controller/Entities/Extensions.cs
@@ -30,15 +30,11 @@ namespace MediaBrowser.Controller.Entities
if (item.RemoteTrailers.Count == 0)
{
- item.RemoteTrailers = new[] { mediaUrl };
+ item.RemoteTrailers = [mediaUrl];
}
else
{
- var oldIds = item.RemoteTrailers;
- var newIds = new MediaUrl[oldIds.Count + 1];
- oldIds.CopyTo(newIds);
- newIds[oldIds.Count] = mediaUrl;
- item.RemoteTrailers = newIds;
+ item.RemoteTrailers = [..item.RemoteTrailers, mediaUrl];
}
}
}
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index a2957cdca..b2e5d7263 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Security;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
@@ -269,11 +270,12 @@ namespace MediaBrowser.Controller.Entities
/// <param name="progress">The progress.</param>
/// <param name="metadataRefreshOptions">The metadata refresh options.</param>
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
+ /// <param name="allowRemoveRoot">remove item even this folder is root.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- public Task ValidateChildren(IProgress<double> progress, MetadataRefreshOptions metadataRefreshOptions, bool recursive = true, CancellationToken cancellationToken = default)
+ public Task ValidateChildren(IProgress<double> progress, MetadataRefreshOptions metadataRefreshOptions, bool recursive = true, bool allowRemoveRoot = false, CancellationToken cancellationToken = default)
{
- return ValidateChildrenInternal(progress, recursive, true, metadataRefreshOptions, metadataRefreshOptions.DirectoryService, cancellationToken);
+ return ValidateChildrenInternal(progress, recursive, true, allowRemoveRoot, metadataRefreshOptions, metadataRefreshOptions.DirectoryService, cancellationToken);
}
private Dictionary<Guid, BaseItem> GetActualChildrenDictionary()
@@ -307,11 +309,12 @@ namespace MediaBrowser.Controller.Entities
/// <param name="progress">The progress.</param>
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
/// <param name="refreshChildMetadata">if set to <c>true</c> [refresh child metadata].</param>
+ /// <param name="allowRemoveRoot">remove item even this folder is root.</param>
/// <param name="refreshOptions">The refresh options.</param>
/// <param name="directoryService">The directory service.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- protected virtual async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
+ protected virtual async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, bool allowRemoveRoot, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
if (recursive)
{
@@ -320,7 +323,7 @@ namespace MediaBrowser.Controller.Entities
try
{
- await ValidateChildrenInternal2(progress, recursive, refreshChildMetadata, refreshOptions, directoryService, cancellationToken).ConfigureAwait(false);
+ await ValidateChildrenInternal2(progress, recursive, refreshChildMetadata, allowRemoveRoot, refreshOptions, directoryService, cancellationToken).ConfigureAwait(false);
}
finally
{
@@ -331,8 +334,13 @@ namespace MediaBrowser.Controller.Entities
}
}
- private static bool IsLibraryFolderAccessible(IDirectoryService directoryService, BaseItem item)
+ private static bool IsLibraryFolderAccessible(IDirectoryService directoryService, BaseItem item, bool checkCollection)
{
+ if (!checkCollection && (item is BoxSet || string.Equals(item.FileNameWithoutExtension, "collections", StringComparison.OrdinalIgnoreCase)))
+ {
+ return true;
+ }
+
// For top parents i.e. Library folders, skip the validation if it's empty or inaccessible
if (item.IsTopParent && !directoryService.IsAccessible(item.ContainingFolderPath))
{
@@ -343,9 +351,9 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- private async Task ValidateChildrenInternal2(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
+ private async Task ValidateChildrenInternal2(IProgress<double> progress, bool recursive, bool refreshChildMetadata, bool allowRemoveRoot, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
- if (!IsLibraryFolderAccessible(directoryService, this))
+ if (!IsLibraryFolderAccessible(directoryService, this, allowRemoveRoot))
{
return;
}
@@ -357,15 +365,23 @@ namespace MediaBrowser.Controller.Entities
if (IsFileProtocol)
{
- IEnumerable<BaseItem> nonCachedChildren;
+ IEnumerable<BaseItem> nonCachedChildren = [];
try
{
nonCachedChildren = GetNonCachedChildren(directoryService);
}
+ catch (IOException ex)
+ {
+ Logger.LogError(ex, "Error retrieving children from file system");
+ }
+ catch (SecurityException ex)
+ {
+ Logger.LogError(ex, "Error retrieving children from file system");
+ }
catch (Exception ex)
{
- Logger.LogError(ex, "Error retrieving children folder");
+ Logger.LogError(ex, "Error retrieving children");
return;
}
@@ -386,7 +402,7 @@ namespace MediaBrowser.Controller.Entities
foreach (var child in nonCachedChildren)
{
- if (!IsLibraryFolderAccessible(directoryService, child))
+ if (!IsLibraryFolderAccessible(directoryService, child, allowRemoveRoot))
{
continue;
}
@@ -414,12 +430,12 @@ namespace MediaBrowser.Controller.Entities
validChildren.Add(child);
}
+ // That's all the new and changed ones - now see if any have been removed and need cleanup
+ var itemsRemoved = currentChildren.Values.Except(validChildren).ToList();
+ var shouldRemove = !IsRoot || allowRemoveRoot;
// If it's an AggregateFolder, don't remove
- if (!IsRoot && currentChildren.Count != validChildren.Count)
+ if (shouldRemove && itemsRemoved.Count > 0)
{
- // That's all the new and changed ones - now see if there are any that are missing
- var itemsRemoved = currentChildren.Values.Except(validChildren).ToList();
-
foreach (var item in itemsRemoved)
{
if (item.IsFileProtocol)
@@ -460,15 +476,7 @@ namespace MediaBrowser.Controller.Entities
progress.Report(percent);
- // TODO: this is sometimes being called after the refresh has completed.
- try
- {
- ProviderManager.OnRefreshProgress(folder, percent);
- }
- catch (InvalidOperationException e)
- {
- Logger.LogError(e, "Error refreshing folder");
- }
+ ProviderManager.OnRefreshProgress(folder, percent);
});
if (validChildrenNeedGeneration)
@@ -500,15 +508,7 @@ namespace MediaBrowser.Controller.Entities
if (recursive)
{
- // TODO: this is sometimes being called after the refresh has completed.
- try
- {
- ProviderManager.OnRefreshProgress(folder, percent);
- }
- catch (InvalidOperationException e)
- {
- Logger.LogError(e, "Error refreshing folder");
- }
+ ProviderManager.OnRefreshProgress(folder, percent);
}
});
@@ -578,7 +578,7 @@ namespace MediaBrowser.Controller.Entities
private Task ValidateSubFolders(IList<Folder> children, IDirectoryService directoryService, IProgress<double> progress, CancellationToken cancellationToken)
{
return RunTasks(
- (folder, innerProgress) => folder.ValidateChildrenInternal(innerProgress, true, false, null, directoryService, cancellationToken),
+ (folder, innerProgress) => folder.ValidateChildrenInternal(innerProgress, true, false, false, null, directoryService, cancellationToken),
children,
progress,
cancellationToken);
@@ -603,7 +603,7 @@ namespace MediaBrowser.Controller.Entities
}
var fanoutConcurrency = ConfigurationManager.Configuration.LibraryScanFanoutConcurrency;
- var parallelism = fanoutConcurrency > 0 ? fanoutConcurrency : 2 * Environment.ProcessorCount;
+ var parallelism = fanoutConcurrency > 0 ? fanoutConcurrency : Environment.ProcessorCount;
var actionBlock = new ActionBlock<int>(
async i =>
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index 555dd050c..1461a3680 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -51,6 +51,7 @@ namespace MediaBrowser.Controller.Entities
TrailerTypes = Array.Empty<TrailerType>();
VideoTypes = Array.Empty<VideoType>();
Years = Array.Empty<int>();
+ SkipDeserialization = false;
}
public InternalItemsQuery(User? user)
@@ -358,6 +359,8 @@ namespace MediaBrowser.Controller.Entities
public string? SeriesTimerId { get; set; }
+ public bool SkipDeserialization { get; set; }
+
public void SetUser(User user)
{
MaxParentalRating = user.MaxParentalAgeRating;
diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs
index 81f6248fa..710b05e7f 100644
--- a/MediaBrowser.Controller/Entities/Movies/Movie.cs
+++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs
@@ -45,9 +45,6 @@ namespace MediaBrowser.Controller.Entities.Movies
set => TmdbCollectionName = value;
}
- [JsonIgnore]
- public override bool StopRefreshIfLocalMetadataFound => false;
-
public override double GetDefaultPrimaryImageAspectRatio()
{
// hack for tv plugins
@@ -124,23 +121,5 @@ namespace MediaBrowser.Controller.Entities.Movies
return hasChanges;
}
-
- /// <inheritdoc />
- public override List<ExternalUrl> GetRelatedUrls()
- {
- var list = base.GetRelatedUrls();
-
- var imdbId = this.GetProviderId(MetadataProvider.Imdb);
- if (!string.IsNullOrEmpty(imdbId))
- {
- list.Add(new ExternalUrl
- {
- Name = "Trakt",
- Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/movies/{0}", imdbId)
- });
- }
-
- return list;
- }
}
}
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index 37e241414..5c54f014c 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -344,22 +344,5 @@ namespace MediaBrowser.Controller.Entities.TV
return hasChanges;
}
-
- public override List<ExternalUrl> GetRelatedUrls()
- {
- var list = base.GetRelatedUrls();
-
- var imdbId = this.GetProviderId(MetadataProvider.Imdb);
- if (!string.IsNullOrEmpty(imdbId))
- {
- list.Add(new ExternalUrl
- {
- Name = "Trakt",
- Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/episodes/{0}", imdbId)
- });
- }
-
- return list;
- }
}
}
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs
index c29cefc15..083f12746 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -159,7 +159,7 @@ namespace MediaBrowser.Controller.Entities.TV
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
- var items = GetEpisodes(user, query.DtoOptions).Where(filter);
+ var items = GetEpisodes(user, query.DtoOptions, true).Where(filter);
return PostFilterAndSort(items, query, false);
}
@@ -169,30 +169,31 @@ namespace MediaBrowser.Controller.Entities.TV
/// </summary>
/// <param name="user">The user.</param>
/// <param name="options">The options to use.</param>
+ /// <param name="shouldIncludeMissingEpisodes">If missing episodes should be included.</param>
/// <returns>Set of episodes.</returns>
- public List<BaseItem> GetEpisodes(User user, DtoOptions options)
+ public List<BaseItem> GetEpisodes(User user, DtoOptions options, bool shouldIncludeMissingEpisodes)
{
- return GetEpisodes(Series, user, options);
+ return GetEpisodes(Series, user, options, shouldIncludeMissingEpisodes);
}
- public List<BaseItem> GetEpisodes(Series series, User user, DtoOptions options)
+ public List<BaseItem> GetEpisodes(Series series, User user, DtoOptions options, bool shouldIncludeMissingEpisodes)
{
- return GetEpisodes(series, user, null, options);
+ return GetEpisodes(series, user, null, options, shouldIncludeMissingEpisodes);
}
- public List<BaseItem> GetEpisodes(Series series, User user, IEnumerable<Episode> allSeriesEpisodes, DtoOptions options)
+ public List<BaseItem> GetEpisodes(Series series, User user, IEnumerable<Episode> allSeriesEpisodes, DtoOptions options, bool shouldIncludeMissingEpisodes)
{
- return series.GetSeasonEpisodes(this, user, allSeriesEpisodes, options);
+ return series.GetSeasonEpisodes(this, user, allSeriesEpisodes, options, shouldIncludeMissingEpisodes);
}
public List<BaseItem> GetEpisodes()
{
- return Series.GetSeasonEpisodes(this, null, null, new DtoOptions(true));
+ return Series.GetSeasonEpisodes(this, null, null, new DtoOptions(true), true);
}
public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query)
{
- return GetEpisodes(user, new DtoOptions(true));
+ return GetEpisodes(user, new DtoOptions(true), true);
}
protected override bool GetBlockUnratedValue(User user)
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index a49c1609d..a324f79ef 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -28,7 +28,6 @@ namespace MediaBrowser.Controller.Entities.TV
public Series()
{
AirDays = Array.Empty<DayOfWeek>();
- SeasonNames = new Dictionary<int, string>();
}
public DayOfWeek[] AirDays { get; set; }
@@ -36,9 +35,6 @@ namespace MediaBrowser.Controller.Entities.TV
public string AirTime { get; set; }
[JsonIgnore]
- public Dictionary<int, string> SeasonNames { get; set; }
-
- [JsonIgnore]
public override bool SupportsAddingToPlaylist => true;
[JsonIgnore]
@@ -73,9 +69,6 @@ namespace MediaBrowser.Controller.Entities.TV
/// <value>The status.</value>
public SeriesStatus? Status { get; set; }
- [JsonIgnore]
- public override bool StopRefreshIfLocalMetadataFound => false;
-
public override double GetDefaultPrimaryImageAspectRatio()
{
double value = 2;
@@ -257,7 +250,7 @@ namespace MediaBrowser.Controller.Entities.TV
return LibraryManager.GetItemsResult(query);
}
- public IEnumerable<BaseItem> GetEpisodes(User user, DtoOptions options)
+ public IEnumerable<BaseItem> GetEpisodes(User user, DtoOptions options, bool shouldIncludeMissingEpisodes)
{
var seriesKey = GetUniqueSeriesKey(this);
@@ -267,10 +260,10 @@ namespace MediaBrowser.Controller.Entities.TV
SeriesPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] { BaseItemKind.Episode, BaseItemKind.Season },
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) },
- DtoOptions = options
+ DtoOptions = options,
};
- if (user is null || !user.DisplayMissingEpisodes)
+ if (!shouldIncludeMissingEpisodes)
{
query.IsMissing = false;
}
@@ -280,7 +273,7 @@ namespace MediaBrowser.Controller.Entities.TV
var allSeriesEpisodes = allItems.OfType<Episode>().ToList();
var allEpisodes = allItems.OfType<Season>()
- .SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes, options))
+ .SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes, options, shouldIncludeMissingEpisodes))
.Reverse();
// Specials could appear twice based on above - once in season 0, once in the aired season
@@ -292,8 +285,7 @@ namespace MediaBrowser.Controller.Entities.TV
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
{
- // Refresh bottom up, children first, then the boxset
- // By then hopefully the movies within will have Tmdb collection values
+ // Refresh bottom up, seasons and episodes first, then the series
var items = GetRecursiveChildren();
var totalItems = items.Count;
@@ -356,7 +348,7 @@ namespace MediaBrowser.Controller.Entities.TV
await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
}
- public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, DtoOptions options)
+ public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, DtoOptions options, bool shouldIncludeMissingEpisodes)
{
var queryFromSeries = ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons;
@@ -373,24 +365,22 @@ namespace MediaBrowser.Controller.Entities.TV
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) },
DtoOptions = options
};
- if (user is not null)
+
+ if (!shouldIncludeMissingEpisodes)
{
- if (!user.DisplayMissingEpisodes)
- {
- query.IsMissing = false;
- }
+ query.IsMissing = false;
}
var allItems = LibraryManager.GetItemList(query);
- return GetSeasonEpisodes(parentSeason, user, allItems, options);
+ return GetSeasonEpisodes(parentSeason, user, allItems, options, shouldIncludeMissingEpisodes);
}
- public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, IEnumerable<BaseItem> allSeriesEpisodes, DtoOptions options)
+ public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, IEnumerable<BaseItem> allSeriesEpisodes, DtoOptions options, bool shouldIncludeMissingEpisodes)
{
if (allSeriesEpisodes is null)
{
- return GetSeasonEpisodes(parentSeason, user, options);
+ return GetSeasonEpisodes(parentSeason, user, options, shouldIncludeMissingEpisodes);
}
var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);
@@ -499,22 +489,5 @@ namespace MediaBrowser.Controller.Entities.TV
return hasChanges;
}
-
- public override List<ExternalUrl> GetRelatedUrls()
- {
- var list = base.GetRelatedUrls();
-
- var imdbId = this.GetProviderId(MetadataProvider.Imdb);
- if (!string.IsNullOrEmpty(imdbId))
- {
- list.Add(new ExternalUrl
- {
- Name = "Trakt",
- Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/shows/{0}", imdbId)
- });
- }
-
- return list;
- }
}
}
diff --git a/MediaBrowser.Controller/Entities/TagExtensions.cs b/MediaBrowser.Controller/Entities/TagExtensions.cs
index ec3eb0f70..c1e4d1db2 100644
--- a/MediaBrowser.Controller/Entities/TagExtensions.cs
+++ b/MediaBrowser.Controller/Entities/TagExtensions.cs
@@ -21,11 +21,11 @@ namespace MediaBrowser.Controller.Entities
{
if (current.Length == 0)
{
- item.Tags = new[] { name };
+ item.Tags = [name];
}
else
{
- item.Tags = current.Concat(new[] { name }).ToArray();
+ item.Tags = [..current, name];
}
}
}
diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs
index 1c558d419..939709215 100644
--- a/MediaBrowser.Controller/Entities/Trailer.cs
+++ b/MediaBrowser.Controller/Entities/Trailer.cs
@@ -23,9 +23,6 @@ namespace MediaBrowser.Controller.Entities
TrailerTypes = Array.Empty<TrailerType>();
}
- [JsonIgnore]
- public override bool StopRefreshIfLocalMetadataFound => false;
-
public TrailerType[] TrailerTypes { get; set; }
public override double GetDefaultPrimaryImageAspectRatio()
@@ -83,22 +80,5 @@ namespace MediaBrowser.Controller.Entities
return hasChanges;
}
-
- public override List<ExternalUrl> GetRelatedUrls()
- {
- var list = base.GetRelatedUrls();
-
- var imdbId = this.GetProviderId(MetadataProvider.Imdb);
- if (!string.IsNullOrEmpty(imdbId))
- {
- list.Add(new ExternalUrl
- {
- Name = "Trakt",
- Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/movies/{0}", imdbId)
- });
- }
-
- return list;
- }
}
}
diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs
index 69743b926..fc8a29763 100644
--- a/MediaBrowser.Controller/Entities/UserRootFolder.cs
+++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs
@@ -117,11 +117,11 @@ namespace MediaBrowser.Controller.Entities
return base.GetNonCachedChildren(directoryService);
}
- protected override async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
+ protected override async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, bool allowRemoveRoot, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
ClearCache();
- await base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, refreshOptions, directoryService, cancellationToken)
+ await base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, allowRemoveRoot, refreshOptions, directoryService, cancellationToken)
.ConfigureAwait(false);
ClearCache();
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index c93488a85..e4fb340f7 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -6,10 +6,12 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
+using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Querying;
@@ -180,7 +182,7 @@ namespace MediaBrowser.Controller.Entities
return _originalFolderViewTypes.Contains(viewType);
}
- protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService, System.Threading.CancellationToken cancellationToken)
+ protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, bool allowRemoveRoot, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 4af000557..3a1d0c070 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -744,7 +744,7 @@ namespace MediaBrowser.Controller.Entities
{
var filterValue = query.HasThemeSong.Value;
- var themeCount = item.GetThemeSongs().Count;
+ var themeCount = item.GetThemeSongs(user).Count;
var ok = filterValue ? themeCount > 0 : themeCount == 0;
if (!ok)
@@ -757,7 +757,7 @@ namespace MediaBrowser.Controller.Entities
{
var filterValue = query.HasThemeVideo.Value;
- var themeCount = item.GetThemeVideos().Count;
+ var themeCount = item.GetThemeVideos(user).Count;
var ok = filterValue ? themeCount > 0 : themeCount == 0;
if (!ok)