mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-05-24 02:02:29 -04:00
Merge branch 'master' into NetworkPR2
This commit is contained in:
commit
ec245dce90
@ -62,6 +62,7 @@ jobs:
|
|||||||
|
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
displayName: 'Download Reference Assembly Build Artifact'
|
displayName: 'Download Reference Assembly Build Artifact'
|
||||||
|
enabled: false
|
||||||
inputs:
|
inputs:
|
||||||
source: "specific"
|
source: "specific"
|
||||||
artifact: "$(NugetPackageName)"
|
artifact: "$(NugetPackageName)"
|
||||||
@ -73,6 +74,7 @@ jobs:
|
|||||||
|
|
||||||
- task: CopyFiles@2
|
- task: CopyFiles@2
|
||||||
displayName: 'Copy Reference Assembly Build Artifact'
|
displayName: 'Copy Reference Assembly Build Artifact'
|
||||||
|
enabled: false
|
||||||
inputs:
|
inputs:
|
||||||
sourceFolder: $(System.ArtifactsDirectory)/current-artifacts
|
sourceFolder: $(System.ArtifactsDirectory)/current-artifacts
|
||||||
contents: '**/*.dll'
|
contents: '**/*.dll'
|
||||||
@ -83,6 +85,7 @@ jobs:
|
|||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
- task: DotNetCoreCLI@2
|
||||||
displayName: 'Execute ABI Compatibility Check Tool'
|
displayName: 'Execute ABI Compatibility Check Tool'
|
||||||
|
enabled: false
|
||||||
inputs:
|
inputs:
|
||||||
command: custom
|
command: custom
|
||||||
custom: compat
|
custom: compat
|
||||||
|
@ -487,7 +487,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
User = user,
|
User = user,
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
IsMissing = false,
|
IsMissing = false,
|
||||||
ExcludeItemTypes = new[] { typeof(Book).Name },
|
ExcludeItemTypes = new[] { nameof(Book) },
|
||||||
IsFolder = isFolder,
|
IsFolder = isFolder,
|
||||||
MediaTypes = mediaTypes,
|
MediaTypes = mediaTypes,
|
||||||
DtoOptions = GetDtoOptions()
|
DtoOptions = GetDtoOptions()
|
||||||
@ -556,7 +556,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
Limit = limit,
|
Limit = limit,
|
||||||
StartIndex = startIndex,
|
StartIndex = startIndex,
|
||||||
IsVirtualItem = false,
|
IsVirtualItem = false,
|
||||||
ExcludeItemTypes = new[] { typeof(Book).Name },
|
ExcludeItemTypes = new[] { nameof(Book) },
|
||||||
IsPlaceHolder = false,
|
IsPlaceHolder = false,
|
||||||
DtoOptions = GetDtoOptions()
|
DtoOptions = GetDtoOptions()
|
||||||
};
|
};
|
||||||
@ -575,7 +575,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
StartIndex = startIndex,
|
StartIndex = startIndex,
|
||||||
Limit = limit,
|
Limit = limit,
|
||||||
};
|
};
|
||||||
query.IncludeItemTypes = new[] { typeof(LiveTvChannel).Name };
|
query.IncludeItemTypes = new[] { nameof(LiveTvChannel) };
|
||||||
|
|
||||||
SetSorting(query, sort, false);
|
SetSorting(query, sort, false);
|
||||||
|
|
||||||
@ -910,7 +910,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(Series).Name };
|
query.IncludeItemTypes = new[] { nameof(Series) };
|
||||||
|
|
||||||
var result = _libraryManager.GetItemsResult(query);
|
var result = _libraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
@ -923,7 +923,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
query.IncludeItemTypes = new[] { nameof(Movie) };
|
||||||
|
|
||||||
var result = _libraryManager.GetItemsResult(query);
|
var result = _libraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
@ -936,7 +936,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
// query.Parent = parent;
|
// query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(BoxSet).Name };
|
query.IncludeItemTypes = new[] { nameof(BoxSet) };
|
||||||
|
|
||||||
var result = _libraryManager.GetItemsResult(query);
|
var result = _libraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
@ -949,7 +949,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(MusicAlbum).Name };
|
query.IncludeItemTypes = new[] { nameof(MusicAlbum) };
|
||||||
|
|
||||||
var result = _libraryManager.GetItemsResult(query);
|
var result = _libraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
@ -962,7 +962,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(Audio).Name };
|
query.IncludeItemTypes = new[] { nameof(Audio) };
|
||||||
|
|
||||||
var result = _libraryManager.GetItemsResult(query);
|
var result = _libraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
@ -975,7 +975,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.IsFavorite = true;
|
query.IsFavorite = true;
|
||||||
query.IncludeItemTypes = new[] { typeof(Audio).Name };
|
query.IncludeItemTypes = new[] { nameof(Audio) };
|
||||||
|
|
||||||
var result = _libraryManager.GetItemsResult(query);
|
var result = _libraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
@ -988,7 +988,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.IsFavorite = true;
|
query.IsFavorite = true;
|
||||||
query.IncludeItemTypes = new[] { typeof(Series).Name };
|
query.IncludeItemTypes = new[] { nameof(Series) };
|
||||||
|
|
||||||
var result = _libraryManager.GetItemsResult(query);
|
var result = _libraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
@ -1001,7 +1001,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.IsFavorite = true;
|
query.IsFavorite = true;
|
||||||
query.IncludeItemTypes = new[] { typeof(Episode).Name };
|
query.IncludeItemTypes = new[] { nameof(Episode) };
|
||||||
|
|
||||||
var result = _libraryManager.GetItemsResult(query);
|
var result = _libraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
@ -1014,7 +1014,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.IsFavorite = true;
|
query.IsFavorite = true;
|
||||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
query.IncludeItemTypes = new[] { nameof(Movie) };
|
||||||
|
|
||||||
var result = _libraryManager.GetItemsResult(query);
|
var result = _libraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
@ -1027,7 +1027,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.IsFavorite = true;
|
query.IsFavorite = true;
|
||||||
query.IncludeItemTypes = new[] { typeof(MusicAlbum).Name };
|
query.IncludeItemTypes = new[] { nameof(MusicAlbum) };
|
||||||
|
|
||||||
var result = _libraryManager.GetItemsResult(query);
|
var result = _libraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
@ -1181,7 +1181,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
{
|
{
|
||||||
UserId = user.Id,
|
UserId = user.Id,
|
||||||
Limit = 50,
|
Limit = 50,
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name },
|
IncludeItemTypes = new[] { nameof(Episode) },
|
||||||
ParentId = parent == null ? Guid.Empty : parent.Id,
|
ParentId = parent == null ? Guid.Empty : parent.Id,
|
||||||
GroupItems = false
|
GroupItems = false
|
||||||
},
|
},
|
||||||
@ -1215,7 +1215,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
Recursive = true,
|
Recursive = true,
|
||||||
ParentId = parentId,
|
ParentId = parentId,
|
||||||
ArtistIds = new[] { item.Id },
|
ArtistIds = new[] { item.Id },
|
||||||
IncludeItemTypes = new[] { typeof(MusicAlbum).Name },
|
IncludeItemTypes = new[] { nameof(MusicAlbum) },
|
||||||
Limit = limit,
|
Limit = limit,
|
||||||
StartIndex = startIndex,
|
StartIndex = startIndex,
|
||||||
DtoOptions = GetDtoOptions()
|
DtoOptions = GetDtoOptions()
|
||||||
@ -1259,7 +1259,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
Recursive = true,
|
Recursive = true,
|
||||||
ParentId = parentId,
|
ParentId = parentId,
|
||||||
GenreIds = new[] { item.Id },
|
GenreIds = new[] { item.Id },
|
||||||
IncludeItemTypes = new[] { typeof(MusicAlbum).Name },
|
IncludeItemTypes = new[] { nameof(MusicAlbum) },
|
||||||
Limit = limit,
|
Limit = limit,
|
||||||
StartIndex = startIndex,
|
StartIndex = startIndex,
|
||||||
DtoOptions = GetDtoOptions()
|
DtoOptions = GetDtoOptions()
|
||||||
|
@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.AppBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string VirtualDataPath { get; } = "%AppDataPath%";
|
public string VirtualDataPath => "%AppDataPath%";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the image cache path.
|
/// Gets the image cache path.
|
||||||
|
@ -349,7 +349,7 @@ namespace Emby.Server.Implementations
|
|||||||
/// Gets the email address for use within a comment section of a user agent field.
|
/// Gets the email address for use within a comment section of a user agent field.
|
||||||
/// Presently used to provide contact information to MusicBrainz service.
|
/// Presently used to provide contact information to MusicBrainz service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ApplicationUserAgentAddress { get; } = "team@jellyfin.org";
|
public string ApplicationUserAgentAddress => "team@jellyfin.org";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the current application name.
|
/// Gets the current application name.
|
||||||
|
@ -543,7 +543,7 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
return _libraryManager.GetItemIds(
|
return _libraryManager.GetItemIds(
|
||||||
new InternalItemsQuery
|
new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Channel).Name },
|
IncludeItemTypes = new[] { nameof(Channel) },
|
||||||
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }
|
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }
|
||||||
}).Select(i => GetChannelFeatures(i.ToString("N", CultureInfo.InvariantCulture))).ToArray();
|
}).Select(i => GetChannelFeatures(i.ToString("N", CultureInfo.InvariantCulture))).ToArray();
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
|
|
||||||
var uninstalledChannels = _libraryManager.GetItemList(new InternalItemsQuery
|
var uninstalledChannels = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Channel).Name },
|
IncludeItemTypes = new[] { nameof(Channel) },
|
||||||
ExcludeItemIds = installedChannelIds.ToArray()
|
ExcludeItemIds = installedChannelIds.ToArray()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3914,7 +3914,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
if (query.IsPlayed.HasValue)
|
if (query.IsPlayed.HasValue)
|
||||||
{
|
{
|
||||||
// We should probably figure this out for all folders, but for right now, this is the only place where we need it
|
// We should probably figure this out for all folders, but for right now, this is the only place where we need it
|
||||||
if (query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], typeof(Series).Name, StringComparison.OrdinalIgnoreCase))
|
if (query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], nameof(Series), StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (query.IsPlayed.Value)
|
if (query.IsPlayed.Value)
|
||||||
{
|
{
|
||||||
@ -4755,29 +4755,29 @@ namespace Emby.Server.Implementations.Data
|
|||||||
{
|
{
|
||||||
var list = new List<string>();
|
var list = new List<string>();
|
||||||
|
|
||||||
if (IsTypeInQuery(typeof(Person).Name, query))
|
if (IsTypeInQuery(nameof(Person), query))
|
||||||
{
|
{
|
||||||
list.Add(typeof(Person).Name);
|
list.Add(nameof(Person));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsTypeInQuery(typeof(Genre).Name, query))
|
if (IsTypeInQuery(nameof(Genre), query))
|
||||||
{
|
{
|
||||||
list.Add(typeof(Genre).Name);
|
list.Add(nameof(Genre));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsTypeInQuery(typeof(MusicGenre).Name, query))
|
if (IsTypeInQuery(nameof(MusicGenre), query))
|
||||||
{
|
{
|
||||||
list.Add(typeof(MusicGenre).Name);
|
list.Add(nameof(MusicGenre));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsTypeInQuery(typeof(MusicArtist).Name, query))
|
if (IsTypeInQuery(nameof(MusicArtist), query))
|
||||||
{
|
{
|
||||||
list.Add(typeof(MusicArtist).Name);
|
list.Add(nameof(MusicArtist));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsTypeInQuery(typeof(Studio).Name, query))
|
if (IsTypeInQuery(nameof(Studio), query))
|
||||||
{
|
{
|
||||||
list.Add(typeof(Studio).Name);
|
list.Add(nameof(Studio));
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
@ -4832,12 +4832,12 @@ namespace Emby.Server.Implementations.Data
|
|||||||
|
|
||||||
var types = new[]
|
var types = new[]
|
||||||
{
|
{
|
||||||
typeof(Episode).Name,
|
nameof(Episode),
|
||||||
typeof(Video).Name,
|
nameof(Video),
|
||||||
typeof(Movie).Name,
|
nameof(Movie),
|
||||||
typeof(MusicVideo).Name,
|
nameof(MusicVideo),
|
||||||
typeof(Series).Name,
|
nameof(Series),
|
||||||
typeof(Season).Name
|
nameof(Season)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)))
|
if (types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)))
|
||||||
|
@ -465,7 +465,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
{
|
{
|
||||||
var parentAlbumIds = _libraryManager.GetItemIds(new InternalItemsQuery
|
var parentAlbumIds = _libraryManager.GetItemIds(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(MusicAlbum).Name },
|
IncludeItemTypes = new[] { nameof(MusicAlbum) },
|
||||||
Name = item.Album,
|
Name = item.Album,
|
||||||
Limit = 1
|
Limit = 1
|
||||||
});
|
});
|
||||||
|
@ -267,7 +267,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
|||||||
if (param.Length == 2)
|
if (param.Length == 2)
|
||||||
{
|
{
|
||||||
var value = NormalizeValue(param[1].Trim(new[] { '"' }));
|
var value = NormalizeValue(param[1].Trim(new[] { '"' }));
|
||||||
result.Add(param[0], value);
|
result[param[0]] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ namespace Emby.Server.Implementations.Images
|
|||||||
// return _libraryManager.GetItemList(new InternalItemsQuery
|
// return _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
// {
|
// {
|
||||||
// ArtistIds = new[] { item.Id },
|
// ArtistIds = new[] { item.Id },
|
||||||
// IncludeItemTypes = new[] { typeof(MusicAlbum).Name },
|
// IncludeItemTypes = new[] { nameof(MusicAlbum) },
|
||||||
// OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
|
// OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
|
||||||
// Limit = 4,
|
// Limit = 4,
|
||||||
// Recursive = true,
|
// Recursive = true,
|
||||||
|
@ -42,7 +42,12 @@ namespace Emby.Server.Implementations.Images
|
|||||||
return _libraryManager.GetItemList(new InternalItemsQuery
|
return _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
Genres = new[] { item.Name },
|
Genres = new[] { item.Name },
|
||||||
IncludeItemTypes = new[] { typeof(MusicAlbum).Name, typeof(MusicVideo).Name, typeof(Audio).Name },
|
IncludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
nameof(MusicAlbum),
|
||||||
|
nameof(MusicVideo),
|
||||||
|
nameof(Audio)
|
||||||
|
},
|
||||||
OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
|
OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
|
||||||
Limit = 4,
|
Limit = 4,
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
@ -77,7 +82,7 @@ namespace Emby.Server.Implementations.Images
|
|||||||
return _libraryManager.GetItemList(new InternalItemsQuery
|
return _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
Genres = new[] { item.Name },
|
Genres = new[] { item.Name },
|
||||||
IncludeItemTypes = new[] { typeof(Series).Name, typeof(Movie).Name },
|
IncludeItemTypes = new[] { nameof(Series), nameof(Movie) },
|
||||||
OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
|
OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
|
||||||
Limit = 4,
|
Limit = 4,
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
|
@ -49,7 +49,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
var genres = item
|
var genres = item
|
||||||
.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Audio).Name },
|
IncludeItemTypes = new[] { nameof(Audio) },
|
||||||
DtoOptions = dtoOptions
|
DtoOptions = dtoOptions
|
||||||
})
|
})
|
||||||
.Cast<Audio>()
|
.Cast<Audio>()
|
||||||
@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
{
|
{
|
||||||
return _libraryManager.GetItemList(new InternalItemsQuery(user)
|
return _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Audio).Name },
|
IncludeItemTypes = new[] { nameof(Audio) },
|
||||||
|
|
||||||
GenreIds = genreIds.ToArray(),
|
GenreIds = genreIds.ToArray(),
|
||||||
|
|
||||||
|
@ -87,61 +87,61 @@ namespace Emby.Server.Implementations.Library
|
|||||||
var excludeItemTypes = query.ExcludeItemTypes.ToList();
|
var excludeItemTypes = query.ExcludeItemTypes.ToList();
|
||||||
var includeItemTypes = (query.IncludeItemTypes ?? Array.Empty<string>()).ToList();
|
var includeItemTypes = (query.IncludeItemTypes ?? Array.Empty<string>()).ToList();
|
||||||
|
|
||||||
excludeItemTypes.Add(typeof(Year).Name);
|
excludeItemTypes.Add(nameof(Year));
|
||||||
excludeItemTypes.Add(typeof(Folder).Name);
|
excludeItemTypes.Add(nameof(Folder));
|
||||||
|
|
||||||
if (query.IncludeGenres && (includeItemTypes.Count == 0 || includeItemTypes.Contains("Genre", StringComparer.OrdinalIgnoreCase)))
|
if (query.IncludeGenres && (includeItemTypes.Count == 0 || includeItemTypes.Contains("Genre", StringComparer.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
if (!query.IncludeMedia)
|
if (!query.IncludeMedia)
|
||||||
{
|
{
|
||||||
AddIfMissing(includeItemTypes, typeof(Genre).Name);
|
AddIfMissing(includeItemTypes, nameof(Genre));
|
||||||
AddIfMissing(includeItemTypes, typeof(MusicGenre).Name);
|
AddIfMissing(includeItemTypes, nameof(MusicGenre));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddIfMissing(excludeItemTypes, typeof(Genre).Name);
|
AddIfMissing(excludeItemTypes, nameof(Genre));
|
||||||
AddIfMissing(excludeItemTypes, typeof(MusicGenre).Name);
|
AddIfMissing(excludeItemTypes, nameof(MusicGenre));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IncludePeople && (includeItemTypes.Count == 0 || includeItemTypes.Contains("People", StringComparer.OrdinalIgnoreCase) || includeItemTypes.Contains("Person", StringComparer.OrdinalIgnoreCase)))
|
if (query.IncludePeople && (includeItemTypes.Count == 0 || includeItemTypes.Contains("People", StringComparer.OrdinalIgnoreCase) || includeItemTypes.Contains("Person", StringComparer.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
if (!query.IncludeMedia)
|
if (!query.IncludeMedia)
|
||||||
{
|
{
|
||||||
AddIfMissing(includeItemTypes, typeof(Person).Name);
|
AddIfMissing(includeItemTypes, nameof(Person));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddIfMissing(excludeItemTypes, typeof(Person).Name);
|
AddIfMissing(excludeItemTypes, nameof(Person));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IncludeStudios && (includeItemTypes.Count == 0 || includeItemTypes.Contains("Studio", StringComparer.OrdinalIgnoreCase)))
|
if (query.IncludeStudios && (includeItemTypes.Count == 0 || includeItemTypes.Contains("Studio", StringComparer.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
if (!query.IncludeMedia)
|
if (!query.IncludeMedia)
|
||||||
{
|
{
|
||||||
AddIfMissing(includeItemTypes, typeof(Studio).Name);
|
AddIfMissing(includeItemTypes, nameof(Studio));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddIfMissing(excludeItemTypes, typeof(Studio).Name);
|
AddIfMissing(excludeItemTypes, nameof(Studio));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IncludeArtists && (includeItemTypes.Count == 0 || includeItemTypes.Contains("MusicArtist", StringComparer.OrdinalIgnoreCase)))
|
if (query.IncludeArtists && (includeItemTypes.Count == 0 || includeItemTypes.Contains("MusicArtist", StringComparer.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
if (!query.IncludeMedia)
|
if (!query.IncludeMedia)
|
||||||
{
|
{
|
||||||
AddIfMissing(includeItemTypes, typeof(MusicArtist).Name);
|
AddIfMissing(includeItemTypes, nameof(MusicArtist));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddIfMissing(excludeItemTypes, typeof(MusicArtist).Name);
|
AddIfMissing(excludeItemTypes, nameof(MusicArtist));
|
||||||
}
|
}
|
||||||
|
|
||||||
AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name);
|
AddIfMissing(excludeItemTypes, nameof(CollectionFolder));
|
||||||
AddIfMissing(excludeItemTypes, typeof(Folder).Name);
|
AddIfMissing(excludeItemTypes, nameof(Folder));
|
||||||
var mediaTypes = query.MediaTypes.ToList();
|
var mediaTypes = query.MediaTypes.ToList();
|
||||||
|
|
||||||
if (includeItemTypes.Count > 0)
|
if (includeItemTypes.Count > 0)
|
||||||
|
@ -81,7 +81,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
|||||||
|
|
||||||
var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery
|
var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(MusicArtist).Name },
|
IncludeItemTypes = new[] { nameof(MusicArtist) },
|
||||||
IsDeadArtist = true,
|
IsDeadArtist = true,
|
||||||
IsLocked = false
|
IsLocked = false
|
||||||
}).Cast<MusicArtist>().ToList();
|
}).Cast<MusicArtist>().ToList();
|
||||||
|
@ -91,7 +91,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
|||||||
|
|
||||||
var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery
|
var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Person).Name },
|
IncludeItemTypes = new[] { nameof(Person) },
|
||||||
IsDeadPerson = true,
|
IsDeadPerson = true,
|
||||||
IsLocked = false
|
IsLocked = false
|
||||||
});
|
});
|
||||||
|
@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
|||||||
|
|
||||||
var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery
|
var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Studio).Name },
|
IncludeItemTypes = new[] { nameof(Studio) },
|
||||||
IsDeadStudio = true,
|
IsDeadStudio = true,
|
||||||
IsLocked = false
|
IsLocked = false
|
||||||
});
|
});
|
||||||
|
@ -1790,7 +1790,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
{
|
{
|
||||||
var program = string.IsNullOrWhiteSpace(timer.ProgramId) ? null : _libraryManager.GetItemList(new InternalItemsQuery
|
var program = string.IsNullOrWhiteSpace(timer.ProgramId) ? null : _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new[] { nameof(LiveTvProgram) },
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
ExternalId = timer.ProgramId,
|
ExternalId = timer.ProgramId,
|
||||||
DtoOptions = new DtoOptions(true)
|
DtoOptions = new DtoOptions(true)
|
||||||
@ -2151,7 +2151,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
{
|
{
|
||||||
var query = new InternalItemsQuery
|
var query = new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new string[] { nameof(LiveTvProgram) },
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
DtoOptions = new DtoOptions(true)
|
DtoOptions = new DtoOptions(true)
|
||||||
{
|
{
|
||||||
@ -2370,7 +2370,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
var query = new InternalItemsQuery
|
var query = new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new string[] { nameof(LiveTvProgram) },
|
||||||
ExternalSeriesId = seriesTimer.SeriesId,
|
ExternalSeriesId = seriesTimer.SeriesId,
|
||||||
DtoOptions = new DtoOptions(true)
|
DtoOptions = new DtoOptions(true)
|
||||||
{
|
{
|
||||||
@ -2405,7 +2405,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
channel = _libraryManager.GetItemList(
|
channel = _libraryManager.GetItemList(
|
||||||
new InternalItemsQuery
|
new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name },
|
IncludeItemTypes = new string[] { nameof(LiveTvChannel) },
|
||||||
ItemIds = new[] { parent.ChannelId },
|
ItemIds = new[] { parent.ChannelId },
|
||||||
DtoOptions = new DtoOptions()
|
DtoOptions = new DtoOptions()
|
||||||
}).FirstOrDefault() as LiveTvChannel;
|
}).FirstOrDefault() as LiveTvChannel;
|
||||||
@ -2464,7 +2464,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
channel = _libraryManager.GetItemList(
|
channel = _libraryManager.GetItemList(
|
||||||
new InternalItemsQuery
|
new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name },
|
IncludeItemTypes = new string[] { nameof(LiveTvChannel) },
|
||||||
ItemIds = new[] { programInfo.ChannelId },
|
ItemIds = new[] { programInfo.ChannelId },
|
||||||
DtoOptions = new DtoOptions()
|
DtoOptions = new DtoOptions()
|
||||||
}).FirstOrDefault() as LiveTvChannel;
|
}).FirstOrDefault() as LiveTvChannel;
|
||||||
@ -2529,7 +2529,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
var seriesIds = _libraryManager.GetItemIds(
|
var seriesIds = _libraryManager.GetItemIds(
|
||||||
new InternalItemsQuery
|
new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Series).Name },
|
IncludeItemTypes = new[] { nameof(Series) },
|
||||||
Name = program.Name
|
Name = program.Name
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
|
||||||
@ -2542,7 +2542,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
{
|
{
|
||||||
var result = _libraryManager.GetItemIds(new InternalItemsQuery
|
var result = _libraryManager.GetItemIds(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name },
|
IncludeItemTypes = new[] { nameof(Episode) },
|
||||||
ParentIndexNumber = program.SeasonNumber.Value,
|
ParentIndexNumber = program.SeasonNumber.Value,
|
||||||
IndexNumber = program.EpisodeNumber.Value,
|
IndexNumber = program.EpisodeNumber.Value,
|
||||||
AncestorIds = seriesIds,
|
AncestorIds = seriesIds,
|
||||||
|
@ -159,7 +159,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
{
|
{
|
||||||
var librarySeries = _libraryManager.GetItemList(new InternalItemsQuery
|
var librarySeries = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new string[] { typeof(Series).Name },
|
IncludeItemTypes = new string[] { nameof(Series) },
|
||||||
Name = seriesName,
|
Name = seriesName,
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
ImageTypes = new ImageType[] { ImageType.Thumb },
|
ImageTypes = new ImageType[] { ImageType.Thumb },
|
||||||
@ -253,7 +253,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
{
|
{
|
||||||
var librarySeries = _libraryManager.GetItemList(new InternalItemsQuery
|
var librarySeries = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new string[] { typeof(Series).Name },
|
IncludeItemTypes = new string[] { nameof(Series) },
|
||||||
Name = seriesName,
|
Name = seriesName,
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
ImageTypes = new ImageType[] { ImageType.Thumb },
|
ImageTypes = new ImageType[] { ImageType.Thumb },
|
||||||
@ -296,7 +296,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var program = _libraryManager.GetItemList(new InternalItemsQuery
|
var program = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new string[] { typeof(Series).Name },
|
IncludeItemTypes = new string[] { nameof(Series) },
|
||||||
Name = seriesName,
|
Name = seriesName,
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
ImageTypes = new ImageType[] { ImageType.Primary },
|
ImageTypes = new ImageType[] { ImageType.Primary },
|
||||||
@ -307,7 +307,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
{
|
{
|
||||||
program = _libraryManager.GetItemList(new InternalItemsQuery
|
program = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new string[] { nameof(LiveTvProgram) },
|
||||||
ExternalSeriesId = programSeriesId,
|
ExternalSeriesId = programSeriesId,
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
ImageTypes = new ImageType[] { ImageType.Primary },
|
ImageTypes = new ImageType[] { ImageType.Primary },
|
||||||
|
@ -187,7 +187,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
IsKids = query.IsKids,
|
IsKids = query.IsKids,
|
||||||
IsSports = query.IsSports,
|
IsSports = query.IsSports,
|
||||||
IsSeries = query.IsSeries,
|
IsSeries = query.IsSeries,
|
||||||
IncludeItemTypes = new[] { typeof(LiveTvChannel).Name },
|
IncludeItemTypes = new[] { nameof(LiveTvChannel) },
|
||||||
TopParentIds = new[] { topFolder.Id },
|
TopParentIds = new[] { topFolder.Id },
|
||||||
IsFavorite = query.IsFavorite,
|
IsFavorite = query.IsFavorite,
|
||||||
IsLiked = query.IsLiked,
|
IsLiked = query.IsLiked,
|
||||||
@ -808,7 +808,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var internalQuery = new InternalItemsQuery(user)
|
var internalQuery = new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new[] { nameof(LiveTvProgram) },
|
||||||
MinEndDate = query.MinEndDate,
|
MinEndDate = query.MinEndDate,
|
||||||
MinStartDate = query.MinStartDate,
|
MinStartDate = query.MinStartDate,
|
||||||
MaxEndDate = query.MaxEndDate,
|
MaxEndDate = query.MaxEndDate,
|
||||||
@ -872,7 +872,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var internalQuery = new InternalItemsQuery(user)
|
var internalQuery = new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new[] { nameof(LiveTvProgram) },
|
||||||
IsAiring = query.IsAiring,
|
IsAiring = query.IsAiring,
|
||||||
HasAired = query.HasAired,
|
HasAired = query.HasAired,
|
||||||
IsNews = query.IsNews,
|
IsNews = query.IsNews,
|
||||||
@ -1089,8 +1089,8 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
if (cleanDatabase)
|
if (cleanDatabase)
|
||||||
{
|
{
|
||||||
CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken);
|
CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { nameof(LiveTvChannel) }, progress, cancellationToken);
|
||||||
CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken);
|
CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { nameof(LiveTvProgram) }, progress, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
var coreService = _services.OfType<EmbyTV.EmbyTV>().FirstOrDefault();
|
var coreService = _services.OfType<EmbyTV.EmbyTV>().FirstOrDefault();
|
||||||
@ -1181,7 +1181,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var existingPrograms = _libraryManager.GetItemList(new InternalItemsQuery
|
var existingPrograms = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new string[] { nameof(LiveTvProgram) },
|
||||||
ChannelIds = new Guid[] { currentChannel.Id },
|
ChannelIds = new Guid[] { currentChannel.Id },
|
||||||
DtoOptions = new DtoOptions(true)
|
DtoOptions = new DtoOptions(true)
|
||||||
}).Cast<LiveTvProgram>().ToDictionary(i => i.Id);
|
}).Cast<LiveTvProgram>().ToDictionary(i => i.Id);
|
||||||
@ -1346,11 +1346,11 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
{
|
{
|
||||||
if (query.IsMovie.Value)
|
if (query.IsMovie.Value)
|
||||||
{
|
{
|
||||||
includeItemTypes.Add(typeof(Movie).Name);
|
includeItemTypes.Add(nameof(Movie));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
excludeItemTypes.Add(typeof(Movie).Name);
|
excludeItemTypes.Add(nameof(Movie));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1358,11 +1358,11 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
{
|
{
|
||||||
if (query.IsSeries.Value)
|
if (query.IsSeries.Value)
|
||||||
{
|
{
|
||||||
includeItemTypes.Add(typeof(Episode).Name);
|
includeItemTypes.Add(nameof(Episode));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
excludeItemTypes.Add(typeof(Episode).Name);
|
excludeItemTypes.Add(nameof(Episode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1883,7 +1883,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var programs = options.AddCurrentProgram ? _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var programs = options.AddCurrentProgram ? _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new[] { nameof(LiveTvProgram) },
|
||||||
ChannelIds = channelIds,
|
ChannelIds = channelIds,
|
||||||
MaxStartDate = now,
|
MaxStartDate = now,
|
||||||
MinEndDate = now,
|
MinEndDate = now,
|
||||||
|
@ -95,6 +95,8 @@
|
|||||||
"TasksLibraryCategory": "Library",
|
"TasksLibraryCategory": "Library",
|
||||||
"TasksApplicationCategory": "Application",
|
"TasksApplicationCategory": "Application",
|
||||||
"TasksChannelsCategory": "Internet Channels",
|
"TasksChannelsCategory": "Internet Channels",
|
||||||
|
"TaskCleanActivityLog": "Clean Activity Log",
|
||||||
|
"TaskCleanActivityLogDescription": "Deletes activity log entries older than the configured age.",
|
||||||
"TaskCleanCache": "Clean Cache Directory",
|
"TaskCleanCache": "Clean Cache Directory",
|
||||||
"TaskCleanCacheDescription": "Deletes cache files no longer needed by the system.",
|
"TaskCleanCacheDescription": "Deletes cache files no longer needed by the system.",
|
||||||
"TaskRefreshChapterImages": "Extract Chapter Images",
|
"TaskRefreshChapterImages": "Extract Chapter Images",
|
||||||
|
@ -703,7 +703,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
MaxRuntimeTicks = info.MaxRuntimeTicks
|
MaxRuntimeTicks = info.MaxRuntimeTicks
|
||||||
};
|
};
|
||||||
|
|
||||||
if (info.Type.Equals(typeof(DailyTrigger).Name, StringComparison.OrdinalIgnoreCase))
|
if (info.Type.Equals(nameof(DailyTrigger), StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (!info.TimeOfDayTicks.HasValue)
|
if (!info.TimeOfDayTicks.HasValue)
|
||||||
{
|
{
|
||||||
@ -717,7 +717,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.Type.Equals(typeof(WeeklyTrigger).Name, StringComparison.OrdinalIgnoreCase))
|
if (info.Type.Equals(nameof(WeeklyTrigger), StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (!info.TimeOfDayTicks.HasValue)
|
if (!info.TimeOfDayTicks.HasValue)
|
||||||
{
|
{
|
||||||
@ -737,7 +737,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.Type.Equals(typeof(IntervalTrigger).Name, StringComparison.OrdinalIgnoreCase))
|
if (info.Type.Equals(nameof(IntervalTrigger), StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (!info.IntervalTicks.HasValue)
|
if (!info.IntervalTicks.HasValue)
|
||||||
{
|
{
|
||||||
@ -751,7 +751,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.Type.Equals(typeof(StartupTrigger).Name, StringComparison.OrdinalIgnoreCase))
|
if (info.Type.Equals(nameof(StartupTrigger), StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return new StartupTrigger();
|
return new StartupTrigger();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.Tasks;
|
||||||
|
|
||||||
|
namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes old activity log entries.
|
||||||
|
/// </summary>
|
||||||
|
public class CleanActivityLogTask : IScheduledTask, IConfigurableScheduledTask
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localization;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
private readonly IServerConfigurationManager _serverConfigurationManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CleanActivityLogTask"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
|
||||||
|
/// <param name="activityManager">Instance of the <see cref="IActivityManager"/> interface.</param>
|
||||||
|
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
|
||||||
|
public CleanActivityLogTask(
|
||||||
|
ILocalizationManager localization,
|
||||||
|
IActivityManager activityManager,
|
||||||
|
IServerConfigurationManager serverConfigurationManager)
|
||||||
|
{
|
||||||
|
_localization = localization;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
_serverConfigurationManager = serverConfigurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Name => _localization.GetLocalizedString("TaskCleanActivityLog");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Key => "CleanActivityLog";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Description => _localization.GetLocalizedString("TaskCleanActivityLogDescription");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsHidden => false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsEnabled => true;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsLogged => true;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
|
||||||
|
{
|
||||||
|
var retentionDays = _serverConfigurationManager.Configuration.ActivityLogRetentionDays;
|
||||||
|
if (!retentionDays.HasValue || retentionDays <= 0)
|
||||||
|
{
|
||||||
|
throw new Exception($"Activity Log Retention days must be at least 0. Currently: {retentionDays}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var startDate = DateTime.UtcNow.AddDays(retentionDays.Value * -1);
|
||||||
|
return _activityManager.CleanAsync(startDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||||
|
{
|
||||||
|
return Enumerable.Empty<TaskTriggerInfo>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -104,6 +104,6 @@ namespace Emby.Server.Implementations
|
|||||||
public string InternalMetadataPath { get; set; }
|
public string InternalMetadataPath { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string VirtualInternalMetadataPath { get; } = "%MetadataPath%";
|
public string VirtualInternalMetadataPath => "%MetadataPath%";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ namespace Emby.Server.Implementations.TV
|
|||||||
.GetItemList(
|
.GetItemList(
|
||||||
new InternalItemsQuery(user)
|
new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name },
|
IncludeItemTypes = new[] { nameof(Episode) },
|
||||||
OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.DatePlayed, SortOrder.Descending) },
|
OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.DatePlayed, SortOrder.Descending) },
|
||||||
SeriesPresentationUniqueKey = presentationUniqueKey,
|
SeriesPresentationUniqueKey = presentationUniqueKey,
|
||||||
Limit = limit,
|
Limit = limit,
|
||||||
@ -214,7 +214,7 @@ namespace Emby.Server.Implementations.TV
|
|||||||
{
|
{
|
||||||
AncestorWithPresentationUniqueKey = null,
|
AncestorWithPresentationUniqueKey = null,
|
||||||
SeriesPresentationUniqueKey = seriesKey,
|
SeriesPresentationUniqueKey = seriesKey,
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name },
|
IncludeItemTypes = new[] { nameof(Episode) },
|
||||||
OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) },
|
OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) },
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
IsPlayed = false,
|
IsPlayed = false,
|
||||||
|
@ -10,6 +10,7 @@ using System.Runtime.Serialization;
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
@ -17,6 +18,8 @@ using MediaBrowser.Common.Plugins;
|
|||||||
using MediaBrowser.Common.Updates;
|
using MediaBrowser.Common.Updates;
|
||||||
using MediaBrowser.Common.System;
|
using MediaBrowser.Common.System;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Updates;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
@ -36,6 +39,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger<InstallationManager> _logger;
|
private readonly ILogger<InstallationManager> _logger;
|
||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
|
private readonly IEventManager _eventManager;
|
||||||
private readonly IHttpClientFactory _httpClientFactory;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
@ -65,23 +69,20 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
ILogger<InstallationManager> logger,
|
ILogger<InstallationManager> logger,
|
||||||
IApplicationHost appHost,
|
IApplicationHost appHost,
|
||||||
IApplicationPaths appPaths,
|
IApplicationPaths appPaths,
|
||||||
|
IEventManager eventManager,
|
||||||
IHttpClientFactory httpClientFactory,
|
IHttpClientFactory httpClientFactory,
|
||||||
IJsonSerializer jsonSerializer,
|
IJsonSerializer jsonSerializer,
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IZipClient zipClient)
|
IZipClient zipClient)
|
||||||
{
|
{
|
||||||
if (logger == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(logger));
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentInstallations = new List<(InstallationInfo, CancellationTokenSource)>();
|
_currentInstallations = new List<(InstallationInfo, CancellationTokenSource)>();
|
||||||
_completedInstallationsInternal = new ConcurrentBag<InstallationInfo>();
|
_completedInstallationsInternal = new ConcurrentBag<InstallationInfo>();
|
||||||
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_applicationHost = appHost;
|
_applicationHost = appHost;
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
|
_eventManager = eventManager;
|
||||||
_httpClientFactory = httpClientFactory;
|
_httpClientFactory = httpClientFactory;
|
||||||
_jsonSerializer = jsonSerializer;
|
_jsonSerializer = jsonSerializer;
|
||||||
_config = config;
|
_config = config;
|
||||||
@ -89,27 +90,6 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
_zipClient = zipClient;
|
_zipClient = zipClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event EventHandler<InstallationInfo> PackageInstalling;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event EventHandler<InstallationInfo> PackageInstallationCompleted;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event EventHandler<InstallationFailedEventArgs> PackageInstallationFailed;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event EventHandler<InstallationInfo> PackageInstallationCancelled;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event EventHandler<IPlugin> PluginUninstalled;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event EventHandler<InstallationInfo> PluginUpdated;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event EventHandler<InstallationInfo> PluginInstalled;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEnumerable<InstallationInfo> CompletedInstallations => _completedInstallationsInternal;
|
public IEnumerable<InstallationInfo> CompletedInstallations => _completedInstallationsInternal;
|
||||||
|
|
||||||
@ -268,11 +248,11 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
|
|
||||||
var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token;
|
var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token;
|
||||||
|
|
||||||
PackageInstalling?.Invoke(this, package);
|
await _eventManager.PublishAsync(new PluginInstallingEventArgs(package)).ConfigureAwait(false);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await InstallPackageInternal(package, linkedToken).ConfigureAwait(false);
|
var isUpdate = await InstallPackageInternal(package, linkedToken).ConfigureAwait(false);
|
||||||
|
|
||||||
lock (_currentInstallationsLock)
|
lock (_currentInstallationsLock)
|
||||||
{
|
{
|
||||||
@ -280,8 +260,11 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
}
|
}
|
||||||
|
|
||||||
_completedInstallationsInternal.Add(package);
|
_completedInstallationsInternal.Add(package);
|
||||||
|
await _eventManager.PublishAsync(isUpdate
|
||||||
|
? (GenericEventArgs<InstallationInfo>)new PluginUpdatedEventArgs(package)
|
||||||
|
: new PluginInstalledEventArgs(package)).ConfigureAwait(false);
|
||||||
|
|
||||||
PackageInstallationCompleted?.Invoke(this, package);
|
_applicationHost.NotifyPendingRestart();
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
@ -292,7 +275,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
|
|
||||||
_logger.LogInformation("Package installation cancelled: {0} {1}", package.Name, package.Version);
|
_logger.LogInformation("Package installation cancelled: {0} {1}", package.Name, package.Version);
|
||||||
|
|
||||||
PackageInstallationCancelled?.Invoke(this, package);
|
await _eventManager.PublishAsync(new PluginInstallationCancelledEventArgs(package)).ConfigureAwait(false);
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -305,11 +288,11 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
_currentInstallations.Remove(tuple);
|
_currentInstallations.Remove(tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageInstallationFailed?.Invoke(this, new InstallationFailedEventArgs
|
await _eventManager.PublishAsync(new InstallationFailedEventArgs
|
||||||
{
|
{
|
||||||
InstallationInfo = package,
|
InstallationInfo = package,
|
||||||
Exception = ex
|
Exception = ex
|
||||||
});
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -326,7 +309,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
/// <param name="package">The package.</param>
|
/// <param name="package">The package.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns><see cref="Task" />.</returns>
|
/// <returns><see cref="Task" />.</returns>
|
||||||
private async Task InstallPackageInternal(InstallationInfo package, CancellationToken cancellationToken)
|
private async Task<bool> InstallPackageInternal(InstallationInfo package, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// Set last update time if we were installed before
|
// Set last update time if we were installed before
|
||||||
IPlugin plugin = _applicationHost.Plugins.FirstOrDefault(p => p.Id == package.Guid)
|
IPlugin plugin = _applicationHost.Plugins.FirstOrDefault(p => p.Id == package.Guid)
|
||||||
@ -336,20 +319,9 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
await PerformPackageInstallation(package, cancellationToken).ConfigureAwait(false);
|
await PerformPackageInstallation(package, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
// Do plugin-specific processing
|
// Do plugin-specific processing
|
||||||
if (plugin == null)
|
_logger.LogInformation(plugin == null ? "New plugin installed: {0} {1}" : "Plugin updated: {0} {1}", package.Name, package.Version);
|
||||||
{
|
|
||||||
_logger.LogInformation("New plugin installed: {0} {1}", package.Name, package.Version);
|
|
||||||
|
|
||||||
PluginInstalled?.Invoke(this, package);
|
return plugin != null;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Plugin updated: {0} {1}", package.Name, package.Version);
|
|
||||||
|
|
||||||
PluginUpdated?.Invoke(this, package);
|
|
||||||
}
|
|
||||||
|
|
||||||
_applicationHost.NotifyPendingRestart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PerformPackageInstallation(InstallationInfo package, CancellationToken cancellationToken)
|
private async Task PerformPackageInstallation(InstallationInfo package, CancellationToken cancellationToken)
|
||||||
@ -467,7 +439,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
_config.SaveConfiguration();
|
_config.SaveConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginUninstalled?.Invoke(this, plugin);
|
_eventManager.Publish(new PluginUninstalledEventArgs(plugin));
|
||||||
|
|
||||||
_applicationHost.NotifyPendingRestart();
|
_applicationHost.NotifyPendingRestart();
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using Jellyfin.Api.Extensions;
|
using Jellyfin.Api.Extensions;
|
||||||
using Jellyfin.Api.Helpers;
|
using Jellyfin.Api.Helpers;
|
||||||
|
using Jellyfin.Api.ModelBinders;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
@ -90,7 +91,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] string? fields,
|
[FromQuery] string? fields,
|
||||||
[FromQuery] string? excludeItemTypes,
|
[FromQuery] string? excludeItemTypes,
|
||||||
[FromQuery] string? includeItemTypes,
|
[FromQuery] string? includeItemTypes,
|
||||||
[FromQuery] ItemFilter[] filters,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
|
||||||
[FromQuery] bool? isFavorite,
|
[FromQuery] bool? isFavorite,
|
||||||
[FromQuery] string? mediaTypes,
|
[FromQuery] string? mediaTypes,
|
||||||
[FromQuery] string? genres,
|
[FromQuery] string? genres,
|
||||||
@ -146,9 +147,9 @@ namespace Jellyfin.Api.Controllers
|
|||||||
NameLessThan = nameLessThan,
|
NameLessThan = nameLessThan,
|
||||||
NameStartsWith = nameStartsWith,
|
NameStartsWith = nameStartsWith,
|
||||||
NameStartsWithOrGreater = nameStartsWithOrGreater,
|
NameStartsWithOrGreater = nameStartsWithOrGreater,
|
||||||
Tags = RequestHelpers.Split(tags, ',', true),
|
Tags = RequestHelpers.Split(tags, '|', true),
|
||||||
OfficialRatings = RequestHelpers.Split(officialRatings, ',', true),
|
OfficialRatings = RequestHelpers.Split(officialRatings, '|', true),
|
||||||
Genres = RequestHelpers.Split(genres, ',', true),
|
Genres = RequestHelpers.Split(genres, '|', true),
|
||||||
GenreIds = RequestHelpers.GetGuids(genreIds),
|
GenreIds = RequestHelpers.GetGuids(genreIds),
|
||||||
StudioIds = RequestHelpers.GetGuids(studioIds),
|
StudioIds = RequestHelpers.GetGuids(studioIds),
|
||||||
Person = person,
|
Person = person,
|
||||||
@ -299,7 +300,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] string? fields,
|
[FromQuery] string? fields,
|
||||||
[FromQuery] string? excludeItemTypes,
|
[FromQuery] string? excludeItemTypes,
|
||||||
[FromQuery] string? includeItemTypes,
|
[FromQuery] string? includeItemTypes,
|
||||||
[FromQuery] ItemFilter[] filters,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
|
||||||
[FromQuery] bool? isFavorite,
|
[FromQuery] bool? isFavorite,
|
||||||
[FromQuery] string? mediaTypes,
|
[FromQuery] string? mediaTypes,
|
||||||
[FromQuery] string? genres,
|
[FromQuery] string? genres,
|
||||||
@ -355,9 +356,9 @@ namespace Jellyfin.Api.Controllers
|
|||||||
NameLessThan = nameLessThan,
|
NameLessThan = nameLessThan,
|
||||||
NameStartsWith = nameStartsWith,
|
NameStartsWith = nameStartsWith,
|
||||||
NameStartsWithOrGreater = nameStartsWithOrGreater,
|
NameStartsWithOrGreater = nameStartsWithOrGreater,
|
||||||
Tags = RequestHelpers.Split(tags, ',', true),
|
Tags = RequestHelpers.Split(tags, '|', true),
|
||||||
OfficialRatings = RequestHelpers.Split(officialRatings, ',', true),
|
OfficialRatings = RequestHelpers.Split(officialRatings, '|', true),
|
||||||
Genres = RequestHelpers.Split(genres, ',', true),
|
Genres = RequestHelpers.Split(genres, '|', true),
|
||||||
GenreIds = RequestHelpers.GetGuids(genreIds),
|
GenreIds = RequestHelpers.GetGuids(genreIds),
|
||||||
StudioIds = RequestHelpers.GetGuids(studioIds),
|
StudioIds = RequestHelpers.GetGuids(studioIds),
|
||||||
Person = person,
|
Person = person,
|
||||||
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
|||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using Jellyfin.Api.Extensions;
|
using Jellyfin.Api.Extensions;
|
||||||
using Jellyfin.Api.Helpers;
|
using Jellyfin.Api.Helpers;
|
||||||
|
using Jellyfin.Api.ModelBinders;
|
||||||
using MediaBrowser.Controller.Channels;
|
using MediaBrowser.Controller.Channels;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
@ -121,7 +122,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] int? startIndex,
|
[FromQuery] int? startIndex,
|
||||||
[FromQuery] int? limit,
|
[FromQuery] int? limit,
|
||||||
[FromQuery] string? sortOrder,
|
[FromQuery] string? sortOrder,
|
||||||
[FromQuery] ItemFilter[] filters,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
|
||||||
[FromQuery] string? sortBy,
|
[FromQuery] string? sortBy,
|
||||||
[FromQuery] string? fields)
|
[FromQuery] string? fields)
|
||||||
{
|
{
|
||||||
@ -196,7 +197,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] Guid? userId,
|
[FromQuery] Guid? userId,
|
||||||
[FromQuery] int? startIndex,
|
[FromQuery] int? startIndex,
|
||||||
[FromQuery] int? limit,
|
[FromQuery] int? limit,
|
||||||
[FromQuery] ItemFilter[] filters,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
|
||||||
[FromQuery] string? fields,
|
[FromQuery] string? fields,
|
||||||
[FromQuery] string? channelIds)
|
[FromQuery] string? channelIds)
|
||||||
{
|
{
|
||||||
|
@ -83,14 +83,14 @@ namespace Jellyfin.Api.Controllers
|
|||||||
/// Adds items to a collection.
|
/// Adds items to a collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="collectionId">The collection id.</param>
|
/// <param name="collectionId">The collection id.</param>
|
||||||
/// <param name="itemIds">Item ids, comma delimited.</param>
|
/// <param name="ids">Item ids, comma delimited.</param>
|
||||||
/// <response code="204">Items added to collection.</response>
|
/// <response code="204">Items added to collection.</response>
|
||||||
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
||||||
[HttpPost("{collectionId}/Items")]
|
[HttpPost("{collectionId}/Items")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public async Task<ActionResult> AddToCollection([FromRoute, Required] Guid collectionId, [FromQuery, Required] string itemIds)
|
public async Task<ActionResult> AddToCollection([FromRoute, Required] Guid collectionId, [FromQuery, Required] string ids)
|
||||||
{
|
{
|
||||||
await _collectionManager.AddToCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(true);
|
await _collectionManager.AddToCollectionAsync(collectionId, RequestHelpers.GetGuids(ids)).ConfigureAwait(true);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,14 +98,14 @@ namespace Jellyfin.Api.Controllers
|
|||||||
/// Removes items from a collection.
|
/// Removes items from a collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="collectionId">The collection id.</param>
|
/// <param name="collectionId">The collection id.</param>
|
||||||
/// <param name="itemIds">Item ids, comma delimited.</param>
|
/// <param name="ids">Item ids, comma delimited.</param>
|
||||||
/// <response code="204">Items removed from collection.</response>
|
/// <response code="204">Items removed from collection.</response>
|
||||||
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
||||||
[HttpDelete("{collectionId}/Items")]
|
[HttpDelete("{collectionId}/Items")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public async Task<ActionResult> RemoveFromCollection([FromRoute, Required] Guid collectionId, [FromQuery, Required] string itemIds)
|
public async Task<ActionResult> RemoveFromCollection([FromRoute, Required] Guid collectionId, [FromQuery, Required] string ids)
|
||||||
{
|
{
|
||||||
await _collectionManager.RemoveFromCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(false);
|
await _collectionManager.RemoveFromCollectionAsync(collectionId, RequestHelpers.GetGuids(ids)).ConfigureAwait(false);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using Jellyfin.Api.Extensions;
|
using Jellyfin.Api.Extensions;
|
||||||
using Jellyfin.Api.Helpers;
|
using Jellyfin.Api.Helpers;
|
||||||
|
using Jellyfin.Api.ModelBinders;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
@ -91,7 +92,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] string? fields,
|
[FromQuery] string? fields,
|
||||||
[FromQuery] string? excludeItemTypes,
|
[FromQuery] string? excludeItemTypes,
|
||||||
[FromQuery] string? includeItemTypes,
|
[FromQuery] string? includeItemTypes,
|
||||||
[FromQuery] ItemFilter[] filters,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
|
||||||
[FromQuery] bool? isFavorite,
|
[FromQuery] bool? isFavorite,
|
||||||
[FromQuery] string? mediaTypes,
|
[FromQuery] string? mediaTypes,
|
||||||
[FromQuery] string? genres,
|
[FromQuery] string? genres,
|
||||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using Jellyfin.Api.Extensions;
|
using Jellyfin.Api.Extensions;
|
||||||
using Jellyfin.Api.Helpers;
|
using Jellyfin.Api.Helpers;
|
||||||
|
using Jellyfin.Api.ModelBinders;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
@ -159,7 +160,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] bool? isHd,
|
[FromQuery] bool? isHd,
|
||||||
[FromQuery] bool? is4K,
|
[FromQuery] bool? is4K,
|
||||||
[FromQuery] string? locationTypes,
|
[FromQuery] string? locationTypes,
|
||||||
[FromQuery] LocationType[] excludeLocationTypes,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] LocationType[] excludeLocationTypes,
|
||||||
[FromQuery] bool? isMissing,
|
[FromQuery] bool? isMissing,
|
||||||
[FromQuery] bool? isUnaired,
|
[FromQuery] bool? isUnaired,
|
||||||
[FromQuery] double? minCommunityRating,
|
[FromQuery] double? minCommunityRating,
|
||||||
@ -182,7 +183,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] string? fields,
|
[FromQuery] string? fields,
|
||||||
[FromQuery] string? excludeItemTypes,
|
[FromQuery] string? excludeItemTypes,
|
||||||
[FromQuery] string? includeItemTypes,
|
[FromQuery] string? includeItemTypes,
|
||||||
[FromQuery] ItemFilter[] filters,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
|
||||||
[FromQuery] bool? isFavorite,
|
[FromQuery] bool? isFavorite,
|
||||||
[FromQuery] string? mediaTypes,
|
[FromQuery] string? mediaTypes,
|
||||||
[FromQuery] ImageType[] imageTypes,
|
[FromQuery] ImageType[] imageTypes,
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
|
using Jellyfin.Api.ModelBinders;
|
||||||
using Jellyfin.Api.Models.LibraryStructureDto;
|
using Jellyfin.Api.Models.LibraryStructureDto;
|
||||||
using MediaBrowser.Common.Progress;
|
using MediaBrowser.Common.Progress;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
@ -75,7 +76,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
public async Task<ActionResult> AddVirtualFolder(
|
public async Task<ActionResult> AddVirtualFolder(
|
||||||
[FromQuery] string? name,
|
[FromQuery] string? name,
|
||||||
[FromQuery] string? collectionType,
|
[FromQuery] string? collectionType,
|
||||||
[FromQuery] string[] paths,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] paths,
|
||||||
[FromBody] AddVirtualFolderDto? libraryOptionsDto,
|
[FromBody] AddVirtualFolderDto? libraryOptionsDto,
|
||||||
[FromQuery] bool refreshLibrary = false)
|
[FromQuery] bool refreshLibrary = false)
|
||||||
{
|
{
|
||||||
|
@ -592,7 +592,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
IsKids = isKids,
|
IsKids = isKids,
|
||||||
IsSports = isSports,
|
IsSports = isSports,
|
||||||
SeriesTimerId = seriesTimerId,
|
SeriesTimerId = seriesTimerId,
|
||||||
Genres = RequestHelpers.Split(genres, ',', true),
|
Genres = RequestHelpers.Split(genres, '|', true),
|
||||||
GenreIds = RequestHelpers.GetGuids(genreIds)
|
GenreIds = RequestHelpers.GetGuids(genreIds)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -648,7 +648,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
IsKids = body.IsKids,
|
IsKids = body.IsKids,
|
||||||
IsSports = body.IsSports,
|
IsSports = body.IsSports,
|
||||||
SeriesTimerId = body.SeriesTimerId,
|
SeriesTimerId = body.SeriesTimerId,
|
||||||
Genres = RequestHelpers.Split(body.Genres, ',', true),
|
Genres = RequestHelpers.Split(body.Genres, '|', true),
|
||||||
GenreIds = RequestHelpers.GetGuids(body.GenreIds)
|
GenreIds = RequestHelpers.GetGuids(body.GenreIds)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,8 +85,8 @@ namespace Jellyfin.Api.Controllers
|
|||||||
IncludeItemTypes = new[]
|
IncludeItemTypes = new[]
|
||||||
{
|
{
|
||||||
nameof(Movie),
|
nameof(Movie),
|
||||||
// typeof(Trailer).Name,
|
// nameof(Trailer),
|
||||||
// typeof(LiveTvProgram).Name
|
// nameof(LiveTvProgram)
|
||||||
},
|
},
|
||||||
// IsMovie = true
|
// IsMovie = true
|
||||||
OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
|
OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
|
||||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using Jellyfin.Api.Extensions;
|
using Jellyfin.Api.Extensions;
|
||||||
using Jellyfin.Api.Helpers;
|
using Jellyfin.Api.Helpers;
|
||||||
|
using Jellyfin.Api.ModelBinders;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
@ -90,7 +91,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] string? fields,
|
[FromQuery] string? fields,
|
||||||
[FromQuery] string? excludeItemTypes,
|
[FromQuery] string? excludeItemTypes,
|
||||||
[FromQuery] string? includeItemTypes,
|
[FromQuery] string? includeItemTypes,
|
||||||
[FromQuery] ItemFilter[] filters,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
|
||||||
[FromQuery] bool? isFavorite,
|
[FromQuery] bool? isFavorite,
|
||||||
[FromQuery] string? mediaTypes,
|
[FromQuery] string? mediaTypes,
|
||||||
[FromQuery] string? genres,
|
[FromQuery] string? genres,
|
||||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using Jellyfin.Api.Extensions;
|
using Jellyfin.Api.Extensions;
|
||||||
using Jellyfin.Api.Helpers;
|
using Jellyfin.Api.Helpers;
|
||||||
|
using Jellyfin.Api.ModelBinders;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
@ -90,7 +91,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] string? fields,
|
[FromQuery] string? fields,
|
||||||
[FromQuery] string? excludeItemTypes,
|
[FromQuery] string? excludeItemTypes,
|
||||||
[FromQuery] string? includeItemTypes,
|
[FromQuery] string? includeItemTypes,
|
||||||
[FromQuery] ItemFilter[] filters,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
|
||||||
[FromQuery] bool? isFavorite,
|
[FromQuery] bool? isFavorite,
|
||||||
[FromQuery] string? mediaTypes,
|
[FromQuery] string? mediaTypes,
|
||||||
[FromQuery] string? genres,
|
[FromQuery] string? genres,
|
||||||
|
@ -379,7 +379,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
public ActionResult PostCapabilities(
|
public ActionResult PostCapabilities(
|
||||||
[FromQuery] string? id,
|
[FromQuery] string? id,
|
||||||
[FromQuery] string? playableMediaTypes,
|
[FromQuery] string? playableMediaTypes,
|
||||||
[FromQuery] GeneralCommandType[] supportedCommands,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] GeneralCommandType[] supportedCommands,
|
||||||
[FromQuery] bool supportsMediaControl = false,
|
[FromQuery] bool supportsMediaControl = false,
|
||||||
[FromQuery] bool supportsSync = false,
|
[FromQuery] bool supportsSync = false,
|
||||||
[FromQuery] bool supportsPersistentIdentifier = true)
|
[FromQuery] bool supportsPersistentIdentifier = true)
|
||||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using Jellyfin.Api.Extensions;
|
using Jellyfin.Api.Extensions;
|
||||||
using Jellyfin.Api.Helpers;
|
using Jellyfin.Api.Helpers;
|
||||||
|
using Jellyfin.Api.ModelBinders;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
@ -89,7 +90,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] string? fields,
|
[FromQuery] string? fields,
|
||||||
[FromQuery] string? excludeItemTypes,
|
[FromQuery] string? excludeItemTypes,
|
||||||
[FromQuery] string? includeItemTypes,
|
[FromQuery] string? includeItemTypes,
|
||||||
[FromQuery] ItemFilter[] filters,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
|
||||||
[FromQuery] bool? isFavorite,
|
[FromQuery] bool? isFavorite,
|
||||||
[FromQuery] string? mediaTypes,
|
[FromQuery] string? mediaTypes,
|
||||||
[FromQuery] string? genres,
|
[FromQuery] string? genres,
|
||||||
@ -145,9 +146,9 @@ namespace Jellyfin.Api.Controllers
|
|||||||
NameLessThan = nameLessThan,
|
NameLessThan = nameLessThan,
|
||||||
NameStartsWith = nameStartsWith,
|
NameStartsWith = nameStartsWith,
|
||||||
NameStartsWithOrGreater = nameStartsWithOrGreater,
|
NameStartsWithOrGreater = nameStartsWithOrGreater,
|
||||||
Tags = RequestHelpers.Split(tags, ',', true),
|
Tags = RequestHelpers.Split(tags, '|', true),
|
||||||
OfficialRatings = RequestHelpers.Split(officialRatings, ',', true),
|
OfficialRatings = RequestHelpers.Split(officialRatings, '|', true),
|
||||||
Genres = RequestHelpers.Split(genres, ',', true),
|
Genres = RequestHelpers.Split(genres, '|', true),
|
||||||
GenreIds = RequestHelpers.GetGuids(genreIds),
|
GenreIds = RequestHelpers.GetGuids(genreIds),
|
||||||
StudioIds = RequestHelpers.GetGuids(studioIds),
|
StudioIds = RequestHelpers.GetGuids(studioIds),
|
||||||
Person = person,
|
Person = person,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
|
using Jellyfin.Api.ModelBinders;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
@ -125,7 +126,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] bool? isHd,
|
[FromQuery] bool? isHd,
|
||||||
[FromQuery] bool? is4K,
|
[FromQuery] bool? is4K,
|
||||||
[FromQuery] string? locationTypes,
|
[FromQuery] string? locationTypes,
|
||||||
[FromQuery] LocationType[] excludeLocationTypes,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] LocationType[] excludeLocationTypes,
|
||||||
[FromQuery] bool? isMissing,
|
[FromQuery] bool? isMissing,
|
||||||
[FromQuery] bool? isUnaired,
|
[FromQuery] bool? isUnaired,
|
||||||
[FromQuery] double? minCommunityRating,
|
[FromQuery] double? minCommunityRating,
|
||||||
@ -147,7 +148,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[FromQuery] string? parentId,
|
[FromQuery] string? parentId,
|
||||||
[FromQuery] string? fields,
|
[FromQuery] string? fields,
|
||||||
[FromQuery] string? excludeItemTypes,
|
[FromQuery] string? excludeItemTypes,
|
||||||
[FromQuery] ItemFilter[] filters,
|
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
|
||||||
[FromQuery] bool? isFavorite,
|
[FromQuery] bool? isFavorite,
|
||||||
[FromQuery] string? mediaTypes,
|
[FromQuery] string? mediaTypes,
|
||||||
[FromQuery] ImageType[] imageTypes,
|
[FromQuery] ImageType[] imageTypes,
|
||||||
|
@ -88,16 +88,14 @@ namespace Jellyfin.Api.Controllers
|
|||||||
/// <response code="302">Redirected to remote audio stream.</response>
|
/// <response code="302">Redirected to remote audio stream.</response>
|
||||||
/// <returns>A <see cref="Task"/> containing the audio file.</returns>
|
/// <returns>A <see cref="Task"/> containing the audio file.</returns>
|
||||||
[HttpGet("Audio/{itemId}/universal")]
|
[HttpGet("Audio/{itemId}/universal")]
|
||||||
[HttpGet("Audio/{itemId}/universal.{container}", Name = "GetUniversalAudioStream_2")]
|
|
||||||
[HttpHead("Audio/{itemId}/universal", Name = "HeadUniversalAudioStream")]
|
[HttpHead("Audio/{itemId}/universal", Name = "HeadUniversalAudioStream")]
|
||||||
[HttpHead("Audio/{itemId}/universal.{container}", Name = "HeadUniversalAudioStream_2")]
|
|
||||||
[Authorize(Policy = Policies.DefaultAuthorization)]
|
[Authorize(Policy = Policies.DefaultAuthorization)]
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status302Found)]
|
[ProducesResponseType(StatusCodes.Status302Found)]
|
||||||
[ProducesAudioFile]
|
[ProducesAudioFile]
|
||||||
public async Task<ActionResult> GetUniversalAudioStream(
|
public async Task<ActionResult> GetUniversalAudioStream(
|
||||||
[FromRoute, Required] Guid itemId,
|
[FromRoute, Required] Guid itemId,
|
||||||
[FromRoute] string? container,
|
[FromQuery] string? container,
|
||||||
[FromQuery] string? mediaSourceId,
|
[FromQuery] string? mediaSourceId,
|
||||||
[FromQuery] string? deviceId,
|
[FromQuery] string? deviceId,
|
||||||
[FromQuery] Guid? userId,
|
[FromQuery] Guid? userId,
|
||||||
@ -276,7 +274,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
|
|
||||||
foreach (var cont in containers)
|
foreach (var cont in containers)
|
||||||
{
|
{
|
||||||
var parts = RequestHelpers.Split(cont, ',', true);
|
var parts = RequestHelpers.Split(cont, '|', true);
|
||||||
|
|
||||||
var audioCodecs = parts.Length == 1 ? null : string.Join(",", parts.Skip(1).ToArray());
|
var audioCodecs = parts.Length == 1 ? null : string.Join(",", parts.Skip(1).ToArray());
|
||||||
|
|
||||||
|
@ -123,9 +123,8 @@ namespace Jellyfin.Api.Helpers
|
|||||||
state.Dispose();
|
state.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
await new ProgressiveFileCopier(outputPath, job, transcodingJobHelper, CancellationToken.None)
|
var stream = new ProgressiveFileStream(outputPath, job, transcodingJobHelper);
|
||||||
.WriteToAsync(httpContext.Response.Body, CancellationToken.None).ConfigureAwait(false);
|
return new FileStreamResult(stream, contentType);
|
||||||
return new FileStreamResult(httpContext.Response.Body, contentType);
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
162
Jellyfin.Api/Helpers/ProgressiveFileStream.cs
Normal file
162
Jellyfin.Api/Helpers/ProgressiveFileStream.cs
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Api.Models.PlaybackDtos;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
|
|
||||||
|
namespace Jellyfin.Api.Helpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A progressive file stream for transferring transcoded files as they are written to.
|
||||||
|
/// </summary>
|
||||||
|
public class ProgressiveFileStream : Stream
|
||||||
|
{
|
||||||
|
private readonly FileStream _fileStream;
|
||||||
|
private readonly TranscodingJobDto? _job;
|
||||||
|
private readonly TranscodingJobHelper _transcodingJobHelper;
|
||||||
|
private readonly bool _allowAsyncFileRead;
|
||||||
|
private int _bytesWritten;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ProgressiveFileStream"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">The path to the transcoded file.</param>
|
||||||
|
/// <param name="job">The transcoding job information.</param>
|
||||||
|
/// <param name="transcodingJobHelper">The transcoding job helper.</param>
|
||||||
|
public ProgressiveFileStream(string filePath, TranscodingJobDto? job, TranscodingJobHelper transcodingJobHelper)
|
||||||
|
{
|
||||||
|
_job = job;
|
||||||
|
_transcodingJobHelper = transcodingJobHelper;
|
||||||
|
_bytesWritten = 0;
|
||||||
|
|
||||||
|
var fileOptions = FileOptions.SequentialScan;
|
||||||
|
_allowAsyncFileRead = false;
|
||||||
|
|
||||||
|
// use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
|
||||||
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
fileOptions |= FileOptions.Asynchronous;
|
||||||
|
_allowAsyncFileRead = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool CanRead => _fileStream.CanRead;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool CanSeek => false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool CanWrite => false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override long Length => throw new NotSupportedException();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get => throw new NotSupportedException();
|
||||||
|
set => throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
_fileStream.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
return _fileStream.Read(buffer, offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
int totalBytesRead = 0;
|
||||||
|
int remainingBytesToRead = count;
|
||||||
|
|
||||||
|
while (remainingBytesToRead > 0)
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
int bytesRead;
|
||||||
|
if (_allowAsyncFileRead)
|
||||||
|
{
|
||||||
|
bytesRead = await _fileStream.ReadAsync(buffer, offset, remainingBytesToRead, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bytesRead = _fileStream.Read(buffer, offset, remainingBytesToRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
remainingBytesToRead -= bytesRead;
|
||||||
|
if (bytesRead > 0)
|
||||||
|
{
|
||||||
|
_bytesWritten += bytesRead;
|
||||||
|
totalBytesRead += bytesRead;
|
||||||
|
|
||||||
|
if (_job != null)
|
||||||
|
{
|
||||||
|
_job.BytesDownloaded = Math.Max(_job.BytesDownloaded ?? _bytesWritten, _bytesWritten);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_job == null || _job.HasExited)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalBytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
=> throw new NotSupportedException();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void SetLength(long value)
|
||||||
|
=> throw new NotSupportedException();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
=> throw new NotSupportedException();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_fileStream.Dispose();
|
||||||
|
|
||||||
|
if (_job != null)
|
||||||
|
{
|
||||||
|
_transcodingJobHelper.OnTranscodeEndRequest(_job);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
||||||
|
|
||||||
namespace Jellyfin.Api.ModelBinders
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Comma delimited array model binder provider.
|
|
||||||
/// </summary>
|
|
||||||
public class CommaDelimitedArrayModelBinderProvider : IModelBinderProvider
|
|
||||||
{
|
|
||||||
private readonly IModelBinder _binder;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="CommaDelimitedArrayModelBinderProvider"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public CommaDelimitedArrayModelBinderProvider()
|
|
||||||
{
|
|
||||||
_binder = new CommaDelimitedArrayModelBinder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public IModelBinder? GetBinder(ModelBinderProviderContext context)
|
|
||||||
{
|
|
||||||
return context.Metadata.ModelType.IsArray ? _binder : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -72,6 +72,18 @@ namespace Jellyfin.Server.Implementations.Activity
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task CleanAsync(DateTime startDate)
|
||||||
|
{
|
||||||
|
await using var dbContext = _provider.CreateContext();
|
||||||
|
var entries = dbContext.ActivityLogs
|
||||||
|
.AsQueryable()
|
||||||
|
.Where(entry => entry.DateCreated <= startDate);
|
||||||
|
|
||||||
|
dbContext.RemoveRange(entries);
|
||||||
|
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
private static ActivityLogEntry ConvertToOldModel(ActivityLog entry)
|
private static ActivityLogEntry ConvertToOldModel(ActivityLog entry)
|
||||||
{
|
{
|
||||||
return new ActivityLogEntry
|
return new ActivityLogEntry
|
||||||
|
@ -16,7 +16,6 @@ using Jellyfin.Api.Auth.LocalAccessPolicy;
|
|||||||
using Jellyfin.Api.Auth.RequiresElevationPolicy;
|
using Jellyfin.Api.Auth.RequiresElevationPolicy;
|
||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using Jellyfin.Api.Controllers;
|
using Jellyfin.Api.Controllers;
|
||||||
using Jellyfin.Api.ModelBinders;
|
|
||||||
using Jellyfin.Server.Configuration;
|
using Jellyfin.Server.Configuration;
|
||||||
using Jellyfin.Server.Filters;
|
using Jellyfin.Server.Filters;
|
||||||
using Jellyfin.Server.Formatters;
|
using Jellyfin.Server.Formatters;
|
||||||
@ -167,8 +166,6 @@ namespace Jellyfin.Server.Extensions
|
|||||||
|
|
||||||
opts.OutputFormatters.Add(new CssOutputFormatter());
|
opts.OutputFormatters.Add(new CssOutputFormatter());
|
||||||
opts.OutputFormatters.Add(new XmlOutputFormatter());
|
opts.OutputFormatters.Add(new XmlOutputFormatter());
|
||||||
|
|
||||||
opts.ModelBinderProviders.Insert(0, new CommaDelimitedArrayModelBinderProvider());
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Clear app parts to avoid other assemblies being picked up
|
// Clear app parts to avoid other assemblies being picked up
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.1.9" />
|
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.1.9" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="3.1.9" />
|
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="3.1.9" />
|
||||||
<PackageReference Include="prometheus-net" Version="4.0.0" />
|
<PackageReference Include="prometheus-net" Version="4.0.0" />
|
||||||
<PackageReference Include="prometheus-net.AspNetCore" Version="3.6.0" />
|
<PackageReference Include="prometheus-net.AspNetCore" Version="4.0.0" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
|
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
|
||||||
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
|
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
|
||||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
|
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
|
||||||
|
@ -280,21 +280,19 @@ namespace Jellyfin.Server
|
|||||||
options.Listen(netAdd.Address, appHost.HttpPort);
|
options.Listen(netAdd.Address, appHost.HttpPort);
|
||||||
if (appHost.ListenWithHttps)
|
if (appHost.ListenWithHttps)
|
||||||
{
|
{
|
||||||
options.Listen(netAdd.Address, appHost.HttpsPort, listenOptions =>
|
options.Listen(
|
||||||
{
|
netAdd.Address,
|
||||||
listenOptions.UseHttps(appHost.Certificate);
|
appHost.HttpsPort,
|
||||||
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
|
listenOptions => listenOptions.UseHttps(appHost.Certificate));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else if (builderContext.HostingEnvironment.IsDevelopment())
|
else if (builderContext.HostingEnvironment.IsDevelopment())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
options.Listen(netAdd.Address, appHost.HttpsPort, listenOptions =>
|
options.Listen(
|
||||||
{
|
netAdd.Address,
|
||||||
listenOptions.UseHttps();
|
appHost.HttpsPort,
|
||||||
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
|
listenOptions => listenOptions.UseHttps());
|
||||||
});
|
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException)
|
catch (InvalidOperationException)
|
||||||
{
|
{
|
||||||
|
@ -11,29 +11,6 @@ namespace MediaBrowser.Common.Updates
|
|||||||
{
|
{
|
||||||
public interface IInstallationManager : IDisposable
|
public interface IInstallationManager : IDisposable
|
||||||
{
|
{
|
||||||
event EventHandler<InstallationInfo> PackageInstalling;
|
|
||||||
|
|
||||||
event EventHandler<InstallationInfo> PackageInstallationCompleted;
|
|
||||||
|
|
||||||
event EventHandler<InstallationFailedEventArgs> PackageInstallationFailed;
|
|
||||||
|
|
||||||
event EventHandler<InstallationInfo> PackageInstallationCancelled;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when a plugin is uninstalled.
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler<IPlugin> PluginUninstalled;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when a plugin is updated.
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler<InstallationInfo> PluginUpdated;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when a plugin is installed.
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler<InstallationInfo> PluginInstalled;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the completed installations.
|
/// Gets the completed installations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -56,7 +56,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
{
|
{
|
||||||
if (query.IncludeItemTypes.Length == 0)
|
if (query.IncludeItemTypes.Length == 0)
|
||||||
{
|
{
|
||||||
query.IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name };
|
query.IncludeItemTypes = new[] { nameof(Audio), nameof(MusicVideo), nameof(MusicAlbum) };
|
||||||
query.ArtistIds = new[] { Id };
|
query.ArtistIds = new[] { Id };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.GenreIds = new[] { Id };
|
query.GenreIds = new[] { Id };
|
||||||
query.IncludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
|
query.IncludeItemTypes = new[] { nameof(MusicVideo), nameof(Audio), nameof(MusicAlbum), nameof(MusicArtist) };
|
||||||
|
|
||||||
return LibraryManager.GetItemList(query);
|
return LibraryManager.GetItemList(query);
|
||||||
}
|
}
|
||||||
|
@ -723,7 +723,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
private bool RequiresPostFiltering2(InternalItemsQuery query)
|
private bool RequiresPostFiltering2(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
if (query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], typeof(BoxSet).Name, StringComparison.OrdinalIgnoreCase))
|
if (query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], nameof(BoxSet), StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.LogDebug("Query requires post-filtering due to BoxSet query");
|
Logger.LogDebug("Query requires post-filtering due to BoxSet query");
|
||||||
return true;
|
return true;
|
||||||
@ -813,7 +813,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (query.IsPlayed.HasValue)
|
if (query.IsPlayed.HasValue)
|
||||||
{
|
{
|
||||||
if (query.IncludeItemTypes.Length == 1 && query.IncludeItemTypes.Contains(typeof(Series).Name))
|
if (query.IncludeItemTypes.Length == 1 && query.IncludeItemTypes.Contains(nameof(Series)))
|
||||||
{
|
{
|
||||||
Logger.LogDebug("Query requires post-filtering due to IsPlayed");
|
Logger.LogDebug("Query requires post-filtering due to IsPlayed");
|
||||||
return true;
|
return true;
|
||||||
|
@ -59,7 +59,13 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.GenreIds = new[] { Id };
|
query.GenreIds = new[] { Id };
|
||||||
query.ExcludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio.Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
|
query.ExcludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
nameof(MusicVideo),
|
||||||
|
nameof(Entities.Audio.Audio),
|
||||||
|
nameof(MusicAlbum),
|
||||||
|
nameof(MusicArtist)
|
||||||
|
};
|
||||||
|
|
||||||
return LibraryManager.GetItemList(query);
|
return LibraryManager.GetItemList(query);
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
if (query.IncludeItemTypes.Length == 0)
|
if (query.IncludeItemTypes.Length == 0)
|
||||||
{
|
{
|
||||||
query.IncludeItemTypes = new[] { typeof(Episode).Name };
|
query.IncludeItemTypes = new[] { nameof(Episode) };
|
||||||
}
|
}
|
||||||
|
|
||||||
query.IsVirtualItem = false;
|
query.IsVirtualItem = false;
|
||||||
@ -207,7 +207,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
query.AncestorWithPresentationUniqueKey = null;
|
query.AncestorWithPresentationUniqueKey = null;
|
||||||
query.SeriesPresentationUniqueKey = seriesKey;
|
query.SeriesPresentationUniqueKey = seriesKey;
|
||||||
query.IncludeItemTypes = new[] { typeof(Season).Name };
|
query.IncludeItemTypes = new[] { nameof(Season) };
|
||||||
query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray();
|
query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray();
|
||||||
|
|
||||||
if (user != null && !user.DisplayMissingEpisodes)
|
if (user != null && !user.DisplayMissingEpisodes)
|
||||||
@ -233,7 +233,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
if (query.IncludeItemTypes.Length == 0)
|
if (query.IncludeItemTypes.Length == 0)
|
||||||
{
|
{
|
||||||
query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name };
|
query.IncludeItemTypes = new[] { nameof(Episode), nameof(Season) };
|
||||||
}
|
}
|
||||||
|
|
||||||
query.IsVirtualItem = false;
|
query.IsVirtualItem = false;
|
||||||
@ -253,7 +253,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
AncestorWithPresentationUniqueKey = null,
|
AncestorWithPresentationUniqueKey = null,
|
||||||
SeriesPresentationUniqueKey = seriesKey,
|
SeriesPresentationUniqueKey = seriesKey,
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name },
|
IncludeItemTypes = new[] { nameof(Episode), nameof(Season) },
|
||||||
OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
|
OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
|
||||||
DtoOptions = options
|
DtoOptions = options
|
||||||
};
|
};
|
||||||
@ -364,7 +364,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
AncestorWithPresentationUniqueKey = queryFromSeries ? null : seriesKey,
|
AncestorWithPresentationUniqueKey = queryFromSeries ? null : seriesKey,
|
||||||
SeriesPresentationUniqueKey = queryFromSeries ? seriesKey : null,
|
SeriesPresentationUniqueKey = queryFromSeries ? seriesKey : null,
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name },
|
IncludeItemTypes = new[] { nameof(Episode) },
|
||||||
OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
|
OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
|
||||||
DtoOptions = options
|
DtoOptions = options
|
||||||
};
|
};
|
||||||
|
@ -142,7 +142,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (query.IncludeItemTypes.Length == 0)
|
if (query.IncludeItemTypes.Length == 0)
|
||||||
{
|
{
|
||||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
query.IncludeItemTypes = new[] { nameof(Movie) };
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent.QueryRecursive(query);
|
return parent.QueryRecursive(query);
|
||||||
@ -167,7 +167,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.IsFavorite = true;
|
query.IsFavorite = true;
|
||||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
query.IncludeItemTypes = new[] { nameof(Movie) };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return _libraryManager.GetItemsResult(query);
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.IsFavorite = true;
|
query.IsFavorite = true;
|
||||||
query.IncludeItemTypes = new[] { typeof(Series).Name };
|
query.IncludeItemTypes = new[] { nameof(Series) };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return _libraryManager.GetItemsResult(query);
|
||||||
}
|
}
|
||||||
@ -189,7 +189,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.IsFavorite = true;
|
query.IsFavorite = true;
|
||||||
query.IncludeItemTypes = new[] { typeof(Episode).Name };
|
query.IncludeItemTypes = new[] { nameof(Episode) };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return _libraryManager.GetItemsResult(query);
|
||||||
}
|
}
|
||||||
@ -200,7 +200,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
query.IncludeItemTypes = new[] { nameof(Movie) };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return _libraryManager.GetItemsResult(query);
|
||||||
}
|
}
|
||||||
@ -208,7 +208,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
private QueryResult<BaseItem> GetMovieCollections(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetMovieCollections(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.Parent = null;
|
query.Parent = null;
|
||||||
query.IncludeItemTypes = new[] { typeof(BoxSet).Name };
|
query.IncludeItemTypes = new[] { nameof(BoxSet) };
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.Recursive = true;
|
query.Recursive = true;
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.Limit = GetSpecialItemsLimit();
|
query.Limit = GetSpecialItemsLimit();
|
||||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
query.IncludeItemTypes = new[] { nameof(Movie) };
|
||||||
|
|
||||||
return ConvertToResult(_libraryManager.GetItemList(query));
|
return ConvertToResult(_libraryManager.GetItemList(query));
|
||||||
}
|
}
|
||||||
@ -236,7 +236,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.Limit = GetSpecialItemsLimit();
|
query.Limit = GetSpecialItemsLimit();
|
||||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
query.IncludeItemTypes = new[] { nameof(Movie) };
|
||||||
|
|
||||||
return ConvertToResult(_libraryManager.GetItemList(query));
|
return ConvertToResult(_libraryManager.GetItemList(query));
|
||||||
}
|
}
|
||||||
@ -255,7 +255,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
var genres = parent.QueryRecursive(new InternalItemsQuery(user)
|
var genres = parent.QueryRecursive(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Movie).Name },
|
IncludeItemTypes = new[] { nameof(Movie) },
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
EnableTotalRecordCount = false
|
EnableTotalRecordCount = false
|
||||||
}).Items
|
}).Items
|
||||||
@ -286,7 +286,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.GenreIds = new[] { displayParent.Id };
|
query.GenreIds = new[] { displayParent.Id };
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
query.IncludeItemTypes = new[] { nameof(Movie) };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return _libraryManager.GetItemsResult(query);
|
||||||
}
|
}
|
||||||
@ -333,7 +333,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.Limit = GetSpecialItemsLimit();
|
query.Limit = GetSpecialItemsLimit();
|
||||||
query.IncludeItemTypes = new[] { typeof(Episode).Name };
|
query.IncludeItemTypes = new[] { nameof(Episode) };
|
||||||
query.IsVirtualItem = false;
|
query.IsVirtualItem = false;
|
||||||
|
|
||||||
return ConvertToResult(_libraryManager.GetItemList(query));
|
return ConvertToResult(_libraryManager.GetItemList(query));
|
||||||
@ -362,7 +362,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.Limit = GetSpecialItemsLimit();
|
query.Limit = GetSpecialItemsLimit();
|
||||||
query.IncludeItemTypes = new[] { typeof(Episode).Name };
|
query.IncludeItemTypes = new[] { nameof(Episode) };
|
||||||
|
|
||||||
return ConvertToResult(_libraryManager.GetItemList(query));
|
return ConvertToResult(_libraryManager.GetItemList(query));
|
||||||
}
|
}
|
||||||
@ -373,7 +373,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Parent = parent;
|
query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(Series).Name };
|
query.IncludeItemTypes = new[] { nameof(Series) };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return _libraryManager.GetItemsResult(query);
|
||||||
}
|
}
|
||||||
@ -382,7 +382,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
var genres = parent.QueryRecursive(new InternalItemsQuery(user)
|
var genres = parent.QueryRecursive(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Series).Name },
|
IncludeItemTypes = new[] { nameof(Series) },
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
EnableTotalRecordCount = false
|
EnableTotalRecordCount = false
|
||||||
}).Items
|
}).Items
|
||||||
@ -413,7 +413,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.GenreIds = new[] { displayParent.Id };
|
query.GenreIds = new[] { displayParent.Id };
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(Series).Name };
|
query.IncludeItemTypes = new[] { nameof(Series) };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return _libraryManager.GetItemsResult(query);
|
||||||
}
|
}
|
||||||
|
@ -2675,9 +2675,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
state.MediaSource = mediaSource;
|
state.MediaSource = mediaSource;
|
||||||
|
|
||||||
var request = state.BaseRequest;
|
var request = state.BaseRequest;
|
||||||
if (!string.IsNullOrWhiteSpace(request.AudioCodec))
|
var supportedAudioCodecs = state.SupportedAudioCodecs;
|
||||||
|
if (request != null && supportedAudioCodecs != null && supportedAudioCodecs.Length > 0)
|
||||||
{
|
{
|
||||||
var supportedAudioCodecsList = request.AudioCodec.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
var supportedAudioCodecsList = supportedAudioCodecs.ToList();
|
||||||
|
|
||||||
ShiftAudioCodecsIfNeeded(supportedAudioCodecsList, state.AudioStream);
|
ShiftAudioCodecsIfNeeded(supportedAudioCodecsList, state.AudioStream);
|
||||||
|
|
||||||
|
@ -287,6 +287,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
return BaseRequest.AudioChannels;
|
return BaseRequest.AudioChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BaseRequest.TranscodingMaxAudioChannels.HasValue)
|
||||||
|
{
|
||||||
|
return BaseRequest.TranscodingMaxAudioChannels;
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(codec))
|
if (!string.IsNullOrEmpty(codec))
|
||||||
{
|
{
|
||||||
var value = BaseRequest.GetOption(codec, "audiochannels");
|
var value = BaseRequest.GetOption(codec, "audiochannels");
|
||||||
|
@ -160,7 +160,7 @@ namespace MediaBrowser.Controller.Playlists
|
|||||||
return LibraryManager.GetItemList(new InternalItemsQuery(user)
|
return LibraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
IncludeItemTypes = new[] { typeof(Audio).Name },
|
IncludeItemTypes = new[] { nameof(Audio) },
|
||||||
GenreIds = new[] { musicGenre.Id },
|
GenreIds = new[] { musicGenre.Id },
|
||||||
OrderBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
|
OrderBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
|
||||||
DtoOptions = options
|
DtoOptions = options
|
||||||
@ -172,7 +172,7 @@ namespace MediaBrowser.Controller.Playlists
|
|||||||
return LibraryManager.GetItemList(new InternalItemsQuery(user)
|
return LibraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
IncludeItemTypes = new[] { typeof(Audio).Name },
|
IncludeItemTypes = new[] { nameof(Audio) },
|
||||||
ArtistIds = new[] { musicArtist.Id },
|
ArtistIds = new[] { musicArtist.Id },
|
||||||
OrderBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
|
OrderBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
|
||||||
DtoOptions = options
|
DtoOptions = options
|
||||||
|
@ -16,5 +16,12 @@ namespace MediaBrowser.Model.Activity
|
|||||||
Task CreateAsync(ActivityLog entry);
|
Task CreateAsync(ActivityLog entry);
|
||||||
|
|
||||||
Task<QueryResult<ActivityLogEntry>> GetPagedResultAsync(ActivityLogQuery query);
|
Task<QueryResult<ActivityLogEntry>> GetPagedResultAsync(ActivityLogQuery query);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove all activity logs before the specified date.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startDate">Activity log start date.</param>
|
||||||
|
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||||
|
Task CleanAsync(DateTime startDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,5 +426,10 @@ namespace MediaBrowser.Model.Configuration
|
|||||||
/// Gets or sets the known proxies.
|
/// Gets or sets the known proxies.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[] KnownProxies { get; set; } = Array.Empty<string>();
|
public string[] KnownProxies { get; set; } = Array.Empty<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the number of days we should retain activity logs.
|
||||||
|
/// </summary>
|
||||||
|
public int? ActivityLogRetentionDays { get; set; } = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,7 +19,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.9" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.9" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.9" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.9" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.9" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.9" />
|
||||||
<PackageReference Include="OptimizedPriorityQueue" Version="4.2.0" />
|
<PackageReference Include="OptimizedPriorityQueue" Version="5.0.0" />
|
||||||
<PackageReference Include="PlaylistsNET" Version="1.1.2" />
|
<PackageReference Include="PlaylistsNET" Version="1.1.2" />
|
||||||
<PackageReference Include="TMDbLib" Version="1.7.3-alpha" />
|
<PackageReference Include="TMDbLib" Version="1.7.3-alpha" />
|
||||||
<PackageReference Include="TvDbSharper" Version="3.2.2" />
|
<PackageReference Include="TvDbSharper" Version="3.2.2" />
|
||||||
|
@ -54,7 +54,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
|||||||
{
|
{
|
||||||
var seriesWithPerson = _libraryManager.GetItemList(new InternalItemsQuery
|
var seriesWithPerson = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Series).Name },
|
IncludeItemTypes = new[] { nameof(Series) },
|
||||||
PersonIds = new[] { item.Id },
|
PersonIds = new[] { item.Id },
|
||||||
DtoOptions = new DtoOptions(false)
|
DtoOptions = new DtoOptions(false)
|
||||||
{
|
{
|
||||||
|
1
debian/control
vendored
1
debian/control
vendored
@ -20,7 +20,6 @@ Breaks: jellyfin (<<10.6.0)
|
|||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: at,
|
Depends: at,
|
||||||
libsqlite3-0,
|
libsqlite3-0,
|
||||||
jellyfin-ffmpeg (>= 4.2.1-2),
|
|
||||||
libfontconfig1,
|
libfontconfig1,
|
||||||
libfreetype6,
|
libfreetype6,
|
||||||
libssl1.1
|
libssl1.1
|
||||||
|
@ -13,9 +13,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoFixture" Version="4.13.0" />
|
<PackageReference Include="AutoFixture" Version="4.14.0" />
|
||||||
<PackageReference Include="AutoFixture.AutoMoq" Version="4.13.0" />
|
<PackageReference Include="AutoFixture.AutoMoq" Version="4.14.0" />
|
||||||
<PackageReference Include="AutoFixture.Xunit2" Version="4.13.0" />
|
<PackageReference Include="AutoFixture.Xunit2" Version="4.14.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.9" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.9" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.9" />
|
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.9" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoFixture" Version="4.13.0" />
|
<PackageReference Include="AutoFixture" Version="4.14.0" />
|
||||||
<PackageReference Include="AutoFixture.AutoMoq" Version="4.13.0" />
|
<PackageReference Include="AutoFixture.AutoMoq" Version="4.14.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||||
<PackageReference Include="Moq" Version="4.14.7" />
|
<PackageReference Include="Moq" Version="4.14.7" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.4.1" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user