mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-07-10 16:23:06 +01:00
Merge branch 'master' into segment-deletion
This commit is contained in:
@@ -35,7 +35,7 @@ namespace MediaBrowser.Controller.BaseItemManager
|
||||
public SemaphoreSlim MetadataRefreshThrottler { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsMetadataFetcherEnabled(BaseItem baseItem, LibraryOptions libraryOptions, string name)
|
||||
public bool IsMetadataFetcherEnabled(BaseItem baseItem, TypeOptions? libraryTypeOptions, string name)
|
||||
{
|
||||
if (baseItem is Channel)
|
||||
{
|
||||
@@ -49,19 +49,18 @@ namespace MediaBrowser.Controller.BaseItemManager
|
||||
return !baseItem.EnableMediaSourceDisplay;
|
||||
}
|
||||
|
||||
var typeOptions = libraryOptions.GetTypeOptions(baseItem.GetType().Name);
|
||||
if (typeOptions != null)
|
||||
if (libraryTypeOptions is not null)
|
||||
{
|
||||
return typeOptions.MetadataFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
return libraryTypeOptions.MetadataFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
var itemConfig = _serverConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, baseItem.GetType().Name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
return itemConfig == null || !itemConfig.DisabledMetadataFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
return itemConfig is null || !itemConfig.DisabledMetadataFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsImageFetcherEnabled(BaseItem baseItem, LibraryOptions libraryOptions, string name)
|
||||
public bool IsImageFetcherEnabled(BaseItem baseItem, TypeOptions? libraryTypeOptions, string name)
|
||||
{
|
||||
if (baseItem is Channel)
|
||||
{
|
||||
@@ -75,15 +74,14 @@ namespace MediaBrowser.Controller.BaseItemManager
|
||||
return !baseItem.EnableMediaSourceDisplay;
|
||||
}
|
||||
|
||||
var typeOptions = libraryOptions.GetTypeOptions(baseItem.GetType().Name);
|
||||
if (typeOptions != null)
|
||||
if (libraryTypeOptions is not null)
|
||||
{
|
||||
return typeOptions.ImageFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
return libraryTypeOptions.ImageFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
var itemConfig = _serverConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, baseItem.GetType().Name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
return itemConfig == null || !itemConfig.DisabledImageFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
return itemConfig is null || !itemConfig.DisabledImageFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -18,18 +18,18 @@ namespace MediaBrowser.Controller.BaseItemManager
|
||||
/// Is metadata fetcher enabled.
|
||||
/// </summary>
|
||||
/// <param name="baseItem">The base item.</param>
|
||||
/// <param name="libraryOptions">The library options.</param>
|
||||
/// <param name="libraryTypeOptions">The type options for <c>baseItem</c> from the library (if defined).</param>
|
||||
/// <param name="name">The metadata fetcher name.</param>
|
||||
/// <returns><c>true</c> if metadata fetcher is enabled, else false.</returns>
|
||||
bool IsMetadataFetcherEnabled(BaseItem baseItem, LibraryOptions libraryOptions, string name);
|
||||
bool IsMetadataFetcherEnabled(BaseItem baseItem, TypeOptions? libraryTypeOptions, string name);
|
||||
|
||||
/// <summary>
|
||||
/// Is image fetcher enabled.
|
||||
/// </summary>
|
||||
/// <param name="baseItem">The base item.</param>
|
||||
/// <param name="libraryOptions">The library options.</param>
|
||||
/// <param name="libraryTypeOptions">The type options for <c>baseItem</c> from the library (if defined).</param>
|
||||
/// <param name="name">The image fetcher name.</param>
|
||||
/// <returns><c>true</c> if image fetcher is enabled, else false.</returns>
|
||||
bool IsImageFetcherEnabled(BaseItem baseItem, LibraryOptions libraryOptions, string name);
|
||||
bool IsImageFetcherEnabled(BaseItem baseItem, TypeOptions? libraryTypeOptions, string name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,6 @@ namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public interface IChannelManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the parts.
|
||||
/// </summary>
|
||||
/// <param name="channels">The channels.</param>
|
||||
void AddParts(IEnumerable<IChannel> channels);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel features.
|
||||
/// </summary>
|
||||
@@ -52,14 +46,14 @@ namespace MediaBrowser.Controller.Channels
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>The channels.</returns>
|
||||
QueryResult<Channel> GetChannelsInternal(ChannelQuery query);
|
||||
Task<QueryResult<Channel>> GetChannelsInternalAsync(ChannelQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channels.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>The channels.</returns>
|
||||
QueryResult<BaseItemDto> GetChannels(ChannelQuery query);
|
||||
Task<QueryResult<BaseItemDto>> GetChannelsAsync(ChannelQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the latest channel items.
|
||||
|
||||
@@ -42,8 +42,6 @@ namespace MediaBrowser.Controller.Drawing
|
||||
|
||||
public IReadOnlyCollection<ImageFormat> SupportedOutputFormats { get; set; }
|
||||
|
||||
public bool AddPlayedIndicator { get; set; }
|
||||
|
||||
public int? UnplayedCount { get; set; }
|
||||
|
||||
public int? Blur { get; set; }
|
||||
@@ -111,7 +109,6 @@ namespace MediaBrowser.Controller.Drawing
|
||||
{
|
||||
return (Quality >= 90) &&
|
||||
IsFormatSupported(originalImagePath) &&
|
||||
!AddPlayedIndicator &&
|
||||
PercentPlayed.Equals(0) &&
|
||||
!UnplayedCount.HasValue &&
|
||||
!Blur.HasValue &&
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.Drawing
|
||||
{
|
||||
var imageInfo = item.GetImageInfo(imageType, imageIndex);
|
||||
|
||||
if (imageInfo == null)
|
||||
if (imageInfo is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#nullable disable
|
||||
#pragma warning disable CA1002
|
||||
|
||||
using System.Collections.Generic;
|
||||
@@ -28,7 +27,7 @@ namespace MediaBrowser.Controller.Dto
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="owner">The owner.</param>
|
||||
/// <returns>BaseItemDto.</returns>
|
||||
BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null);
|
||||
BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User? user = null, BaseItem? owner = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base item dtos.
|
||||
@@ -38,7 +37,7 @@ namespace MediaBrowser.Controller.Dto
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="owner">The owner.</param>
|
||||
/// <returns>The <see cref="IReadOnlyList{T}"/> of <see cref="BaseItemDto"/>.</returns>
|
||||
IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null);
|
||||
IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User? user = null, BaseItem? owner = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item by name dto.
|
||||
@@ -48,6 +47,6 @@ namespace MediaBrowser.Controller.Dto
|
||||
/// <param name="taggedItems">The list of tagged items.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>The item dto.</returns>
|
||||
BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, User user = null);
|
||||
BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem>? taggedItems, User? user = null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,14 +67,14 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
lock (_childIdsLock)
|
||||
{
|
||||
if (_childrenIds == null || _childrenIds.Length == 0)
|
||||
if (_childrenIds is null || _childrenIds.Length == 0)
|
||||
{
|
||||
var list = base.LoadChildren();
|
||||
_childrenIds = list.Select(i => i.Id).ToArray();
|
||||
return list;
|
||||
}
|
||||
|
||||
return _childrenIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList();
|
||||
return _childrenIds.Select(LibraryManager.GetItemById).Where(i => i is not null).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var path = ContainingFolderPath;
|
||||
|
||||
var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService)
|
||||
var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, LibraryManager)
|
||||
{
|
||||
FileInfo = FileSystem.GetDirectoryInfo(path)
|
||||
};
|
||||
|
||||
@@ -81,8 +81,8 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
/// <returns>System.String.</returns>
|
||||
protected override string CreateSortName()
|
||||
{
|
||||
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ", CultureInfo.InvariantCulture) : string.Empty)
|
||||
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ", CultureInfo.InvariantCulture) : string.Empty) + Name;
|
||||
return (ParentIndexNumber is not null ? ParentIndexNumber.Value.ToString("0000 - ", CultureInfo.InvariantCulture) : string.Empty)
|
||||
+ (IndexNumber is not null ? IndexNumber.Value.ToString("0000 - ", CultureInfo.InvariantCulture) : string.Empty) + Name;
|
||||
}
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
|
||||
var artist = GetMusicArtist(new DtoOptions(false));
|
||||
|
||||
if (artist != null)
|
||||
if (artist is not null)
|
||||
{
|
||||
id.ArtistProviderIds = artist.ProviderIds;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// The supported image extensions.
|
||||
/// </summary>
|
||||
public static readonly string[] SupportedImageExtensions
|
||||
= new[] { ".png", ".jpg", ".jpeg", ".tbn", ".gif" };
|
||||
= new[] { ".png", ".jpg", ".jpeg", ".webp", ".tbn", ".gif" };
|
||||
|
||||
private static readonly List<string> _supportedExtensions = new List<string>(SupportedImageExtensions)
|
||||
{
|
||||
@@ -56,6 +56,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
".srt",
|
||||
".vtt",
|
||||
".sub",
|
||||
".sup",
|
||||
".idx",
|
||||
".txt",
|
||||
".edl",
|
||||
@@ -127,6 +128,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
[JsonIgnore]
|
||||
public string Album { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LUFS value.
|
||||
/// </summary>
|
||||
/// <value>The LUFS Value.</value>
|
||||
[JsonIgnore]
|
||||
public float LUFS { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the channel identifier.
|
||||
/// </summary>
|
||||
@@ -494,7 +502,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_sortName == null)
|
||||
if (_sortName is null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ForcedSortName))
|
||||
{
|
||||
@@ -553,7 +561,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
public string OfficialRating { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public int InheritedParentalRatingValue { get; set; }
|
||||
public int? InheritedParentalRatingValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the critic rating.
|
||||
@@ -658,7 +666,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
|
||||
var parent = DisplayParent;
|
||||
if (parent != null)
|
||||
if (parent is not null)
|
||||
{
|
||||
return parent.OfficialRatingForComparison;
|
||||
}
|
||||
@@ -679,7 +687,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
|
||||
var parent = DisplayParent;
|
||||
if (parent != null)
|
||||
if (parent is not null)
|
||||
{
|
||||
return parent.CustomRatingForComparison;
|
||||
}
|
||||
@@ -800,16 +808,14 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
return allowed.Contains(ChannelId);
|
||||
}
|
||||
else
|
||||
{
|
||||
var collectionFolders = LibraryManager.GetCollectionFolders(this, allCollectionFolders);
|
||||
|
||||
foreach (var folder in collectionFolders)
|
||||
var collectionFolders = LibraryManager.GetCollectionFolders(this, allCollectionFolders);
|
||||
|
||||
foreach (var folder in collectionFolders)
|
||||
{
|
||||
if (allowed.Contains(folder.Id))
|
||||
{
|
||||
if (allowed.Contains(folder.Id))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -880,7 +886,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <returns>System.String.</returns>
|
||||
protected virtual string CreateSortName()
|
||||
{
|
||||
if (Name == null)
|
||||
if (Name is null)
|
||||
{
|
||||
return null; // some items may not have name filled in properly
|
||||
}
|
||||
@@ -892,16 +898,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var sortable = Name.Trim().ToLowerInvariant();
|
||||
|
||||
foreach (var removeChar in ConfigurationManager.Configuration.SortRemoveCharacters)
|
||||
{
|
||||
sortable = sortable.Replace(removeChar, string.Empty, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
foreach (var replaceChar in ConfigurationManager.Configuration.SortReplaceCharacters)
|
||||
{
|
||||
sortable = sortable.Replace(replaceChar, " ", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
foreach (var search in ConfigurationManager.Configuration.SortRemoveWords)
|
||||
{
|
||||
// Remove from beginning if a space follows
|
||||
@@ -920,12 +916,22 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var removeChar in ConfigurationManager.Configuration.SortRemoveCharacters)
|
||||
{
|
||||
sortable = sortable.Replace(removeChar, string.Empty, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
foreach (var replaceChar in ConfigurationManager.Configuration.SortReplaceCharacters)
|
||||
{
|
||||
sortable = sortable.Replace(replaceChar, " ", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
return ModifySortChunks(sortable);
|
||||
}
|
||||
|
||||
internal static string ModifySortChunks(string name)
|
||||
internal static string ModifySortChunks(ReadOnlySpan<char> name)
|
||||
{
|
||||
void AppendChunk(StringBuilder builder, bool isDigitChunk, ReadOnlySpan<char> chunk)
|
||||
static void AppendChunk(StringBuilder builder, bool isDigitChunk, ReadOnlySpan<char> chunk)
|
||||
{
|
||||
if (isDigitChunk && chunk.Length < 10)
|
||||
{
|
||||
@@ -935,7 +941,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
builder.Append(chunk);
|
||||
}
|
||||
|
||||
if (name.Length == 0)
|
||||
if (name.IsEmpty)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
@@ -949,13 +955,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
var isDigit = char.IsDigit(name[i]);
|
||||
if (isDigit != isDigitChunk)
|
||||
{
|
||||
AppendChunk(builder, isDigitChunk, name.AsSpan(chunkStart, i - chunkStart));
|
||||
AppendChunk(builder, isDigitChunk, name.Slice(chunkStart, i - chunkStart));
|
||||
chunkStart = i;
|
||||
isDigitChunk = isDigit;
|
||||
}
|
||||
}
|
||||
|
||||
AppendChunk(builder, isDigitChunk, name.AsSpan(chunkStart));
|
||||
AppendChunk(builder, isDigitChunk, name.Slice(chunkStart));
|
||||
|
||||
// logger.LogDebug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString());
|
||||
return builder.ToString().RemoveDiacritics();
|
||||
@@ -976,7 +982,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var parent = GetParent();
|
||||
|
||||
while (parent != null)
|
||||
while (parent is not null)
|
||||
{
|
||||
yield return parent;
|
||||
|
||||
@@ -1073,7 +1079,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var stream = i.VideoStream;
|
||||
|
||||
return stream == null || stream.Width == null ? 0 : stream.Width.Value;
|
||||
return stream is null || stream.Width is null ? 0 : stream.Width.Value;
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
@@ -1114,7 +1120,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
|
||||
var video = item as Video;
|
||||
if (video != null)
|
||||
if (video is not null)
|
||||
{
|
||||
info.IsoType = video.IsoType;
|
||||
info.VideoType = video.VideoType;
|
||||
@@ -1153,7 +1159,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
info.SupportsDirectStream = MediaSourceManager.SupportsDirectStream(info.Path, info.Protocol);
|
||||
}
|
||||
|
||||
if (video != null && video.VideoType != VideoType.VideoFile)
|
||||
if (video is not null && video.VideoType != VideoType.VideoFile)
|
||||
{
|
||||
info.SupportsDirectStream = false;
|
||||
}
|
||||
@@ -1330,7 +1336,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public void SetParent(Folder parent)
|
||||
{
|
||||
ParentId = parent == null ? Guid.Empty : parent.Id;
|
||||
ParentId = parent is null ? Guid.Empty : parent.Id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1533,12 +1539,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
|
||||
var maxAllowedRating = user.MaxParentalAgeRating;
|
||||
|
||||
if (maxAllowedRating == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var rating = CustomRatingForComparison;
|
||||
|
||||
if (string.IsNullOrEmpty(rating))
|
||||
@@ -1548,12 +1548,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
if (string.IsNullOrEmpty(rating))
|
||||
{
|
||||
Logger.LogDebug("{0} has no parental rating set.", Name);
|
||||
return !GetBlockUnratedValue(user);
|
||||
}
|
||||
|
||||
var value = LocalizationManager.GetRatingLevel(rating);
|
||||
|
||||
// Could not determine the integer value
|
||||
// Could not determine rating level
|
||||
if (!value.HasValue)
|
||||
{
|
||||
var isAllowed = !GetBlockUnratedValue(user);
|
||||
@@ -1566,7 +1567,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return isAllowed;
|
||||
}
|
||||
|
||||
return value.Value <= maxAllowedRating.Value;
|
||||
return !maxAllowedRating.HasValue || value.Value <= maxAllowedRating.Value;
|
||||
}
|
||||
|
||||
public int? GetInheritedParentalRatingValue()
|
||||
@@ -1606,6 +1607,12 @@ namespace MediaBrowser.Controller.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
var allowedTagsPreference = user.GetPreference(PreferenceKind.AllowedTags);
|
||||
if (allowedTagsPreference.Any() && !allowedTagsPreference.Any(i => Tags.Contains(i, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1620,10 +1627,10 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the block unrated value.
|
||||
/// Gets a bool indicating if access to the unrated item is blocked or not.
|
||||
/// </summary>
|
||||
/// <param name="user">The configuration.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
||||
/// <returns><c>true</c> if blocked, <c>false</c> otherwise.</returns>
|
||||
protected virtual bool GetBlockUnratedValue(User user)
|
||||
{
|
||||
// Don't block plain folders that are unrated. Let the media underneath get blocked
|
||||
@@ -1692,7 +1699,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var itemById = LibraryManager.GetItemById(info.ItemId.Value);
|
||||
|
||||
if (itemById != null)
|
||||
if (itemById is not null)
|
||||
{
|
||||
return itemById;
|
||||
}
|
||||
@@ -1701,7 +1708,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
var item = FindLinkedChild(info);
|
||||
|
||||
// If still null, log
|
||||
if (item == null)
|
||||
if (item is null)
|
||||
{
|
||||
// Don't keep searching over and over
|
||||
info.ItemId = Guid.Empty;
|
||||
@@ -1725,7 +1732,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var itemByPath = LibraryManager.FindByPath(path, null);
|
||||
|
||||
if (itemByPath == null)
|
||||
if (itemByPath is null)
|
||||
{
|
||||
Logger.LogWarning("Unable to find linked item at path {0}", info.Path);
|
||||
}
|
||||
@@ -1737,7 +1744,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var item = LibraryManager.GetItemById(info.LibraryItemId);
|
||||
|
||||
if (item == null)
|
||||
if (item is null)
|
||||
{
|
||||
Logger.LogWarning("Unable to find linked item at path {0}", info.Path);
|
||||
}
|
||||
@@ -1755,10 +1762,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <exception cref="ArgumentNullException">Throws if name is null.</exception>
|
||||
public void AddStudio(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
ArgumentException.ThrowIfNullOrEmpty(name);
|
||||
|
||||
var current = Studios;
|
||||
|
||||
@@ -1791,10 +1795,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <exception cref="ArgumentNullException">Throwns if name is null.</exception>
|
||||
public void AddGenre(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
ArgumentException.ThrowIfNullOrEmpty(name);
|
||||
|
||||
var genres = Genres;
|
||||
if (!genres.Contains(name, StringComparison.OrdinalIgnoreCase))
|
||||
@@ -1892,7 +1893,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var existingImage = GetImageInfo(image.Type, index);
|
||||
|
||||
if (existingImage == null)
|
||||
if (existingImage is null)
|
||||
{
|
||||
AddImage(image);
|
||||
}
|
||||
@@ -1915,7 +1916,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var image = GetImageInfo(type, index);
|
||||
|
||||
if (image == null)
|
||||
if (image is null)
|
||||
{
|
||||
AddImage(GetImageInfo(file, type));
|
||||
}
|
||||
@@ -1942,7 +1943,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var info = GetImageInfo(type, index);
|
||||
|
||||
if (info == null)
|
||||
if (info is null)
|
||||
{
|
||||
// Nothing to do
|
||||
return;
|
||||
@@ -2035,7 +2036,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var chapter = ItemRepository.GetChapter(this, imageIndex);
|
||||
|
||||
if (chapter == null)
|
||||
if (chapter is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -2060,7 +2061,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var artist = FindParent<MusicArtist>();
|
||||
|
||||
if (artist != null)
|
||||
if (artist is not null)
|
||||
{
|
||||
return artist.GetImages(imageType).ElementAtOrDefault(imageIndex);
|
||||
}
|
||||
@@ -2147,7 +2148,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
foreach (var newImage in images)
|
||||
{
|
||||
if (newImage == null)
|
||||
if (newImage is null)
|
||||
{
|
||||
throw new ArgumentException("null image found in list");
|
||||
}
|
||||
@@ -2155,7 +2156,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
var existing = existingImages
|
||||
.Find(i => string.Equals(i.Path, newImage.FullName, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (existing == null)
|
||||
if (existing is null)
|
||||
{
|
||||
newImageList.Add(newImage);
|
||||
}
|
||||
@@ -2241,7 +2242,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
var info1 = GetImageInfo(type, index1);
|
||||
var info2 = GetImageInfo(type, index2);
|
||||
|
||||
if (info1 == null || info2 == null)
|
||||
if (info1 is null || info2 is null)
|
||||
{
|
||||
// Nothing to do
|
||||
return Task.CompletedTask;
|
||||
@@ -2274,14 +2275,14 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var userdata = UserDataManager.GetUserData(user, this);
|
||||
|
||||
return userdata != null && userdata.Played;
|
||||
return userdata is not null && userdata.Played;
|
||||
}
|
||||
|
||||
public bool IsFavoriteOrLiked(User user)
|
||||
{
|
||||
var userdata = UserDataManager.GetUserData(user, this);
|
||||
|
||||
return userdata != null && (userdata.IsFavorite || (userdata.Likes ?? false));
|
||||
return userdata is not null && (userdata.IsFavorite || (userdata.Likes ?? false));
|
||||
}
|
||||
|
||||
public virtual bool IsUnplayed(User user)
|
||||
@@ -2290,7 +2291,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var userdata = UserDataManager.GetUserData(user, this);
|
||||
|
||||
return userdata == null || !userdata.Played;
|
||||
return userdata is null || !userdata.Played;
|
||||
}
|
||||
|
||||
ItemLookupInfo IHasLookupInfo<ItemLookupInfo>.GetLookupInfo()
|
||||
@@ -2445,18 +2446,23 @@ namespace MediaBrowser.Controller.Entities
|
||||
// Try to retrieve it from the db. If we don't find it, use the resolved version
|
||||
var video = LibraryManager.GetItemById(id) as Video;
|
||||
|
||||
if (video == null)
|
||||
if (video is null)
|
||||
{
|
||||
video = LibraryManager.ResolvePath(FileSystem.GetFileSystemInfo(path)) as Video;
|
||||
|
||||
newOptions.ForceSave = true;
|
||||
}
|
||||
|
||||
if (video == null)
|
||||
if (video is null)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
if (video.OwnerId.Equals(default))
|
||||
{
|
||||
video.OwnerId = this.Id;
|
||||
}
|
||||
|
||||
return RefreshMetadataForOwnedItem(video, copyTitleMetadata, newOptions, cancellationToken);
|
||||
}
|
||||
|
||||
@@ -2511,7 +2517,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var item = this;
|
||||
|
||||
var inheritedParentalRatingValue = item.GetInheritedParentalRatingValue() ?? 0;
|
||||
var inheritedParentalRatingValue = item.GetInheritedParentalRatingValue() ?? null;
|
||||
if (inheritedParentalRatingValue != item.InheritedParentalRatingValue)
|
||||
{
|
||||
item.InheritedParentalRatingValue = inheritedParentalRatingValue;
|
||||
@@ -2565,7 +2571,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
return ExtraIds
|
||||
.Select(LibraryManager.GetItemById)
|
||||
.Where(i => i != null)
|
||||
.Where(i => i is not null)
|
||||
.OrderBy(i => i.SortName);
|
||||
}
|
||||
|
||||
@@ -2578,7 +2584,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
return ExtraIds
|
||||
.Select(LibraryManager.GetItemById)
|
||||
.Where(i => i != null)
|
||||
.Where(i => i is not null)
|
||||
.Where(i => i.ExtraType.HasValue && extraTypes.Contains(i.ExtraType.Value))
|
||||
.OrderBy(i => i.SortName);
|
||||
}
|
||||
|
||||
@@ -89,13 +89,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
|
||||
var v = sourceProp.GetValue(source);
|
||||
if (v == null)
|
||||
if (v is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var p = destProps.Find(x => x.Name == sourceProp.Name);
|
||||
if (p != null)
|
||||
if (p is not null)
|
||||
{
|
||||
p.SetValue(dest, v);
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var path = ContainingFolderPath;
|
||||
|
||||
var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService)
|
||||
var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, LibraryManager)
|
||||
{
|
||||
FileInfo = FileSystem.GetDirectoryInfo(path),
|
||||
Parent = GetParent() as Folder,
|
||||
@@ -355,8 +355,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return PhysicalLocations
|
||||
.Where(i => !FileSystem.AreEqual(i, Path))
|
||||
.SelectMany(i => GetPhysicalParents(i, rootChildren))
|
||||
.GroupBy(x => x.Id)
|
||||
.Select(x => x.First());
|
||||
.DistinctBy(x => x.Id);
|
||||
}
|
||||
|
||||
private IEnumerable<Folder> GetPhysicalParents(string path, List<Folder> rootChildren)
|
||||
|
||||
@@ -17,16 +17,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <param name="url">Trailer URL.</param>
|
||||
public static void AddTrailerUrl(this BaseItem item, string url)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(url);
|
||||
|
||||
if (url.Length == 0)
|
||||
{
|
||||
throw new ArgumentException("String can't be empty", nameof(url));
|
||||
}
|
||||
ArgumentException.ThrowIfNullOrEmpty(url);
|
||||
|
||||
var current = item.RemoteTrailers.FirstOrDefault(i => string.Equals(i.Url, url, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (current == null)
|
||||
if (current is null)
|
||||
{
|
||||
var mediaUrl = new MediaUrl
|
||||
{
|
||||
|
||||
@@ -483,7 +483,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
});
|
||||
|
||||
if (container != null)
|
||||
if (container is not null)
|
||||
{
|
||||
await RefreshAllMetadataForContainer(container, refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
@@ -515,7 +515,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
async () =>
|
||||
{
|
||||
var series = container as Series;
|
||||
if (series != null)
|
||||
if (series is not null)
|
||||
{
|
||||
await series.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
@@ -529,7 +529,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var container = child as IMetadataContainer;
|
||||
|
||||
if (container != null)
|
||||
if (container is not null)
|
||||
{
|
||||
await RefreshAllMetadataForContainer(container, refreshOptions, progress, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
@@ -703,7 +703,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
IEnumerable<BaseItem> items;
|
||||
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
||||
|
||||
if (query.User == null)
|
||||
if (query.User is null)
|
||||
{
|
||||
items = GetRecursiveChildren(filter);
|
||||
}
|
||||
@@ -730,7 +730,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return LibraryManager.GetItemsResult(query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> QueryWithPostFiltering2(InternalItemsQuery query)
|
||||
protected QueryResult<BaseItem> QueryWithPostFiltering2(InternalItemsQuery query)
|
||||
{
|
||||
var startIndex = query.StartIndex;
|
||||
var limit = query.Limit;
|
||||
@@ -741,7 +741,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
IEnumerable<BaseItem> itemsList = LibraryManager.GetItemList(query);
|
||||
var user = query.User;
|
||||
|
||||
if (user != null)
|
||||
if (user is not null)
|
||||
{
|
||||
// needed for boxsets
|
||||
itemsList = itemsList.Where(i => i.IsVisibleStandalone(query.User));
|
||||
@@ -961,7 +961,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
IEnumerable<BaseItem> items;
|
||||
|
||||
if (query.User == null)
|
||||
if (query.User is null)
|
||||
{
|
||||
items = Children.Where(filter);
|
||||
}
|
||||
@@ -984,7 +984,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
var user = query.User;
|
||||
|
||||
// Check recursive - don't substitute in plain folder views
|
||||
if (user != null)
|
||||
if (user is not null)
|
||||
{
|
||||
items = CollapseBoxSetItemsIfNeeded(items, query, this, user, ConfigurationManager, CollectionManager);
|
||||
}
|
||||
@@ -1069,7 +1069,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
if (!param.HasValue)
|
||||
{
|
||||
if (user != null && !configurationManager.Configuration.EnableGroupingIntoCollections)
|
||||
if (user is not null && !configurationManager.Configuration.EnableGroupingIntoCollections)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1272,7 +1272,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(user);
|
||||
|
||||
return GetChildren(user, includeLinkedChildren, null);
|
||||
return GetChildren(user, includeLinkedChildren, new InternalItemsQuery(user));
|
||||
}
|
||||
|
||||
public virtual List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query)
|
||||
@@ -1300,8 +1300,15 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <summary>
|
||||
/// Adds the children to list.
|
||||
/// </summary>
|
||||
private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, InternalItemsQuery query)
|
||||
private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, InternalItemsQuery query, HashSet<Folder> visitedFolders = null)
|
||||
{
|
||||
// Prevent infinite recursion of nested folders
|
||||
visitedFolders ??= new HashSet<Folder>();
|
||||
if (!visitedFolders.Add(this))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If Query.AlbumFolders is set, then enforce the format as per the db in that it permits sub-folders in music albums.
|
||||
IEnumerable<BaseItem> children = null;
|
||||
if ((query?.DisplayAlbumFolders ?? false) && (this is MusicAlbum))
|
||||
@@ -1311,47 +1318,38 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
|
||||
// If there are not sub-folders, proceed as normal.
|
||||
if (children == null)
|
||||
if (children is null)
|
||||
{
|
||||
children = GetEligibleChildrenForRecursiveChildren(user);
|
||||
}
|
||||
|
||||
foreach (var child in children)
|
||||
{
|
||||
bool? isVisibleToUser = null;
|
||||
|
||||
if (query == null || UserViewBuilder.FilterItem(child, query))
|
||||
{
|
||||
isVisibleToUser = child.IsVisible(user);
|
||||
|
||||
if (isVisibleToUser.Value)
|
||||
{
|
||||
result[child.Id] = child;
|
||||
}
|
||||
}
|
||||
|
||||
if (isVisibleToUser ?? child.IsVisible(user))
|
||||
{
|
||||
if (recursive && child.IsFolder)
|
||||
{
|
||||
var folder = (Folder)child;
|
||||
|
||||
folder.AddChildren(user, includeLinkedChildren, result, true, query);
|
||||
}
|
||||
}
|
||||
}
|
||||
AddChildrenFromCollection(children, user, includeLinkedChildren, result, recursive, query, visitedFolders);
|
||||
|
||||
if (includeLinkedChildren)
|
||||
{
|
||||
foreach (var child in GetLinkedChildren(user))
|
||||
AddChildrenFromCollection(GetLinkedChildren(user), user, includeLinkedChildren, result, recursive, query, visitedFolders);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddChildrenFromCollection(IEnumerable<BaseItem> children, User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, InternalItemsQuery query, HashSet<Folder> visitedFolders)
|
||||
{
|
||||
foreach (var child in children)
|
||||
{
|
||||
if (!child.IsVisible(user))
|
||||
{
|
||||
if (query == null || UserViewBuilder.FilterItem(child, query))
|
||||
{
|
||||
if (child.IsVisible(user))
|
||||
{
|
||||
result[child.Id] = child;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (query is null || UserViewBuilder.FilterItem(child, query))
|
||||
{
|
||||
result[child.Id] = child;
|
||||
}
|
||||
|
||||
if (recursive && child.IsFolder)
|
||||
{
|
||||
var folder = (Folder)child;
|
||||
|
||||
folder.AddChildren(user, includeLinkedChildren, result, true, query, visitedFolders);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1402,7 +1400,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
foreach (var child in Children)
|
||||
{
|
||||
if (filter == null || filter(child))
|
||||
if (filter is null || filter(child))
|
||||
{
|
||||
result[child.Id] = child;
|
||||
}
|
||||
@@ -1420,7 +1418,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
foreach (var child in GetLinkedChildren())
|
||||
{
|
||||
if (filter == null || filter(child))
|
||||
if (filter is null || filter(child))
|
||||
{
|
||||
result[child.Id] = child;
|
||||
}
|
||||
@@ -1441,7 +1439,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var child = GetLinkedChild(i);
|
||||
|
||||
if (child != null)
|
||||
if (child is not null)
|
||||
{
|
||||
list.Add(child);
|
||||
}
|
||||
@@ -1467,7 +1465,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var child = GetLinkedChild(i);
|
||||
|
||||
if (child != null && child.Id.Equals(itemId))
|
||||
if (child is not null && child.Id.Equals(itemId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -1478,7 +1476,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public List<BaseItem> GetLinkedChildren(User user)
|
||||
{
|
||||
if (!FilterLinkedChildrenPerUser || user == null)
|
||||
if (!FilterLinkedChildrenPerUser || user is null)
|
||||
{
|
||||
return GetLinkedChildren();
|
||||
}
|
||||
@@ -1504,7 +1502,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var child = GetLinkedChild(i);
|
||||
|
||||
if (child == null)
|
||||
if (child is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1547,7 +1545,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
return LinkedChildren
|
||||
.Select(i => new Tuple<LinkedChild, BaseItem>(i, GetLinkedChild(i)))
|
||||
.Where(i => i.Item2 != null);
|
||||
.Where(i => i.Item2 is not null);
|
||||
}
|
||||
|
||||
protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
||||
@@ -1605,7 +1603,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.Where(i => i != null)
|
||||
.Where(i => i is not null)
|
||||
.ToList();
|
||||
|
||||
var currentShortcutLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Shortcut).ToList();
|
||||
@@ -1662,7 +1660,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
// The querying doesn't support virtual unaired
|
||||
var episode = item as Episode;
|
||||
if (episode != null && episode.IsUnaired)
|
||||
if (episode is not null && episode.IsUnaired)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1719,7 +1717,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
if (itemDto != null)
|
||||
if (itemDto is not null)
|
||||
{
|
||||
if (fields.ContainsField(ItemFields.RecursiveItemCount))
|
||||
{
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CA1819, CS1591
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasShares
|
||||
{
|
||||
Share[] Shares { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
EnableTotalRecordCount = true;
|
||||
ExcludeArtistIds = Array.Empty<Guid>();
|
||||
ExcludeInheritedTags = Array.Empty<string>();
|
||||
IncludeInheritedTags = Array.Empty<string>();
|
||||
ExcludeItemIds = Array.Empty<Guid>();
|
||||
ExcludeItemTypes = Array.Empty<BaseItemKind>();
|
||||
ExcludeTags = Array.Empty<string>();
|
||||
@@ -55,7 +56,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
public InternalItemsQuery(User? user)
|
||||
: this()
|
||||
{
|
||||
if (user != null)
|
||||
if (user is not null)
|
||||
{
|
||||
SetUser(user);
|
||||
}
|
||||
@@ -95,6 +96,8 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public string[] ExcludeInheritedTags { get; set; }
|
||||
|
||||
public string[] IncludeInheritedTags { get; set; }
|
||||
|
||||
public IReadOnlyList<string> Genres { get; set; }
|
||||
|
||||
public bool? IsSpecialSeason { get; set; }
|
||||
@@ -316,7 +319,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
if (value is null)
|
||||
{
|
||||
ParentId = Guid.Empty;
|
||||
ParentType = null;
|
||||
@@ -368,6 +371,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
|
||||
ExcludeInheritedTags = user.GetPreference(PreferenceKind.BlockedTags);
|
||||
IncludeInheritedTags = user.GetPreference(PreferenceKind.AllowedTags);
|
||||
|
||||
User = user;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
public string BlurHash { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsLocalFile => Path == null || !Path.StartsWith("http", StringComparison.OrdinalIgnoreCase);
|
||||
public bool IsLocalFile => Path is null || !Path.StartsWith("http", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||
|
||||
public override bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders)
|
||||
{
|
||||
return true;
|
||||
return user.HasPermission(PermissionKind.IsAdministrator) || user.HasPermission(PermissionKind.EnableCollectionManagement);
|
||||
}
|
||||
|
||||
public override bool IsSaveLocalMetadataEnabled()
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||
/// <inheritdoc />
|
||||
[JsonIgnore]
|
||||
public IReadOnlyList<Guid> SpecialFeatureIds => GetExtras()
|
||||
.Where(extra => extra.ExtraType != null && extra is Video)
|
||||
.Where(extra => extra.ExtraType is not null && extra is Video)
|
||||
.Select(extra => extra.Id)
|
||||
.ToArray();
|
||||
|
||||
@@ -33,9 +33,9 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||
.ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the TMDB collection.
|
||||
/// Gets or sets the name of the TMDb collection.
|
||||
/// </summary>
|
||||
/// <value>The name of the TMDB collection.</value>
|
||||
/// <value>The name of the TMDb collection.</value>
|
||||
public string TmdbCollectionName { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
@@ -12,48 +13,44 @@ namespace MediaBrowser.Controller.Entities
|
||||
public static void AddPerson(List<PersonInfo> people, PersonInfo person)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(person);
|
||||
|
||||
if (string.IsNullOrEmpty(person.Name))
|
||||
{
|
||||
throw new ArgumentException("The person's name was empty or null.", nameof(person));
|
||||
}
|
||||
ArgumentException.ThrowIfNullOrEmpty(person.Name);
|
||||
|
||||
// Normalize
|
||||
if (string.Equals(person.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
person.Type = PersonType.GuestStar;
|
||||
person.Type = PersonKind.GuestStar;
|
||||
}
|
||||
else if (string.Equals(person.Role, PersonType.Director, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
person.Type = PersonType.Director;
|
||||
person.Type = PersonKind.Director;
|
||||
}
|
||||
else if (string.Equals(person.Role, PersonType.Producer, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
person.Type = PersonType.Producer;
|
||||
person.Type = PersonKind.Producer;
|
||||
}
|
||||
else if (string.Equals(person.Role, PersonType.Writer, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
person.Type = PersonType.Writer;
|
||||
person.Type = PersonKind.Writer;
|
||||
}
|
||||
|
||||
// If the type is GuestStar and there's already an Actor entry, then update it to avoid dupes
|
||||
if (string.Equals(person.Type, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase))
|
||||
if (person.Type == PersonKind.GuestStar)
|
||||
{
|
||||
var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && p.Type.Equals(PersonType.Actor, StringComparison.OrdinalIgnoreCase));
|
||||
var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && p.Type == PersonKind.Actor);
|
||||
|
||||
if (existing != null)
|
||||
if (existing is not null)
|
||||
{
|
||||
existing.Type = PersonType.GuestStar;
|
||||
existing.Type = PersonKind.GuestStar;
|
||||
MergeExisting(existing, person);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (string.Equals(person.Type, PersonType.Actor, StringComparison.OrdinalIgnoreCase))
|
||||
if (person.Type == PersonKind.Actor)
|
||||
{
|
||||
// If the actor already exists without a role and we have one, fill it in
|
||||
var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && (p.Type.Equals(PersonType.Actor, StringComparison.OrdinalIgnoreCase) || p.Type.Equals(PersonType.GuestStar, StringComparison.OrdinalIgnoreCase)));
|
||||
if (existing == null)
|
||||
var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && (p.Type == PersonKind.Actor || p.Type == PersonKind.GuestStar));
|
||||
if (existing is null)
|
||||
{
|
||||
// Wasn't there - add it
|
||||
people.Add(person);
|
||||
@@ -72,11 +69,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
else
|
||||
{
|
||||
var existing = people.FirstOrDefault(p =>
|
||||
string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(p.Type, person.Type, StringComparison.OrdinalIgnoreCase));
|
||||
string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase)
|
||||
&& p.Type == person.Type);
|
||||
|
||||
// Check for dupes based on the combination of Name and Type
|
||||
if (existing == null)
|
||||
if (existing is null)
|
||||
{
|
||||
people.Add(person);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
@@ -36,7 +37,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// Gets or sets the type.
|
||||
/// </summary>
|
||||
/// <value>The type.</value>
|
||||
public string Type { get; set; }
|
||||
public PersonKind Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ascending sort order.
|
||||
@@ -57,10 +58,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
return Name;
|
||||
}
|
||||
|
||||
public bool IsType(string type)
|
||||
{
|
||||
return string.Equals(Type, type, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(Role, type, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
public bool IsType(PersonKind type) => Type == type || string.Equals(type.ToString(), Role, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public class Share
|
||||
{
|
||||
public string UserId { get; set; }
|
||||
|
||||
public bool CanEdit { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -136,7 +136,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
public string FindSeriesSortName()
|
||||
{
|
||||
var series = Series;
|
||||
return series == null ? SeriesName : series.SortName;
|
||||
return series is null ? SeriesName : series.SortName;
|
||||
}
|
||||
|
||||
public override double GetDefaultPrimaryImageAspectRatio()
|
||||
@@ -155,7 +155,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
var list = base.GetUserDataKeys();
|
||||
|
||||
var series = Series;
|
||||
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
|
||||
if (series is not null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
|
||||
{
|
||||
var seriesUserDataKeys = series.GetUserDataKeys();
|
||||
var take = seriesUserDataKeys.Count;
|
||||
@@ -181,14 +181,14 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
public string FindSeriesPresentationUniqueKey()
|
||||
{
|
||||
var series = Series;
|
||||
return series == null ? null : series.PresentationUniqueKey;
|
||||
return series is null ? null : series.PresentationUniqueKey;
|
||||
}
|
||||
|
||||
public string FindSeasonName()
|
||||
{
|
||||
var season = Season;
|
||||
|
||||
if (season == null)
|
||||
if (season is null)
|
||||
{
|
||||
if (ParentIndexNumber.HasValue)
|
||||
{
|
||||
@@ -204,7 +204,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
public string FindSeriesName()
|
||||
{
|
||||
var series = Series;
|
||||
return series == null ? SeriesName : series.Name;
|
||||
return series is null ? SeriesName : series.Name;
|
||||
}
|
||||
|
||||
public Guid FindSeasonId()
|
||||
@@ -212,11 +212,11 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
var season = FindParent<Season>();
|
||||
|
||||
// Episodes directly in series folder
|
||||
if (season == null)
|
||||
if (season is null)
|
||||
{
|
||||
var series = Series;
|
||||
|
||||
if (series != null && ParentIndexNumber.HasValue)
|
||||
if (series is not null && ParentIndexNumber.HasValue)
|
||||
{
|
||||
var findNumber = ParentIndexNumber.Value;
|
||||
|
||||
@@ -226,7 +226,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
}
|
||||
}
|
||||
|
||||
return season == null ? Guid.Empty : season.Id;
|
||||
return season is null ? Guid.Empty : season.Id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -235,8 +235,8 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
/// <returns>System.String.</returns>
|
||||
protected override string CreateSortName()
|
||||
{
|
||||
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000 - ", CultureInfo.InvariantCulture) : string.Empty)
|
||||
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ", CultureInfo.InvariantCulture) : string.Empty) + Name;
|
||||
return (ParentIndexNumber is not null ? ParentIndexNumber.Value.ToString("000 - ", CultureInfo.InvariantCulture) : string.Empty)
|
||||
+ (IndexNumber is not null ? IndexNumber.Value.ToString("0000 - ", CultureInfo.InvariantCulture) : string.Empty) + Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -262,7 +262,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
public Guid FindSeriesId()
|
||||
{
|
||||
var series = FindParent<Series>();
|
||||
return series == null ? Guid.Empty : series.Id;
|
||||
return series is null ? Guid.Empty : series.Id;
|
||||
}
|
||||
|
||||
public override IEnumerable<Guid> GetAncestorIds()
|
||||
@@ -302,12 +302,17 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
|
||||
var series = Series;
|
||||
|
||||
if (series != null)
|
||||
if (series is not null)
|
||||
{
|
||||
id.SeriesProviderIds = series.ProviderIds;
|
||||
id.SeriesDisplayOrder = series.DisplayOrder;
|
||||
}
|
||||
|
||||
if (Season is not null)
|
||||
{
|
||||
id.SeasonProviderIds = Season.ProviderIds;
|
||||
}
|
||||
|
||||
id.IsMissingEpisode = IsMissingEpisode;
|
||||
id.IndexNumberEnd = IndexNumberEnd;
|
||||
|
||||
@@ -320,7 +325,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
|
||||
if (!IsLocked)
|
||||
{
|
||||
if (SourceType == SourceType.Library)
|
||||
if (SourceType == SourceType.Library || SourceType == SourceType.LiveTV)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
{
|
||||
var series = Series;
|
||||
|
||||
if (series != null)
|
||||
if (series is not null)
|
||||
{
|
||||
return series.Path;
|
||||
}
|
||||
@@ -93,7 +93,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
public string FindSeriesSortName()
|
||||
{
|
||||
var series = Series;
|
||||
return series == null ? SeriesName : series.SortName;
|
||||
return series is null ? SeriesName : series.SortName;
|
||||
}
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
@@ -101,7 +101,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
var list = base.GetUserDataKeys();
|
||||
|
||||
var series = Series;
|
||||
if (series != null)
|
||||
if (series is not null)
|
||||
{
|
||||
var newList = series.GetUserDataKeys();
|
||||
var suffix = (IndexNumber ?? 0).ToString("000", CultureInfo.InvariantCulture);
|
||||
@@ -129,7 +129,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
if (IndexNumber.HasValue)
|
||||
{
|
||||
var series = Series;
|
||||
if (series != null)
|
||||
if (series is not null)
|
||||
{
|
||||
return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000", CultureInfo.InvariantCulture);
|
||||
}
|
||||
@@ -144,12 +144,12 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
/// <returns>System.String.</returns>
|
||||
protected override string CreateSortName()
|
||||
{
|
||||
return IndexNumber != null ? IndexNumber.Value.ToString("0000", CultureInfo.InvariantCulture) : Name;
|
||||
return IndexNumber is not null ? IndexNumber.Value.ToString("0000", CultureInfo.InvariantCulture) : Name;
|
||||
}
|
||||
|
||||
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
|
||||
{
|
||||
if (query.User == null)
|
||||
if (query.User is null)
|
||||
{
|
||||
return base.GetItemsInternal(query);
|
||||
}
|
||||
@@ -208,13 +208,13 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
public string FindSeriesPresentationUniqueKey()
|
||||
{
|
||||
var series = Series;
|
||||
return series == null ? null : series.PresentationUniqueKey;
|
||||
return series is null ? null : series.PresentationUniqueKey;
|
||||
}
|
||||
|
||||
public string FindSeriesName()
|
||||
{
|
||||
var series = Series;
|
||||
return series == null ? SeriesName : series.Name;
|
||||
return series is null ? SeriesName : series.Name;
|
||||
}
|
||||
|
||||
public Guid FindSeriesId()
|
||||
@@ -233,7 +233,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
|
||||
var series = Series;
|
||||
|
||||
if (series != null)
|
||||
if (series is not null)
|
||||
{
|
||||
id.SeriesProviderIds = series.ProviderIds;
|
||||
}
|
||||
|
||||
@@ -28,12 +28,16 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
public Series()
|
||||
{
|
||||
AirDays = Array.Empty<DayOfWeek>();
|
||||
SeasonNames = new Dictionary<int, string>();
|
||||
}
|
||||
|
||||
public DayOfWeek[] AirDays { get; set; }
|
||||
|
||||
public string AirTime { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public Dictionary<int, string> SeasonNames { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public override bool SupportsAddingToPlaylist => true;
|
||||
|
||||
@@ -218,7 +222,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
query.IncludeItemTypes = new[] { BaseItemKind.Season };
|
||||
query.OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) };
|
||||
|
||||
if (user != null && !user.DisplayMissingEpisodes)
|
||||
if (user is not null && !user.DisplayMissingEpisodes)
|
||||
{
|
||||
query.IsMissing = false;
|
||||
}
|
||||
@@ -266,7 +270,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
DtoOptions = options
|
||||
};
|
||||
|
||||
if (user == null || !user.DisplayMissingEpisodes)
|
||||
if (user is null || !user.DisplayMissingEpisodes)
|
||||
{
|
||||
query.IsMissing = false;
|
||||
}
|
||||
@@ -283,7 +287,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
// This depends on settings for that series
|
||||
// When this happens, remove the duplicate from season 0
|
||||
|
||||
return allEpisodes.GroupBy(i => i.Id).Select(x => x.First()).Reverse();
|
||||
return allEpisodes.DistinctBy(i => i.Id).Reverse();
|
||||
}
|
||||
|
||||
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
@@ -369,7 +373,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) },
|
||||
DtoOptions = options
|
||||
};
|
||||
if (user != null)
|
||||
if (user is not null)
|
||||
{
|
||||
if (!user.DisplayMissingEpisodes)
|
||||
{
|
||||
@@ -384,7 +388,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
|
||||
public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, IEnumerable<BaseItem> allSeriesEpisodes, DtoOptions options)
|
||||
{
|
||||
if (allSeriesEpisodes == null)
|
||||
if (allSeriesEpisodes is null)
|
||||
{
|
||||
return GetSeasonEpisodes(parentSeason, user, options);
|
||||
}
|
||||
@@ -426,7 +430,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
}
|
||||
|
||||
var season = episodeItem.Season;
|
||||
return season != null && string.Equals(GetUniqueSeriesKey(season), seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
|
||||
return season is not null && string.Equals(GetUniqueSeriesKey(season), seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -448,7 +452,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
{
|
||||
var episode = i;
|
||||
|
||||
if (episode != null)
|
||||
if (episode is not null)
|
||||
{
|
||||
var currentSeasonNumber = episode.AiredSeasonNumber;
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Rating != null)
|
||||
if (Rating is not null)
|
||||
{
|
||||
return Rating >= MinLikeValue;
|
||||
}
|
||||
|
||||
@@ -56,14 +56,14 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
lock (_childIdsLock)
|
||||
{
|
||||
if (_childrenIds == null)
|
||||
if (_childrenIds is null)
|
||||
{
|
||||
var list = base.LoadChildren();
|
||||
_childrenIds = list.Select(i => i.Id).ToList();
|
||||
return list;
|
||||
}
|
||||
|
||||
return _childrenIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList();
|
||||
return _childrenIds.Select(LibraryManager.GetItemById).Where(i => i is not null).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var user = query.User;
|
||||
|
||||
// if (query.IncludeItemTypes != null &&
|
||||
// if (query.IncludeItemTypes is not null &&
|
||||
// query.IncludeItemTypes.Length == 1 &&
|
||||
// string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase))
|
||||
// {
|
||||
@@ -263,7 +263,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.Where(i => i != null)
|
||||
.Where(i => i is not null)
|
||||
.Select(i => GetUserViewWithName(SpecialFolder.MovieGenre, i.SortName, parent));
|
||||
|
||||
return GetResult(genres, query);
|
||||
@@ -391,7 +391,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.Where(i => i != null)
|
||||
.Where(i => i is not null)
|
||||
.Select(i => GetUserViewWithName(SpecialFolder.TvGenre, i.SortName, parent));
|
||||
|
||||
return GetResult(genres, query);
|
||||
@@ -559,7 +559,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
var val = query.Is3D.Value;
|
||||
var video = item as Video;
|
||||
|
||||
if (video == null || val != video.Video3DFormat.HasValue)
|
||||
if (video is null || val != video.Video3DFormat.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -689,7 +689,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var video = item as Video;
|
||||
|
||||
if (video == null || val != video.HasSubtitles)
|
||||
if (video is null || val != video.HasSubtitles)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -776,7 +776,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
if (query.VideoTypes.Length > 0)
|
||||
{
|
||||
var video = item as Video;
|
||||
if (video == null || !query.VideoTypes.Contains(video.VideoType))
|
||||
if (video is null || !query.VideoTypes.Contains(video.VideoType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -791,7 +791,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
if (query.StudioIds.Length > 0 && !query.StudioIds.Any(id =>
|
||||
{
|
||||
var studioItem = libraryManager.GetItemById(id);
|
||||
return studioItem != null && item.Studios.Contains(studioItem.Name, StringComparison.OrdinalIgnoreCase);
|
||||
return studioItem is not null && item.Studios.Contains(studioItem.Name, StringComparison.OrdinalIgnoreCase);
|
||||
}))
|
||||
{
|
||||
return false;
|
||||
@@ -801,7 +801,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
if (query.GenreIds.Count > 0 && !query.GenreIds.Any(id =>
|
||||
{
|
||||
var genreItem = libraryManager.GetItemById(id);
|
||||
return genreItem != null && item.Genres.Contains(genreItem.Name, StringComparison.OrdinalIgnoreCase);
|
||||
return genreItem is not null && item.Genres.Contains(genreItem.Name, StringComparison.OrdinalIgnoreCase);
|
||||
}))
|
||||
{
|
||||
return false;
|
||||
@@ -913,7 +913,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var episode = item as Episode;
|
||||
|
||||
if (episode == null)
|
||||
if (episode is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -929,7 +929,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
private IEnumerable<BaseItem> GetMediaFolders(User user)
|
||||
{
|
||||
if (user == null)
|
||||
if (user is null)
|
||||
{
|
||||
return _libraryManager.RootFolder
|
||||
.Children
|
||||
@@ -945,14 +945,14 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
private BaseItem[] GetMediaFolders(User user, IEnumerable<string> viewTypes)
|
||||
{
|
||||
if (user == null)
|
||||
if (user is null)
|
||||
{
|
||||
return GetMediaFolders(null)
|
||||
.Where(i =>
|
||||
{
|
||||
var folder = i as ICollectionFolder;
|
||||
|
||||
return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
return folder is not null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
@@ -961,13 +961,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var folder = i as ICollectionFolder;
|
||||
|
||||
return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
return folder is not null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
private BaseItem[] GetMediaFolders(Folder parent, User user, IEnumerable<string> viewTypes)
|
||||
{
|
||||
if (parent == null || parent is UserView)
|
||||
if (parent is null || parent is UserView)
|
||||
{
|
||||
return GetMediaFolders(user, viewTypes);
|
||||
}
|
||||
|
||||
@@ -373,7 +373,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
return LinkedAlternateVersions
|
||||
.Select(GetLinkedChild)
|
||||
.Where(i => i != null)
|
||||
.Where(i => i is not null)
|
||||
.OfType<Video>()
|
||||
.OrderBy(i => i.SortName);
|
||||
}
|
||||
@@ -386,7 +386,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
return GetAdditionalPartIds()
|
||||
.Select(i => LibraryManager.GetItemById(i))
|
||||
.Where(i => i != null)
|
||||
.Where(i => i is not null)
|
||||
.OfType<Video>()
|
||||
.OrderBy(i => i.SortName);
|
||||
}
|
||||
@@ -469,7 +469,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var localAlternates = GetLocalAlternateVersionIds()
|
||||
.Select(i => LibraryManager.GetItemById(i))
|
||||
.Where(i => i != null);
|
||||
.Where(i => i is not null);
|
||||
|
||||
foreach (var item in localAlternates)
|
||||
{
|
||||
@@ -542,7 +542,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return i.Item1 is Video video ? video.GetLocalAlternateVersionIds() : Enumerable.Empty<Guid>();
|
||||
})
|
||||
.Select(LibraryManager.GetItemById)
|
||||
.Where(i => i != null)
|
||||
.Where(i => i is not null)
|
||||
.ToList();
|
||||
|
||||
list.AddRange(localAlternates.Select(i => (i, MediaSourceType.Default)));
|
||||
|
||||
@@ -59,6 +59,11 @@ namespace MediaBrowser.Controller.Extensions
|
||||
/// </summary>
|
||||
public const string UnixSocketPermissionsKey = "kestrel:socketPermissions";
|
||||
|
||||
/// <summary>
|
||||
/// The cache size of the SQL database, see cache_size.
|
||||
/// </summary>
|
||||
public const string SqliteCacheSizeKey = "sqlite:cacheSize";
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the application should host static web content from the <see cref="IConfiguration"/>.
|
||||
/// </summary>
|
||||
@@ -73,7 +78,7 @@ namespace MediaBrowser.Controller.Extensions
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration to read the setting from.</param>
|
||||
/// <returns>The FFmpeg probe size option.</returns>
|
||||
public static string GetFFmpegProbeSize(this IConfiguration configuration)
|
||||
public static string? GetFFmpegProbeSize(this IConfiguration configuration)
|
||||
=> configuration[FfmpegProbeSizeKey];
|
||||
|
||||
/// <summary>
|
||||
@@ -81,7 +86,7 @@ namespace MediaBrowser.Controller.Extensions
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration to read the setting from.</param>
|
||||
/// <returns>The FFmpeg analyze duration option.</returns>
|
||||
public static string GetFFmpegAnalyzeDuration(this IConfiguration configuration)
|
||||
public static string? GetFFmpegAnalyzeDuration(this IConfiguration configuration)
|
||||
=> configuration[FfmpegAnalyzeDurationKey];
|
||||
|
||||
/// <summary>
|
||||
@@ -105,7 +110,7 @@ namespace MediaBrowser.Controller.Extensions
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration to read the setting from.</param>
|
||||
/// <returns>The unix socket path.</returns>
|
||||
public static string GetUnixSocketPath(this IConfiguration configuration)
|
||||
public static string? GetUnixSocketPath(this IConfiguration configuration)
|
||||
=> configuration[UnixSocketPathKey];
|
||||
|
||||
/// <summary>
|
||||
@@ -113,7 +118,15 @@ namespace MediaBrowser.Controller.Extensions
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration to read the setting from.</param>
|
||||
/// <returns>The unix socket permissions.</returns>
|
||||
public static string GetUnixSocketPermissions(this IConfiguration configuration)
|
||||
public static string? GetUnixSocketPermissions(this IConfiguration configuration)
|
||||
=> configuration[UnixSocketPermissionsKey];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cache_size from the <see cref="IConfiguration" />.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration to read the setting from.</param>
|
||||
/// <returns>The sqlite cache size.</returns>
|
||||
public static int? GetSqliteCacheSize(this IConfiguration configuration)
|
||||
=> configuration.GetValue<int?>(SqliteCacheSizeKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +35,7 @@ namespace MediaBrowser.Controller.IO
|
||||
int flattenFolderDepth = 0,
|
||||
bool resolveShortcuts = true)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
ArgumentException.ThrowIfNullOrEmpty(path);
|
||||
|
||||
ArgumentNullException.ThrowIfNull(args);
|
||||
|
||||
|
||||
@@ -50,24 +50,6 @@ namespace MediaBrowser.Controller
|
||||
/// <value>The year path.</value>
|
||||
string YearPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the General IBN directory.
|
||||
/// </summary>
|
||||
/// <value>The general path.</value>
|
||||
string GeneralPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the Ratings IBN directory.
|
||||
/// </summary>
|
||||
/// <value>The ratings path.</value>
|
||||
string RatingsPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media info images path.
|
||||
/// </summary>
|
||||
/// <value>The media info images path.</value>
|
||||
string MediaInfoImagesPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the user configuration directory.
|
||||
/// </summary>
|
||||
|
||||
@@ -429,10 +429,16 @@ namespace MediaBrowser.Controller.Library
|
||||
/// Gets the collection folders.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>IEnumerable<Folder>.</returns>
|
||||
/// <returns>The folders that contain the item.</returns>
|
||||
List<Folder> GetCollectionFolders(BaseItem item);
|
||||
|
||||
List<Folder> GetCollectionFolders(BaseItem item, List<Folder> allUserRootChildren);
|
||||
/// <summary>
|
||||
/// Gets the collection folders.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="allUserRootChildren">The root folders to consider.</param>
|
||||
/// <returns>The folders that contain the item.</returns>
|
||||
List<Folder> GetCollectionFolders(BaseItem item, IEnumerable<Folder> allUserRootChildren);
|
||||
|
||||
LibraryOptions GetLibraryOptions(BaseItem item);
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
@@ -47,14 +45,14 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <param name="id">The id.</param>
|
||||
/// <returns>The user with the specified Id, or <c>null</c> if the user doesn't exist.</returns>
|
||||
/// <exception cref="ArgumentException"><c>id</c> is an empty Guid.</exception>
|
||||
User GetUserById(Guid id);
|
||||
User? GetUserById(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the user by.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>User.</returns>
|
||||
User GetUserByName(string name);
|
||||
User? GetUserByName(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Renames the user.
|
||||
@@ -98,13 +96,6 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <returns>Task.</returns>
|
||||
Task ResetPassword(User user);
|
||||
|
||||
/// <summary>
|
||||
/// Resets the easy password.
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task ResetEasyPassword(User user);
|
||||
|
||||
/// <summary>
|
||||
/// Changes the password.
|
||||
/// </summary>
|
||||
@@ -113,22 +104,13 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <returns>Awaitable task.</returns>
|
||||
Task ChangePassword(User user, string newPassword);
|
||||
|
||||
/// <summary>
|
||||
/// Changes the easy password.
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="newPassword">New password to use.</param>
|
||||
/// <param name="newPasswordSha1">Hash of new password.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task ChangeEasyPassword(User user, string newPassword, string newPasswordSha1);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user dto.
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="remoteEndPoint">The remote end point.</param>
|
||||
/// <returns>UserDto.</returns>
|
||||
UserDto GetUserDto(User user, string remoteEndPoint = null);
|
||||
UserDto GetUserDto(User user, string? remoteEndPoint = null);
|
||||
|
||||
/// <summary>
|
||||
/// Authenticates the user.
|
||||
@@ -139,7 +121,7 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <param name="remoteEndPoint">Remove endpoint to use.</param>
|
||||
/// <param name="isUserSession">Specifies if a user session.</param>
|
||||
/// <returns>User wrapped in awaitable task.</returns>
|
||||
Task<User> AuthenticateUser(string username, string password, string passwordSha1, string remoteEndPoint, bool isUserSession);
|
||||
Task<User?> AuthenticateUser(string username, string password, string passwordSha1, string remoteEndPoint, bool isUserSession);
|
||||
|
||||
/// <summary>
|
||||
/// Starts the forgot password process.
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CA1721, CA1819, CS1591
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.IO;
|
||||
|
||||
@@ -23,22 +22,20 @@ namespace MediaBrowser.Controller.Library
|
||||
/// </summary>
|
||||
private readonly IServerApplicationPaths _appPaths;
|
||||
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private LibraryOptions _libraryOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemResolveArgs" /> class.
|
||||
/// </summary>
|
||||
/// <param name="appPaths">The app paths.</param>
|
||||
/// <param name="directoryService">The directory service.</param>
|
||||
public ItemResolveArgs(IServerApplicationPaths appPaths, IDirectoryService directoryService)
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
public ItemResolveArgs(IServerApplicationPaths appPaths, ILibraryManager libraryManager)
|
||||
{
|
||||
_appPaths = appPaths;
|
||||
DirectoryService = directoryService;
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
// TODO remove dependencies as properties, they should be injected where it makes sense
|
||||
public IDirectoryService DirectoryService { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the file system children.
|
||||
/// </summary>
|
||||
@@ -47,7 +44,7 @@ namespace MediaBrowser.Controller.Library
|
||||
|
||||
public LibraryOptions LibraryOptions
|
||||
{
|
||||
get => _libraryOptions ??= Parent == null ? new LibraryOptions() : BaseItem.LibraryManager.GetLibraryOptions(Parent);
|
||||
get => _libraryOptions ??= Parent is null ? new LibraryOptions() : _libraryManager.GetLibraryOptions(Parent);
|
||||
set => _libraryOptions = value;
|
||||
}
|
||||
|
||||
@@ -119,7 +116,7 @@ namespace MediaBrowser.Controller.Library
|
||||
get
|
||||
{
|
||||
var paths = string.IsNullOrEmpty(Path) ? Array.Empty<string>() : new[] { Path };
|
||||
return AdditionalLocations == null ? paths : paths.Concat(AdditionalLocations).ToArray();
|
||||
return AdditionalLocations is null ? paths : paths.Concat(AdditionalLocations).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,13 +127,13 @@ namespace MediaBrowser.Controller.Library
|
||||
{
|
||||
var parent = Parent;
|
||||
|
||||
if (parent != null)
|
||||
if (parent is not null)
|
||||
{
|
||||
var item = parent as T;
|
||||
|
||||
// Just in case the user decided to nest episodes.
|
||||
// Not officially supported but in some cases we can handle it.
|
||||
if (item == null)
|
||||
if (item is null)
|
||||
{
|
||||
var parents = parent.GetParents();
|
||||
foreach (var currentParent in parents)
|
||||
@@ -148,7 +145,7 @@ namespace MediaBrowser.Controller.Library
|
||||
}
|
||||
}
|
||||
|
||||
return item != null;
|
||||
return item is not null;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -171,10 +168,7 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <exception cref="ArgumentNullException"><paramref name="path"/> is <c>null</c> or empty.</exception>
|
||||
public void AddAdditionalLocation(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
throw new ArgumentException("The path was empty or null.", nameof(path));
|
||||
}
|
||||
ArgumentException.ThrowIfNullOrEmpty(path);
|
||||
|
||||
AdditionalLocations ??= new List<string>();
|
||||
AdditionalLocations.Add(path);
|
||||
@@ -190,10 +184,7 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <exception cref="ArgumentNullException"><paramref name="name"/> is <c>null</c> or empty.</exception>
|
||||
public FileSystemMetadata GetFileSystemEntryByName(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentException("The name was empty or null.", nameof(name));
|
||||
}
|
||||
ArgumentException.ThrowIfNullOrEmpty(name);
|
||||
|
||||
return GetFileSystemEntryByPath(System.IO.Path.Combine(Path, name));
|
||||
}
|
||||
@@ -206,10 +197,7 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <exception cref="ArgumentNullException">Throws if path is invalid.</exception>
|
||||
public FileSystemMetadata GetFileSystemEntryByPath(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
throw new ArgumentException("The path was empty or null.", nameof(path));
|
||||
}
|
||||
ArgumentException.ThrowIfNullOrEmpty(path);
|
||||
|
||||
foreach (var file in FileSystemChildren)
|
||||
{
|
||||
@@ -240,21 +228,15 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <summary>
|
||||
/// Gets the configured content type for the path.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is subject to future refactoring as it relies on a static property in BaseItem.
|
||||
/// </remarks>
|
||||
/// <returns>The configured content type.</returns>
|
||||
public string GetConfiguredContentType()
|
||||
{
|
||||
return BaseItem.LibraryManager.GetConfiguredContentType(Path);
|
||||
return _libraryManager.GetConfiguredContentType(Path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file system children that do not hit the ignore file check.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is subject to future refactoring as it relies on a static property in BaseItem.
|
||||
/// </remarks>
|
||||
/// <returns>The file system children that are not ignored.</returns>
|
||||
public IEnumerable<FileSystemMetadata> GetActualFileSystemChildren()
|
||||
{
|
||||
@@ -262,7 +244,7 @@ namespace MediaBrowser.Controller.Library
|
||||
for (var i = 0; i < numberOfChildren; i++)
|
||||
{
|
||||
var child = FileSystemChildren[i];
|
||||
if (BaseItem.LibraryManager.IgnoreFile(child, Parent))
|
||||
if (_libraryManager.IgnoreFile(child, Parent))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -287,14 +269,14 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <returns><c>true</c> if the arguments are the same, <c>false</c> otherwise.</returns>
|
||||
protected bool Equals(ItemResolveArgs args)
|
||||
{
|
||||
if (args != null)
|
||||
if (args is not null)
|
||||
{
|
||||
if (args.Path == null && Path == null)
|
||||
if (args.Path is null && Path is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return args.Path != null && BaseItem.FileSystem.AreEqual(args.Path, Path);
|
||||
return args.Path is not null && BaseItem.FileSystem.AreEqual(args.Path, Path);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
@@ -9,7 +7,7 @@ namespace MediaBrowser.Controller.Library
|
||||
{
|
||||
public static class LibraryManagerExtensions
|
||||
{
|
||||
public static BaseItem GetItemById(this ILibraryManager manager, string id)
|
||||
public static BaseItem? GetItemById(this ILibraryManager manager, string id)
|
||||
{
|
||||
return manager.GetItemById(new Guid(id));
|
||||
}
|
||||
|
||||
@@ -10,12 +10,11 @@ namespace MediaBrowser.Controller.Library
|
||||
public static class NameExtensions
|
||||
{
|
||||
public static IEnumerable<string> DistinctNames(this IEnumerable<string> names)
|
||||
=> names.GroupBy(RemoveDiacritics, StringComparer.OrdinalIgnoreCase)
|
||||
.Select(x => x.First());
|
||||
=> names.DistinctBy(RemoveDiacritics, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private static string RemoveDiacritics(string? name)
|
||||
{
|
||||
if (name == null)
|
||||
if (name is null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>A recording.</returns>
|
||||
QueryResult<BaseItemDto> GetRecordings(RecordingQuery query, DtoOptions options);
|
||||
Task<QueryResult<BaseItemDto>> GetRecordingsAsync(RecordingQuery query, DtoOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the timers.
|
||||
@@ -308,6 +308,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
|
||||
void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, ActiveRecordingInfo activeRecordingInfo, User user = null);
|
||||
|
||||
List<BaseItem> GetRecordingFolders(User user);
|
||||
Task<BaseItem[]> GetRecordingFoldersAsync(User user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using Jellyfin.Data.Enums;
|
||||
using Jellyfin.Extensions;
|
||||
@@ -105,12 +106,9 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
|
||||
protected override string CreateSortName()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Number))
|
||||
if (double.TryParse(Number, CultureInfo.InvariantCulture, out double number))
|
||||
{
|
||||
if (double.TryParse(Number, NumberStyles.Any, CultureInfo.InvariantCulture, out double number))
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0:00000.0}", number) + "-" + (Name ?? string.Empty);
|
||||
}
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0:00000.0}", number) + "-" + (Name ?? string.Empty);
|
||||
}
|
||||
|
||||
return (Number ?? string.Empty) + "-" + (Name ?? string.Empty);
|
||||
@@ -122,9 +120,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
}
|
||||
|
||||
public IEnumerable<BaseItem> GetTaggedItems()
|
||||
{
|
||||
return new List<BaseItem>();
|
||||
}
|
||||
=> Enumerable.Empty<BaseItem>();
|
||||
|
||||
public override List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
{
|
||||
@@ -139,7 +135,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
Path = Path,
|
||||
RunTimeTicks = RunTimeTicks,
|
||||
Type = MediaSourceType.Placeholder,
|
||||
IsInfiniteStream = RunTimeTicks == null
|
||||
IsInfiniteStream = RunTimeTicks is null
|
||||
};
|
||||
|
||||
list.Add(info);
|
||||
|
||||
@@ -197,10 +197,8 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
return 2.0 / 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 16.0 / 9;
|
||||
}
|
||||
|
||||
return 16.0 / 9;
|
||||
}
|
||||
|
||||
public override string GetClientTypeName()
|
||||
@@ -246,7 +244,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
|
||||
var listings = GetListingsProviderInfo();
|
||||
|
||||
if (listings != null)
|
||||
if (listings is not null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(listings.MoviePrefix) && name.StartsWith(listings.MoviePrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Lyrics;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
|
||||
<PackageReference Include="System.Threading.Tasks.Dataflow" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -35,7 +35,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
@@ -51,13 +51,13 @@
|
||||
|
||||
<!-- Code Analyzers-->
|
||||
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
<PackageReference Include="SerilogAnalyzer" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,7 +40,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
if (!_transcodeReasons.HasValue)
|
||||
{
|
||||
if (BaseRequest.TranscodeReasons == null)
|
||||
if (BaseRequest.TranscodeReasons is null)
|
||||
{
|
||||
_transcodeReasons = 0;
|
||||
return 0;
|
||||
@@ -147,7 +147,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
|
||||
if (VideoStream is not null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
|
||||
{
|
||||
var size = new ImageDimensions(VideoStream.Width.Value, VideoStream.Height.Value);
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
|
||||
if (VideoStream is not null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
|
||||
{
|
||||
var size = new ImageDimensions(VideoStream.Width.Value, VideoStream.Height.Value);
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
if (BaseRequest.Static
|
||||
|| EncodingHelper.IsCopyCodec(OutputAudioCodec))
|
||||
{
|
||||
if (AudioStream != null)
|
||||
if (AudioStream is not null)
|
||||
{
|
||||
return AudioStream.SampleRate;
|
||||
}
|
||||
@@ -227,7 +227,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
if (BaseRequest.Static
|
||||
|| EncodingHelper.IsCopyCodec(OutputAudioCodec))
|
||||
{
|
||||
if (AudioStream != null)
|
||||
if (AudioStream is not null)
|
||||
{
|
||||
return AudioStream.BitDepth;
|
||||
}
|
||||
@@ -250,8 +250,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
}
|
||||
|
||||
var level = GetRequestedLevel(ActualOutputVideoCodec);
|
||||
if (!string.IsNullOrEmpty(level)
|
||||
&& double.TryParse(level, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
||||
if (double.TryParse(level, CultureInfo.InvariantCulture, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -305,7 +304,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
if (BaseRequest.Static
|
||||
|| EncodingHelper.IsCopyCodec(OutputVideoCodec))
|
||||
{
|
||||
return VideoStream == null ? null : (VideoStream.AverageFrameRate ?? VideoStream.RealFrameRate);
|
||||
return VideoStream is null ? null : (VideoStream.AverageFrameRate ?? VideoStream.RealFrameRate);
|
||||
}
|
||||
|
||||
return BaseRequest.MaxFramerate ?? BaseRequest.Framerate;
|
||||
@@ -419,7 +418,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VideoStream == null)
|
||||
if (VideoStream is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -437,7 +436,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (AudioStream == null)
|
||||
if (AudioStream is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -556,7 +555,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced)
|
||||
{
|
||||
var videoStream = VideoStream;
|
||||
var isInputInterlaced = videoStream != null && videoStream.IsInterlaced;
|
||||
var isInputInterlaced = videoStream is not null && videoStream.IsInterlaced;
|
||||
|
||||
if (!isInputInterlaced)
|
||||
{
|
||||
@@ -645,8 +644,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
if (!string.IsNullOrEmpty(codec))
|
||||
{
|
||||
var value = BaseRequest.GetOption(codec, "maxrefframes");
|
||||
if (!string.IsNullOrEmpty(value)
|
||||
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
||||
if (int.TryParse(value, CultureInfo.InvariantCulture, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -665,8 +663,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
if (!string.IsNullOrEmpty(codec))
|
||||
{
|
||||
var value = BaseRequest.GetOption(codec, "videobitdepth");
|
||||
if (!string.IsNullOrEmpty(value)
|
||||
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
||||
if (int.TryParse(value, CultureInfo.InvariantCulture, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -685,8 +682,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
if (!string.IsNullOrEmpty(codec))
|
||||
{
|
||||
var value = BaseRequest.GetOption(codec, "audiobitdepth");
|
||||
if (!string.IsNullOrEmpty(value)
|
||||
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
||||
if (int.TryParse(value, CultureInfo.InvariantCulture, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -700,8 +696,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
if (!string.IsNullOrEmpty(codec))
|
||||
{
|
||||
var value = BaseRequest.GetOption(codec, "audiochannels");
|
||||
if (!string.IsNullOrEmpty(value)
|
||||
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
||||
if (int.TryParse(value, CultureInfo.InvariantCulture, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
Version EncoderVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether p key pausing is supported.
|
||||
/// Gets a value indicating whether p key pausing is supported.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if p key pausing is supported, <c>false</c> otherwise.</value>
|
||||
bool IsPkeyPauseSupported { get; }
|
||||
@@ -153,6 +153,14 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
/// <returns>System.String.</returns>
|
||||
string GetInputArgument(string inputFile, MediaSourceInfo mediaSource);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the input argument.
|
||||
/// </summary>
|
||||
/// <param name="inputFiles">The input files.</param>
|
||||
/// <param name="mediaSource">The mediaSource.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
string GetInputArgument(IReadOnlyList<string> inputFiles, MediaSourceInfo mediaSource);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the input argument for an external subtitle file.
|
||||
/// </summary>
|
||||
@@ -194,6 +202,20 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
/// <param name="path">The to the .vob files.</param>
|
||||
/// <param name="titleNumber">The title number to start with.</param>
|
||||
/// <returns>A playlist.</returns>
|
||||
IEnumerable<string> GetPrimaryPlaylistVobFiles(string path, uint? titleNumber);
|
||||
IReadOnlyList<string> GetPrimaryPlaylistVobFiles(string path, uint? titleNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the primary playlist of .m2ts files.
|
||||
/// </summary>
|
||||
/// <param name="path">The to the .m2ts files.</param>
|
||||
/// <returns>A playlist.</returns>
|
||||
IReadOnlyList<string> GetPrimaryPlaylistM2tsFiles(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a FFmpeg concat config for the source.
|
||||
/// </summary>
|
||||
/// <param name="source">The <see cref="MediaSourceInfo"/>.</param>
|
||||
/// <param name="concatFilePath">The path the config should be written to.</param>
|
||||
void GenerateConcatConfig(MediaSourceInfo source, string concatFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
var rate = parts[i + 1];
|
||||
|
||||
if (float.TryParse(rate, NumberStyles.Any, CultureInfo.InvariantCulture, out var val))
|
||||
if (float.TryParse(rate, CultureInfo.InvariantCulture, out var val))
|
||||
{
|
||||
framerate = val;
|
||||
}
|
||||
@@ -95,7 +95,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
var rate = part.Split('=', 2)[^1];
|
||||
|
||||
if (float.TryParse(rate, NumberStyles.Any, CultureInfo.InvariantCulture, out var val))
|
||||
if (float.TryParse(rate, CultureInfo.InvariantCulture, out var val))
|
||||
{
|
||||
framerate = val;
|
||||
}
|
||||
@@ -127,7 +127,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
if (scale.HasValue)
|
||||
{
|
||||
if (long.TryParse(size, NumberStyles.Any, CultureInfo.InvariantCulture, out var val))
|
||||
if (long.TryParse(size, CultureInfo.InvariantCulture, out var val))
|
||||
{
|
||||
bytesTranscoded = val * scale.Value;
|
||||
}
|
||||
@@ -146,7 +146,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
if (scale.HasValue)
|
||||
{
|
||||
if (float.TryParse(rate, NumberStyles.Any, CultureInfo.InvariantCulture, out var val))
|
||||
if (float.TryParse(rate, CultureInfo.InvariantCulture, out var val))
|
||||
{
|
||||
bitRate = (int)Math.Ceiling(val * scale.Value);
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ namespace MediaBrowser.Controller.Net
|
||||
|
||||
var data = await GetDataToSend().ConfigureAwait(false);
|
||||
|
||||
if (data != null)
|
||||
if (data is not null)
|
||||
{
|
||||
await connection.SendAsync(
|
||||
new WebSocketMessage<TReturnDataType>
|
||||
@@ -204,7 +204,7 @@ namespace MediaBrowser.Controller.Net
|
||||
{
|
||||
var connection = _activeConnections.FirstOrDefault(c => c.Item1 == message.Connection);
|
||||
|
||||
if (connection != null)
|
||||
if (connection is not null)
|
||||
{
|
||||
DisposeConnection(connection);
|
||||
}
|
||||
@@ -227,9 +227,15 @@ namespace MediaBrowser.Controller.Net
|
||||
connection.Item2.Cancel();
|
||||
connection.Item2.Dispose();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
catch (ObjectDisposedException ex)
|
||||
{
|
||||
// TODO Investigate and properly fix.
|
||||
Logger.LogError(ex, "Object Disposed");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// TODO Investigate and properly fix.
|
||||
Logger.LogError(ex, "Error disposing websocket");
|
||||
}
|
||||
|
||||
lock (_activeConnections)
|
||||
|
||||
28
MediaBrowser.Controller/Net/WebSocketMessage.cs
Normal file
28
MediaBrowser.Controller/Net/WebSocketMessage.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net;
|
||||
|
||||
/// <summary>
|
||||
/// Websocket message without data.
|
||||
/// </summary>
|
||||
public abstract class WebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the message.
|
||||
/// TODO make this abstract and get only.
|
||||
/// </summary>
|
||||
public virtual SessionMessageType MessageType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message id.
|
||||
/// </summary>
|
||||
public Guid MessageId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the server id.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public string? ServerId { get; set; }
|
||||
}
|
||||
33
MediaBrowser.Controller/Net/WebSocketMessageOfT.cs
Normal file
33
MediaBrowser.Controller/Net/WebSocketMessageOfT.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma warning disable SA1649 // File name must equal class name.
|
||||
|
||||
namespace MediaBrowser.Controller.Net;
|
||||
|
||||
/// <summary>
|
||||
/// Class WebSocketMessage.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data.</typeparam>
|
||||
// TODO make this abstract, remove empty ctor.
|
||||
public class WebSocketMessage<T> : WebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebSocketMessage{T}"/> class.
|
||||
/// </summary>
|
||||
public WebSocketMessage()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebSocketMessage{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to send.</param>
|
||||
protected WebSocketMessage(T data)
|
||||
{
|
||||
Data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data.
|
||||
/// </summary>
|
||||
// TODO make this set only.
|
||||
public T? Data { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma warning disable CA1040
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages;
|
||||
|
||||
/// <summary>
|
||||
/// Interface representing that the websocket message is inbound.
|
||||
/// </summary>
|
||||
public interface IInboundWebSocketMessage
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma warning disable CA1040
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages;
|
||||
|
||||
/// <summary>
|
||||
/// Interface representing that the websocket message is outbound.
|
||||
/// </summary>
|
||||
public interface IOutboundWebSocketMessage
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Activity;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Inbound;
|
||||
|
||||
/// <summary>
|
||||
/// Activity log entry start message.
|
||||
/// </summary>
|
||||
public class ActivityLogEntryStartMessage : WebSocketMessage<IReadOnlyCollection<ActivityLogEntry>>, IInboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ActivityLogEntryStartMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Collection of activity log entries.</param>
|
||||
public ActivityLogEntryStartMessage(IReadOnlyCollection<ActivityLogEntry> data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.ActivityLogEntryStart)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.ActivityLogEntryStart;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Activity;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Inbound;
|
||||
|
||||
/// <summary>
|
||||
/// Activity log entry stop message.
|
||||
/// </summary>
|
||||
public class ActivityLogEntryStopMessage : WebSocketMessage<IReadOnlyCollection<ActivityLogEntry>>, IInboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ActivityLogEntryStopMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Collection of activity log entries.</param>
|
||||
public ActivityLogEntryStopMessage(IReadOnlyCollection<ActivityLogEntry> data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.ActivityLogEntryStop)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.ActivityLogEntryStop;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Inbound;
|
||||
|
||||
/// <summary>
|
||||
/// Scheduled tasks info start message.
|
||||
/// </summary>
|
||||
public class ScheduledTasksInfoStartMessage : WebSocketMessage<IReadOnlyCollection<TaskInfo>>, IInboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ScheduledTasksInfoStartMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Collection of task info.</param>
|
||||
public ScheduledTasksInfoStartMessage(IReadOnlyCollection<TaskInfo> data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.ScheduledTasksInfoStart)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.ScheduledTasksInfoStart;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Inbound;
|
||||
|
||||
/// <summary>
|
||||
/// Scheduled tasks info stop message.
|
||||
/// </summary>
|
||||
public class ScheduledTasksInfoStopMessage : WebSocketMessage<IReadOnlyCollection<TaskInfo>>, IInboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ScheduledTasksInfoStopMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Collection of task info.</param>
|
||||
public ScheduledTasksInfoStopMessage(IReadOnlyCollection<TaskInfo> data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.ScheduledTasksInfoStop)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.ScheduledTasksInfoStop;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Inbound;
|
||||
|
||||
/// <summary>
|
||||
/// Sessions start message.
|
||||
/// </summary>
|
||||
public class SessionsStartMessage : WebSocketMessage<SessionInfo>, IInboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SessionsStartMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Session info.</param>
|
||||
public SessionsStartMessage(SessionInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.SessionsStart)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.SessionsStart;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Inbound;
|
||||
|
||||
/// <summary>
|
||||
/// Sessions stop message.
|
||||
/// </summary>
|
||||
public class SessionsStopMessage : WebSocketMessage<SessionInfo>, IInboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SessionsStopMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Session info.</param>
|
||||
public SessionsStopMessage(SessionInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.SessionsStop)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.SessionsStop;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages;
|
||||
|
||||
/// <summary>
|
||||
/// Class representing the list of outbound websocket message types.
|
||||
/// Only used in openapi generation.
|
||||
/// </summary>
|
||||
public class InboundWebSocketMessage : WebSocketMessage
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Activity;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Activity log created message.
|
||||
/// </summary>
|
||||
public class ActivityLogEntryMessage : WebSocketMessage<IReadOnlyList<ActivityLogEntry>>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ActivityLogEntryMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">List of activity log entries.</param>
|
||||
public ActivityLogEntryMessage(IReadOnlyList<ActivityLogEntry> data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.ActivityLogEntry)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.ActivityLogEntry;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Force keep alive websocket messages.
|
||||
/// </summary>
|
||||
public class ForceKeepAliveMessage : WebSocketMessage<int>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ForceKeepAliveMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The timeout in seconds.</param>
|
||||
public ForceKeepAliveMessage(int data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.ForceKeepAlive)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.ForceKeepAlive;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// General command websocket message.
|
||||
/// </summary>
|
||||
public class GeneralCommandMessage : WebSocketMessage<GeneralCommand>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeneralCommandMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The general command.</param>
|
||||
public GeneralCommandMessage(GeneralCommand data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.GeneralCommand)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.GeneralCommand;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Library changed message.
|
||||
/// </summary>
|
||||
public class LibraryChangedMessage : WebSocketMessage<LibraryUpdateInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LibraryChangedMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The library update info.</param>
|
||||
public LibraryChangedMessage(LibraryUpdateInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.LibraryChanged)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.LibraryChanged;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Play command websocket message.
|
||||
/// </summary>
|
||||
public class PlayMessage : WebSocketMessage<PlayRequest>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlayMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The play request.</param>
|
||||
public PlayMessage(PlayRequest data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.Play)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.Play;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Playstate message.
|
||||
/// </summary>
|
||||
public class PlaystateMessage : WebSocketMessage<PlaystateRequest>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlaystateMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Playstate request data.</param>
|
||||
public PlaystateMessage(PlaystateRequest data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.Playstate)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.Playstate;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.Updates;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installation cancelled message.
|
||||
/// </summary>
|
||||
public class PluginInstallationCancelledMessage : WebSocketMessage<InstallationInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginInstallationCancelledMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Installation info.</param>
|
||||
public PluginInstallationCancelledMessage(InstallationInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.PackageInstallationCancelled)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.PackageInstallationCancelled;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.Updates;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installation completed message.
|
||||
/// </summary>
|
||||
public class PluginInstallationCompletedMessage : WebSocketMessage<InstallationInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginInstallationCompletedMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Installation info.</param>
|
||||
public PluginInstallationCompletedMessage(InstallationInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.PackageInstallationCompleted)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.PackageInstallationCompleted;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.Updates;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installation failed message.
|
||||
/// </summary>
|
||||
public class PluginInstallationFailedMessage : WebSocketMessage<InstallationInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginInstallationFailedMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Installation info.</param>
|
||||
public PluginInstallationFailedMessage(InstallationInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.PackageInstallationFailed)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.PackageInstallationFailed;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.Updates;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Package installing message.
|
||||
/// </summary>
|
||||
public class PluginInstallingMessage : WebSocketMessage<InstallationInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginInstallingMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Installation info.</param>
|
||||
public PluginInstallingMessage(InstallationInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.PackageInstalling)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.PackageInstalling;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Plugins;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin uninstalled message.
|
||||
/// </summary>
|
||||
public class PluginUninstalledMessage : WebSocketMessage<PluginInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginUninstalledMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Plugin info.</param>
|
||||
public PluginUninstalledMessage(PluginInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.PackageUninstalled)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.PackageUninstalled;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Refresh progress message.
|
||||
/// </summary>
|
||||
public class RefreshProgressMessage : WebSocketMessage<Dictionary<string, string>>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RefreshProgressMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Refresh progress data.</param>
|
||||
public RefreshProgressMessage(Dictionary<string, string> data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.RefreshProgress)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.RefreshProgress;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Restart required.
|
||||
/// </summary>
|
||||
public class RestartRequiredMessage : WebSocketMessage, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.RestartRequired)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.RestartRequired;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Scheduled task ended message.
|
||||
/// </summary>
|
||||
public class ScheduledTaskEndedMessage : WebSocketMessage<TaskResult>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ScheduledTaskEndedMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Task result.</param>
|
||||
public ScheduledTaskEndedMessage(TaskResult data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.ScheduledTaskEnded)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.ScheduledTaskEnded;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Scheduled tasks info message.
|
||||
/// </summary>
|
||||
public class ScheduledTasksInfoMessage : WebSocketMessage<IReadOnlyList<TaskInfo>>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ScheduledTasksInfoMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">List of task infos.</param>
|
||||
public ScheduledTasksInfoMessage(IReadOnlyList<TaskInfo> data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.ScheduledTasksInfo)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.ScheduledTasksInfo;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Series timer cancelled message.
|
||||
/// </summary>
|
||||
public class SeriesTimerCancelledMessage : WebSocketMessage<TimerEventInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SeriesTimerCancelledMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The timer event info.</param>
|
||||
public SeriesTimerCancelledMessage(TimerEventInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.SeriesTimerCancelled)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.SeriesTimerCancelled;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Series timer created message.
|
||||
/// </summary>
|
||||
public class SeriesTimerCreatedMessage : WebSocketMessage<TimerEventInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SeriesTimerCreatedMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">timer event info.</param>
|
||||
public SeriesTimerCreatedMessage(TimerEventInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.SeriesTimerCreated)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.SeriesTimerCreated;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Server restarting down message.
|
||||
/// </summary>
|
||||
public class ServerRestartingMessage : WebSocketMessage, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.ServerRestarting)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.ServerRestarting;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Server shutting down message.
|
||||
/// </summary>
|
||||
public class ServerShuttingDownMessage : WebSocketMessage, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.ServerShuttingDown)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.ServerShuttingDown;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Sessions message.
|
||||
/// </summary>
|
||||
public class SessionsMessage : WebSocketMessage<SessionInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SessionsMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Session info.</param>
|
||||
public SessionsMessage(SessionInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.Sessions)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.Sessions;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.SyncPlay;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Sync play command.
|
||||
/// </summary>
|
||||
public class SyncPlayCommandMessage : WebSocketMessage<SendCommand>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SyncPlayCommandMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The send command.</param>
|
||||
public SyncPlayCommandMessage(SendCommand data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.SyncPlayCommand)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.SyncPlayCommand;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.SyncPlay;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Untyped sync play command.
|
||||
/// </summary>
|
||||
public class SyncPlayGroupUpdateCommandMessage : WebSocketMessage<GroupUpdate>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SyncPlayGroupUpdateCommandMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The send command.</param>
|
||||
public SyncPlayGroupUpdateCommandMessage(GroupUpdate data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.SyncPlayGroupUpdate)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.SyncPlayGroupUpdate;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.SyncPlay;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Sync play group update command with group info.
|
||||
/// GroupUpdateTypes: GroupJoined.
|
||||
/// </summary>
|
||||
public class SyncPlayGroupUpdateCommandOfGroupInfoMessage : WebSocketMessage<GroupUpdate<GroupInfoDto>>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SyncPlayGroupUpdateCommandOfGroupInfoMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The group info.</param>
|
||||
public SyncPlayGroupUpdateCommandOfGroupInfoMessage(GroupUpdate<GroupInfoDto> data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.SyncPlayGroupUpdate)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.SyncPlayGroupUpdate;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.SyncPlay;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Sync play group update command with group state update.
|
||||
/// GroupUpdateTypes: StateUpdate.
|
||||
/// </summary>
|
||||
public class SyncPlayGroupUpdateCommandOfGroupStateUpdateMessage : WebSocketMessage<GroupUpdate<GroupStateUpdate>>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SyncPlayGroupUpdateCommandOfGroupStateUpdateMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The group info.</param>
|
||||
public SyncPlayGroupUpdateCommandOfGroupStateUpdateMessage(GroupUpdate<GroupStateUpdate> data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.SyncPlayGroupUpdate)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.SyncPlayGroupUpdate;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.SyncPlay;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Sync play group update command with play queue update.
|
||||
/// GroupUpdateTypes: PlayQueue.
|
||||
/// </summary>
|
||||
public class SyncPlayGroupUpdateCommandOfPlayQueueUpdateMessage : WebSocketMessage<GroupUpdate<PlayQueueUpdate>>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SyncPlayGroupUpdateCommandOfPlayQueueUpdateMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The play queue update.</param>
|
||||
public SyncPlayGroupUpdateCommandOfPlayQueueUpdateMessage(GroupUpdate<PlayQueueUpdate> data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.SyncPlayGroupUpdate)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.SyncPlayGroupUpdate;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.SyncPlay;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Sync play group update command with string.
|
||||
/// GroupUpdateTypes: GroupDoesNotExist (error), LibraryAccessDenied (error), NotInGroup (error), GroupLeft (groupId), UserJoined (username), UserLeft (username).
|
||||
/// </summary>
|
||||
public class SyncPlayGroupUpdateCommandOfStringMessage : WebSocketMessage<GroupUpdate<string>>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SyncPlayGroupUpdateCommandOfStringMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The send command.</param>
|
||||
public SyncPlayGroupUpdateCommandOfStringMessage(GroupUpdate<string> data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.SyncPlayGroupUpdate)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.SyncPlayGroupUpdate;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Timer cancelled message.
|
||||
/// </summary>
|
||||
public class TimerCancelledMessage : WebSocketMessage<TimerEventInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TimerCancelledMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Timer event info.</param>
|
||||
public TimerCancelledMessage(TimerEventInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.TimerCancelled)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.TimerCancelled;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// Timer created message.
|
||||
/// </summary>
|
||||
public class TimerCreatedMessage : WebSocketMessage<TimerEventInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TimerCreatedMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Timer event info.</param>
|
||||
public TimerCreatedMessage(TimerEventInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.TimerCreated)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.TimerCreated;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// User data changed message.
|
||||
/// </summary>
|
||||
public class UserDataChangedMessage : WebSocketMessage<UserDataChangeInfo>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserDataChangedMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The data change info.</param>
|
||||
public UserDataChangedMessage(UserDataChangeInfo data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.UserDataChanged)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.UserDataChanged;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// User deleted message.
|
||||
/// </summary>
|
||||
public class UserDeletedMessage : WebSocketMessage<Guid>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserDeletedMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The user id.</param>
|
||||
public UserDeletedMessage(Guid data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.UserDeleted)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.UserDeleted;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
|
||||
|
||||
/// <summary>
|
||||
/// User updated message.
|
||||
/// </summary>
|
||||
public class UserUpdatedMessage : WebSocketMessage<UserDto>, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserUpdatedMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The user dto.</param>
|
||||
public UserUpdatedMessage(UserDto data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.UserUpdated)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.UserUpdated;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages;
|
||||
|
||||
/// <summary>
|
||||
/// Class representing the list of outbound websocket message types.
|
||||
/// Only used in openapi generation.
|
||||
/// </summary>
|
||||
public class OutboundWebSocketMessage : WebSocketMessage
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.ComponentModel;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
namespace MediaBrowser.Controller.Net.WebSocketMessages.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// Keep alive websocket messages.
|
||||
/// </summary>
|
||||
public class KeepAliveMessage : WebSocketMessage<int>, IInboundWebSocketMessage, IOutboundWebSocketMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="KeepAliveMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The seconds to keep alive for.</param>
|
||||
public KeepAliveMessage(int data)
|
||||
: base(data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DefaultValue(SessionMessageType.KeepAlive)]
|
||||
public override SessionMessageType MessageType => SessionMessageType.KeepAlive;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Notifications;
|
||||
|
||||
namespace MediaBrowser.Controller.Notifications
|
||||
{
|
||||
public interface INotificationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends the notification.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task SendNotification(NotificationRequest request, CancellationToken cancellationToken);
|
||||
|
||||
Task SendNotification(NotificationRequest request, BaseItem? relatedItem, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the parts.
|
||||
/// </summary>
|
||||
/// <param name="services">The services.</param>
|
||||
/// <param name="notificationTypeFactories">The notification type factories.</param>
|
||||
void AddParts(IEnumerable<INotificationService> services, IEnumerable<INotificationTypeFactory> notificationTypeFactories);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the notification types.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{NotificationTypeInfo}.</returns>
|
||||
List<NotificationTypeInfo> GetNotificationTypes();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the notification services.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{NotificationServiceInfo}.</returns>
|
||||
IEnumerable<NameIdPair> GetNotificationServices();
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Data.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Notifications
|
||||
{
|
||||
public interface INotificationService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sends the notification.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task SendNotification(UserNotification request, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is enabled for user] [the specified user identifier].
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns><c>true</c> if [is enabled for user] [the specified user identifier]; otherwise, <c>false</c>.</returns>
|
||||
bool IsEnabledForUser(User user);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.Notifications;
|
||||
|
||||
namespace MediaBrowser.Controller.Notifications
|
||||
{
|
||||
public interface INotificationTypeFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the notification types.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{NotificationTypeInfo}.</returns>
|
||||
IEnumerable<NotificationTypeInfo> GetNotificationTypes();
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using Jellyfin.Data.Entities;
|
||||
using MediaBrowser.Model.Notifications;
|
||||
|
||||
namespace MediaBrowser.Controller.Notifications
|
||||
{
|
||||
public class UserNotification
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
public NotificationLevel Level { get; set; }
|
||||
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
public User User { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ namespace MediaBrowser.Controller.Persistence
|
||||
/// </summary>
|
||||
/// <param name="items">The items.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
void SaveItems(IEnumerable<BaseItem> items, CancellationToken cancellationToken);
|
||||
void SaveItems(IReadOnlyList<BaseItem> items, CancellationToken cancellationToken);
|
||||
|
||||
void SaveImages(BaseItem item);
|
||||
|
||||
|
||||
@@ -56,5 +56,19 @@ namespace MediaBrowser.Controller.Playlists
|
||||
/// <param name="newIndex">The new index.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task MoveItemAsync(string playlistId, string entryId, int newIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Removed all playlists of a user.
|
||||
/// If the playlist is shared, ownership is transferred.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task RemovePlaylistsAsync(Guid userId);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a playlist.
|
||||
/// </summary>
|
||||
/// <param name="item">The playlist.</param>
|
||||
void SavePlaylistFile(Playlist item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Querying;
|
||||
|
||||
namespace MediaBrowser.Controller.Playlists
|
||||
@@ -33,10 +34,13 @@ namespace MediaBrowser.Controller.Playlists
|
||||
public Playlist()
|
||||
{
|
||||
Shares = Array.Empty<Share>();
|
||||
OpenAccess = false;
|
||||
}
|
||||
|
||||
public Guid OwnerUserId { get; set; }
|
||||
|
||||
public bool OpenAccess { get; set; }
|
||||
|
||||
public Share[] Shares { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
@@ -165,7 +169,7 @@ namespace MediaBrowser.Controller.Playlists
|
||||
|
||||
public static List<BaseItem> GetPlaylistItems(string playlistMediaType, IEnumerable<BaseItem> inputItems, User user, DtoOptions options)
|
||||
{
|
||||
if (user != null)
|
||||
if (user is not null)
|
||||
{
|
||||
inputItems = inputItems.Where(i => i.IsVisible(user));
|
||||
}
|
||||
@@ -232,7 +236,13 @@ namespace MediaBrowser.Controller.Playlists
|
||||
return base.IsVisible(user);
|
||||
}
|
||||
|
||||
if (user.Id.Equals(OwnerUserId))
|
||||
if (OpenAccess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var userId = user.Id;
|
||||
if (userId.Equals(OwnerUserId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -240,10 +250,9 @@ namespace MediaBrowser.Controller.Playlists
|
||||
var shares = Shares;
|
||||
if (shares.Length == 0)
|
||||
{
|
||||
return base.IsVisible(user);
|
||||
return false;
|
||||
}
|
||||
|
||||
var userId = user.Id;
|
||||
return shares.Any(share => Guid.TryParse(share.UserId, out var id) && id.Equals(userId));
|
||||
}
|
||||
|
||||
|
||||
@@ -12,10 +12,13 @@ namespace MediaBrowser.Controller.Providers
|
||||
public EpisodeInfo()
|
||||
{
|
||||
SeriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
SeasonProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public Dictionary<string, string> SeriesProviderIds { get; set; }
|
||||
|
||||
public Dictionary<string, string> SeasonProviderIds { get; set; }
|
||||
|
||||
public int? IndexNumberEnd { get; set; }
|
||||
|
||||
public bool IsMissingEpisode { get; set; }
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IHasOrder.
|
||||
/// </summary>
|
||||
public interface IHasOrder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the order.
|
||||
/// </summary>
|
||||
/// <value>The order.</value>
|
||||
int Order { get; }
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user