Merge branch 'master' into segment-deletion

This commit is contained in:
Dominik
2023-06-15 19:38:42 +02:00
committed by GitHub
1007 changed files with 41859 additions and 38419 deletions

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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.

View File

@@ -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 &&

View File

@@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.Drawing
{
var imageInfo = item.GetImageInfo(imageType, imageIndex);
if (imageInfo == null)
if (imageInfo is null)
{
return null;
}

View File

@@ -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);
}
}

View File

@@ -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)
};

View File

@@ -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()

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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
{

View File

@@ -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))
{

View File

@@ -1,11 +0,0 @@
#nullable disable
#pragma warning disable CA1819, CS1591
namespace MediaBrowser.Controller.Entities
{
public interface IHasShares
{
Share[] Shares { get; set; }
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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()

View File

@@ -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]

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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; }
}
}

View File

@@ -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
{

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -105,7 +105,7 @@ namespace MediaBrowser.Controller.Entities
{
get
{
if (Rating != null)
if (Rating is not null)
{
return Rating >= MinLikeValue;
}

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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)));

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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>

View File

@@ -429,10 +429,16 @@ namespace MediaBrowser.Controller.Library
/// Gets the collection folders.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>IEnumerable&lt;Folder&gt;.</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);

View File

@@ -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.

View File

@@ -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;

View File

@@ -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));
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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))
{

View File

@@ -1,5 +1,3 @@
using System;
namespace MediaBrowser.Controller.Lyrics;
/// <summary>

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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)

View 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; }
}

View 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; }
}

View File

@@ -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
{
}

View File

@@ -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
{
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
{
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
{
}

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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; }
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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));
}

View File

@@ -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; }

View File

@@ -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