mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-03-17 23:56:44 +00:00
Merge branch 'master' into event-rewrite-1
# Conflicts: # Emby.Dlna/Emby.Dlna.csproj # Emby.Dlna/Eventing/DlnaEventManager.cs # Emby.Dlna/Service/BaseService.cs # Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs # MediaBrowser.Controller/Subtitles/SubtitleDownloadEventArgs.cs
This commit is contained in:
@@ -746,12 +746,21 @@ namespace Emby.Server.Implementations.Channels
|
||||
// null if came from cache
|
||||
if (itemsResult != null)
|
||||
{
|
||||
var internalItems = itemsResult.Items
|
||||
.Select(i => GetChannelItemEntity(i, channelProvider, channel.Id, parentItem, cancellationToken))
|
||||
.ToArray();
|
||||
var items = itemsResult.Items;
|
||||
var itemsLen = items.Count;
|
||||
var internalItems = new Guid[itemsLen];
|
||||
for (int i = 0; i < itemsLen; i++)
|
||||
{
|
||||
internalItems[i] = (await GetChannelItemEntityAsync(
|
||||
items[i],
|
||||
channelProvider,
|
||||
channel.Id,
|
||||
parentItem,
|
||||
cancellationToken).ConfigureAwait(false)).Id;
|
||||
}
|
||||
|
||||
var existingIds = _libraryManager.GetItemIds(query);
|
||||
var deadIds = existingIds.Except(internalItems.Select(i => i.Id))
|
||||
var deadIds = existingIds.Except(internalItems)
|
||||
.ToArray();
|
||||
|
||||
foreach (var deadId in deadIds)
|
||||
@@ -963,7 +972,7 @@ namespace Emby.Server.Implementations.Channels
|
||||
return item;
|
||||
}
|
||||
|
||||
private BaseItem GetChannelItemEntity(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, BaseItem parentFolder, CancellationToken cancellationToken)
|
||||
private async Task<BaseItem> GetChannelItemEntityAsync(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, BaseItem parentFolder, CancellationToken cancellationToken)
|
||||
{
|
||||
var parentFolderId = parentFolder.Id;
|
||||
|
||||
@@ -1165,7 +1174,7 @@ namespace Emby.Server.Implementations.Channels
|
||||
}
|
||||
else if (forceUpdate)
|
||||
{
|
||||
item.UpdateToRepository(ItemUpdateType.None, cancellationToken);
|
||||
await item.UpdateToRepositoryAsync(ItemUpdateType.None, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if ((isNew || forceUpdate) && info.Type == ChannelItemType.Media)
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Emby.Server.Implementations.Collections
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public BoxSet CreateCollection(CollectionCreationOptions options)
|
||||
public async Task<BoxSet> CreateCollectionAsync(CollectionCreationOptions options)
|
||||
{
|
||||
var name = options.Name;
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace Emby.Server.Implementations.Collections
|
||||
// This could cause it to get re-resolved as a plain folder
|
||||
var folderName = _fileSystem.GetValidFilename(name) + " [boxset]";
|
||||
|
||||
var parentFolder = GetCollectionsFolder(true).GetAwaiter().GetResult();
|
||||
var parentFolder = await GetCollectionsFolder(true).ConfigureAwait(false);
|
||||
|
||||
if (parentFolder == null)
|
||||
{
|
||||
@@ -169,12 +169,16 @@ namespace Emby.Server.Implementations.Collections
|
||||
|
||||
if (options.ItemIdList.Length > 0)
|
||||
{
|
||||
AddToCollection(collection.Id, options.ItemIdList, false, new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
||||
{
|
||||
// The initial adding of items is going to create a local metadata file
|
||||
// This will cause internet metadata to be skipped as a result
|
||||
MetadataRefreshMode = MetadataRefreshMode.FullRefresh
|
||||
});
|
||||
await AddToCollectionAsync(
|
||||
collection.Id,
|
||||
options.ItemIdList.Select(x => new Guid(x)),
|
||||
false,
|
||||
new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
||||
{
|
||||
// The initial adding of items is going to create a local metadata file
|
||||
// This will cause internet metadata to be skipped as a result
|
||||
MetadataRefreshMode = MetadataRefreshMode.FullRefresh
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -197,18 +201,10 @@ namespace Emby.Server.Implementations.Collections
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddToCollection(Guid collectionId, IEnumerable<string> ids)
|
||||
{
|
||||
AddToCollection(collectionId, ids, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem)));
|
||||
}
|
||||
public Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids)
|
||||
=> AddToCollectionAsync(collectionId, ids, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem)));
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
|
||||
{
|
||||
AddToCollection(collectionId, ids.Select(i => i.ToString("N", CultureInfo.InvariantCulture)), true, new MetadataRefreshOptions(new DirectoryService(_fileSystem)));
|
||||
}
|
||||
|
||||
private void AddToCollection(Guid collectionId, IEnumerable<string> ids, bool fireEvent, MetadataRefreshOptions refreshOptions)
|
||||
private async Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent, MetadataRefreshOptions refreshOptions)
|
||||
{
|
||||
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
|
||||
if (collection == null)
|
||||
@@ -224,15 +220,14 @@ namespace Emby.Server.Implementations.Collections
|
||||
|
||||
foreach (var id in ids)
|
||||
{
|
||||
var guidId = new Guid(id);
|
||||
var item = _libraryManager.GetItemById(guidId);
|
||||
var item = _libraryManager.GetItemById(id);
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentException("No item exists with the supplied Id");
|
||||
}
|
||||
|
||||
if (!currentLinkedChildrenIds.Contains(guidId))
|
||||
if (!currentLinkedChildrenIds.Contains(id))
|
||||
{
|
||||
itemList.Add(item);
|
||||
|
||||
@@ -249,7 +244,7 @@ namespace Emby.Server.Implementations.Collections
|
||||
|
||||
collection.UpdateRatingToItems(linkedChildrenList);
|
||||
|
||||
collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
||||
await collection.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
refreshOptions.ForceSave = true;
|
||||
_providerManager.QueueRefresh(collection.Id, refreshOptions, RefreshPriority.High);
|
||||
@@ -266,13 +261,7 @@ namespace Emby.Server.Implementations.Collections
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RemoveFromCollection(Guid collectionId, IEnumerable<string> itemIds)
|
||||
{
|
||||
RemoveFromCollection(collectionId, itemIds.Select(i => new Guid(i)));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds)
|
||||
public async Task RemoveFromCollectionAsync(Guid collectionId, IEnumerable<Guid> itemIds)
|
||||
{
|
||||
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
|
||||
|
||||
@@ -309,7 +298,7 @@ namespace Emby.Server.Implementations.Collections
|
||||
collection.LinkedChildren = collection.LinkedChildren.Except(list).ToArray();
|
||||
}
|
||||
|
||||
collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
||||
await collection.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||
_providerManager.QueueRefresh(
|
||||
collection.Id,
|
||||
new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
||||
|
||||
@@ -90,6 +90,9 @@ namespace Emby.Server.Implementations.Data
|
||||
_typeMapper = new TypeMapper();
|
||||
_jsonOptions = JsonDefaults.GetOptions();
|
||||
|
||||
// GetItem throws NotSupportedException with this enabled, so hardcode false.
|
||||
_jsonOptions.IgnoreNullValues = false;
|
||||
|
||||
DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db");
|
||||
}
|
||||
|
||||
@@ -4308,7 +4311,7 @@ namespace Emby.Server.Implementations.Data
|
||||
whereClauses.Add("ProductionYear=@Years");
|
||||
if (statement != null)
|
||||
{
|
||||
statement.TryBind("@Years", query.Years[0].ToString());
|
||||
statement.TryBind("@Years", query.Years[0].ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
}
|
||||
else if (query.Years.Length > 1)
|
||||
@@ -4560,13 +4563,13 @@ namespace Emby.Server.Implementations.Data
|
||||
if (query.AncestorIds.Length > 1)
|
||||
{
|
||||
var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i.ToString("N", CultureInfo.InvariantCulture) + "'"));
|
||||
whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause));
|
||||
whereClauses.Add(string.Format(CultureInfo.InvariantCulture, "Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(query.AncestorWithPresentationUniqueKey))
|
||||
{
|
||||
var inClause = "select guid from TypedBaseItems where PresentationUniqueKey=@AncestorWithPresentationUniqueKey";
|
||||
whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorId in ({0}))", inClause));
|
||||
whereClauses.Add(string.Format(CultureInfo.InvariantCulture, "Guid in (select itemId from AncestorIds where AncestorId in ({0}))", inClause));
|
||||
if (statement != null)
|
||||
{
|
||||
statement.TryBind("@AncestorWithPresentationUniqueKey", query.AncestorWithPresentationUniqueKey);
|
||||
@@ -5170,7 +5173,10 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
||||
insertText.Append(',');
|
||||
}
|
||||
|
||||
insertText.AppendFormat("(@ItemId, @AncestorId{0}, @AncestorIdText{0})", i.ToString(CultureInfo.InvariantCulture));
|
||||
insertText.AppendFormat(
|
||||
CultureInfo.InvariantCulture,
|
||||
"(@ItemId, @AncestorId{0}, @AncestorIdText{0})",
|
||||
i.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
using (var statement = PrepareStatement(db, insertText.ToString()))
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<PackageReference Include="ServiceStack.Text.Core" Version="5.9.2" />
|
||||
<PackageReference Include="sharpcompress" Version="0.26.0" />
|
||||
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" />
|
||||
<PackageReference Include="DotNet.Glob" Version="3.0.9" />
|
||||
<PackageReference Include="DotNet.Glob" Version="3.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -6,12 +6,11 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Emby.Server.Implementations.Library;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
using MediaBrowser.Model.IO;
|
||||
using Emby.Server.Implementations.Library;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.IO
|
||||
@@ -38,6 +37,8 @@ namespace Emby.Server.Implementations.IO
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, string> _tempIgnoredPaths = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// Add the path to our temporary ignore list. Use when writing to a path within our listening scope.
|
||||
/// </summary>
|
||||
@@ -492,8 +493,6 @@ namespace Emby.Server.Implementations.IO
|
||||
}
|
||||
}
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
@@ -522,24 +521,4 @@ namespace Emby.Server.Implementations.IO
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public class LibraryMonitorStartup : IServerEntryPoint
|
||||
{
|
||||
private readonly ILibraryMonitor _monitor;
|
||||
|
||||
public LibraryMonitorStartup(ILibraryMonitor monitor)
|
||||
{
|
||||
_monitor = monitor;
|
||||
}
|
||||
|
||||
public Task RunAsync()
|
||||
{
|
||||
_monitor.Start();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
35
Emby.Server.Implementations/IO/LibraryMonitorStartup.cs
Normal file
35
Emby.Server.Implementations/IO/LibraryMonitorStartup.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
|
||||
namespace Emby.Server.Implementations.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IServerEntryPoint" /> which is responsible for starting the library monitor.
|
||||
/// </summary>
|
||||
public sealed class LibraryMonitorStartup : IServerEntryPoint
|
||||
{
|
||||
private readonly ILibraryMonitor _monitor;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LibraryMonitorStartup"/> class.
|
||||
/// </summary>
|
||||
/// <param name="monitor">The library monitor.</param>
|
||||
public LibraryMonitorStartup(ILibraryMonitor monitor)
|
||||
{
|
||||
_monitor = monitor;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task RunAsync()
|
||||
{
|
||||
_monitor.Start();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -729,7 +729,7 @@ namespace Emby.Server.Implementations.Library
|
||||
Directory.CreateDirectory(rootFolderPath);
|
||||
|
||||
var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ??
|
||||
((Folder) ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath)))
|
||||
((Folder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath)))
|
||||
.DeepCopy<Folder, AggregateFolder>();
|
||||
|
||||
// In case program data folder was moved
|
||||
@@ -771,7 +771,7 @@ namespace Emby.Server.Implementations.Library
|
||||
if (folder.ParentId != rootFolder.Id)
|
||||
{
|
||||
folder.ParentId = rootFolder.Id;
|
||||
folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None);
|
||||
folder.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, CancellationToken.None).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
rootFolder.AddVirtualChild(folder);
|
||||
@@ -1868,7 +1868,8 @@ namespace Emby.Server.Implementations.Library
|
||||
return image.Path != null && !image.IsLocalFile;
|
||||
}
|
||||
|
||||
public void UpdateImages(BaseItem item, bool forceUpdate = false)
|
||||
/// <inheritdoc />
|
||||
public async Task UpdateImagesAsync(BaseItem item, bool forceUpdate = false)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
@@ -1891,7 +1892,7 @@ namespace Emby.Server.Implementations.Library
|
||||
try
|
||||
{
|
||||
var index = item.GetImageIndex(img);
|
||||
image = ConvertImageToLocal(item, img, index).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
image = await ConvertImageToLocal(item, img, index).ConfigureAwait(false);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
@@ -1913,7 +1914,7 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Cannnot get image dimensions for {0}", image.Path);
|
||||
_logger.LogError(ex, "Cannot get image dimensions for {0}", image.Path);
|
||||
image.Width = 0;
|
||||
image.Height = 0;
|
||||
continue;
|
||||
@@ -1943,10 +1944,8 @@ namespace Emby.Server.Implementations.Library
|
||||
RegisterItem(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the item.
|
||||
/// </summary>
|
||||
public void UpdateItems(IReadOnlyList<BaseItem> items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
|
||||
/// <inheritdoc />
|
||||
public async Task UpdateItemsAsync(IReadOnlyList<BaseItem> items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
@@ -1957,7 +1956,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
item.DateLastSaved = DateTime.UtcNow;
|
||||
|
||||
UpdateImages(item, updateReason >= ItemUpdateType.ImageUpdate);
|
||||
await UpdateImagesAsync(item, updateReason >= ItemUpdateType.ImageUpdate).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_itemRepository.SaveItems(items, cancellationToken);
|
||||
@@ -1991,17 +1990,9 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="parent">The parent item.</param>
|
||||
/// <param name="updateReason">The update reason.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
public void UpdateItem(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
|
||||
{
|
||||
UpdateItems(new[] { item }, parent, updateReason, cancellationToken);
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
|
||||
=> UpdateItemsAsync(new[] { item }, parent, updateReason, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Reports the item removed.
|
||||
@@ -2233,7 +2224,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
if (refresh)
|
||||
{
|
||||
item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None);
|
||||
item.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, CancellationToken.None).GetAwaiter().GetResult();
|
||||
ProviderManager.QueueRefresh(item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.Normal);
|
||||
}
|
||||
|
||||
@@ -2420,7 +2411,7 @@ namespace Emby.Server.Implementations.Library
|
||||
if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
item.ViewType = viewType;
|
||||
item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
||||
item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
var refresh = isNew || DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval;
|
||||
@@ -2902,7 +2893,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
await ProviderManager.SaveImage(item, url, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
|
||||
await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
return item.GetImageInfo(image.Type, imageIndex);
|
||||
}
|
||||
@@ -2920,7 +2911,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
// Remove this image to prevent it from retrying over and over
|
||||
item.RemoveImage(image);
|
||||
item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
|
||||
await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
|
||||
if (filters.Count > 0)
|
||||
{
|
||||
output += string.Format(" -vf \"{0}\"", string.Join(",", filters.ToArray()));
|
||||
output += string.Format(CultureInfo.InvariantCulture, " -vf \"{0}\"", string.Join(",", filters.ToArray()));
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
@@ -5,7 +5,7 @@ using MediaBrowser.Controller.Plugins;
|
||||
|
||||
namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
{
|
||||
public class EntryPoint : IServerEntryPoint
|
||||
public sealed class EntryPoint : IServerEntryPoint
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task RunAsync()
|
||||
|
||||
@@ -929,7 +929,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||
|
||||
private static string NormalizeName(string value)
|
||||
{
|
||||
return value.Replace(" ", string.Empty).Replace("-", string.Empty);
|
||||
return value.Replace(" ", string.Empty, StringComparison.Ordinal).Replace("-", string.Empty, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public class ScheduleDirect
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||
&& !programInfo.IsRepeat
|
||||
&& (programInfo.EpisodeNumber ?? 0) == 0)
|
||||
{
|
||||
programInfo.ShowId = programInfo.ShowId + programInfo.StartDate.Ticks.ToString(CultureInfo.InvariantCulture);
|
||||
programInfo.ShowId += programInfo.StartDate.Ticks.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -246,7 +246,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||
}
|
||||
|
||||
// Construct an id from the channel and start date
|
||||
programInfo.Id = string.Format("{0}_{1:O}", program.ChannelId, program.StartDate);
|
||||
programInfo.Id = string.Format(CultureInfo.InvariantCulture, "{0}_{1:O}", program.ChannelId, program.StartDate);
|
||||
|
||||
if (programInfo.IsMovie)
|
||||
{
|
||||
@@ -296,7 +296,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||
Name = c.DisplayName,
|
||||
ImageUrl = c.Icon != null && !string.IsNullOrEmpty(c.Icon.Source) ? c.Icon.Source : null,
|
||||
Number = string.IsNullOrWhiteSpace(c.Number) ? c.Id : c.Number
|
||||
|
||||
}).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
/// </summary>
|
||||
public class LiveTvManager : ILiveTvManager, IDisposable
|
||||
{
|
||||
private const int MaxGuideDays = 14;
|
||||
private const string ExternalServiceTag = "ExternalServiceId";
|
||||
|
||||
private const string EtagKey = "ProgramEtag";
|
||||
@@ -421,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
}
|
||||
}
|
||||
|
||||
private LiveTvChannel GetChannel(ChannelInfo channelInfo, string serviceName, BaseItem parentFolder, CancellationToken cancellationToken)
|
||||
private async Task<LiveTvChannel> GetChannelAsync(ChannelInfo channelInfo, string serviceName, BaseItem parentFolder, CancellationToken cancellationToken)
|
||||
{
|
||||
var parentFolderId = parentFolder.Id;
|
||||
var isNew = false;
|
||||
@@ -511,7 +512,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
}
|
||||
else if (forceUpdate)
|
||||
{
|
||||
_libraryManager.UpdateItem(item, parentFolder, ItemUpdateType.MetadataImport, cancellationToken);
|
||||
await _libraryManager.UpdateItemAsync(item, parentFolder, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -560,7 +561,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
item.Audio = info.Audio;
|
||||
item.ChannelId = channel.Id;
|
||||
item.CommunityRating = item.CommunityRating ?? info.CommunityRating;
|
||||
item.CommunityRating ??= info.CommunityRating;
|
||||
if ((item.CommunityRating ?? 0).Equals(0))
|
||||
{
|
||||
item.CommunityRating = null;
|
||||
@@ -645,8 +646,8 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
item.IsSeries = isSeries;
|
||||
|
||||
item.Name = info.Name;
|
||||
item.OfficialRating = item.OfficialRating ?? info.OfficialRating;
|
||||
item.Overview = item.Overview ?? info.Overview;
|
||||
item.OfficialRating ??= info.OfficialRating;
|
||||
item.Overview ??= info.Overview;
|
||||
item.RunTimeTicks = (info.EndDate - info.StartDate).Ticks;
|
||||
item.ProviderIds = info.ProviderIds;
|
||||
|
||||
@@ -683,19 +684,23 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(info.ImagePath))
|
||||
{
|
||||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = info.ImagePath,
|
||||
Type = ImageType.Primary
|
||||
}, 0);
|
||||
item.SetImage(
|
||||
new ItemImageInfo
|
||||
{
|
||||
Path = info.ImagePath,
|
||||
Type = ImageType.Primary
|
||||
},
|
||||
0);
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(info.ImageUrl))
|
||||
{
|
||||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = info.ImageUrl,
|
||||
Type = ImageType.Primary
|
||||
}, 0);
|
||||
item.SetImage(
|
||||
new ItemImageInfo
|
||||
{
|
||||
Path = info.ImageUrl,
|
||||
Type = ImageType.Primary
|
||||
},
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,11 +708,13 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(info.ThumbImageUrl))
|
||||
{
|
||||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = info.ThumbImageUrl,
|
||||
Type = ImageType.Thumb
|
||||
}, 0);
|
||||
item.SetImage(
|
||||
new ItemImageInfo
|
||||
{
|
||||
Path = info.ThumbImageUrl,
|
||||
Type = ImageType.Thumb
|
||||
},
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,11 +722,13 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(info.LogoImageUrl))
|
||||
{
|
||||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = info.LogoImageUrl,
|
||||
Type = ImageType.Logo
|
||||
}, 0);
|
||||
item.SetImage(
|
||||
new ItemImageInfo
|
||||
{
|
||||
Path = info.LogoImageUrl,
|
||||
Type = ImageType.Logo
|
||||
},
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -727,11 +736,13 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(info.BackdropImageUrl))
|
||||
{
|
||||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = info.BackdropImageUrl,
|
||||
Type = ImageType.Backdrop
|
||||
}, 0);
|
||||
item.SetImage(
|
||||
new ItemImageInfo
|
||||
{
|
||||
Path = info.BackdropImageUrl,
|
||||
Type = ImageType.Backdrop
|
||||
},
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -786,7 +797,6 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
if (query.OrderBy.Count == 0)
|
||||
{
|
||||
|
||||
// Unless something else was specified, order by start date to take advantage of a specialized index
|
||||
query.OrderBy = new[]
|
||||
{
|
||||
@@ -824,7 +834,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(query.SeriesTimerId))
|
||||
{
|
||||
var seriesTimers = await GetSeriesTimersInternal(new SeriesTimerQuery { }, cancellationToken).ConfigureAwait(false);
|
||||
var seriesTimers = await GetSeriesTimersInternal(new SeriesTimerQuery(), cancellationToken).ConfigureAwait(false);
|
||||
var seriesTimer = seriesTimers.Items.FirstOrDefault(i => string.Equals(_tvDtoService.GetInternalSeriesTimerId(i.Id).ToString("N", CultureInfo.InvariantCulture), query.SeriesTimerId, StringComparison.OrdinalIgnoreCase));
|
||||
if (seriesTimer != null)
|
||||
{
|
||||
@@ -847,13 +857,11 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
var returnArray = _dtoService.GetBaseItemDtos(queryResult.Items, options, user);
|
||||
|
||||
var result = new QueryResult<BaseItemDto>
|
||||
return new QueryResult<BaseItemDto>
|
||||
{
|
||||
Items = returnArray,
|
||||
TotalRecordCount = queryResult.TotalRecordCount
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public QueryResult<BaseItem> GetRecommendedProgramsInternal(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken)
|
||||
@@ -1121,7 +1129,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
try
|
||||
{
|
||||
var item = GetChannel(channelInfo.Item2, channelInfo.Item1, parentFolder, cancellationToken);
|
||||
var item = await GetChannelAsync(channelInfo.Item2, channelInfo.Item1, parentFolder, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
list.Add(item);
|
||||
}
|
||||
@@ -1138,7 +1146,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
double percent = numComplete;
|
||||
percent /= allChannelsList.Count;
|
||||
|
||||
progress.Report(5 * percent + 10);
|
||||
progress.Report((5 * percent) + 10);
|
||||
}
|
||||
|
||||
progress.Report(15);
|
||||
@@ -1173,7 +1181,6 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
var existingPrograms = _libraryManager.GetItemList(new InternalItemsQuery
|
||||
{
|
||||
|
||||
IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
|
||||
ChannelIds = new Guid[] { currentChannel.Id },
|
||||
DtoOptions = new DtoOptions(true)
|
||||
@@ -1214,7 +1221,11 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
if (updatedPrograms.Count > 0)
|
||||
{
|
||||
_libraryManager.UpdateItems(updatedPrograms, currentChannel, ItemUpdateType.MetadataImport, cancellationToken);
|
||||
await _libraryManager.UpdateItemsAsync(
|
||||
updatedPrograms,
|
||||
currentChannel,
|
||||
ItemUpdateType.MetadataImport,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
currentChannel.IsMovie = isMovie;
|
||||
@@ -1227,7 +1238,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
currentChannel.AddTag("Kids");
|
||||
}
|
||||
|
||||
currentChannel.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken);
|
||||
await currentChannel.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
|
||||
await currentChannel.RefreshMetadata(
|
||||
new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
||||
{
|
||||
@@ -1298,8 +1309,6 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
}
|
||||
}
|
||||
|
||||
private const int MaxGuideDays = 14;
|
||||
|
||||
private double GetGuideDays()
|
||||
{
|
||||
var config = GetConfiguration();
|
||||
@@ -1712,7 +1721,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
if (timer == null)
|
||||
{
|
||||
throw new ResourceNotFoundException(string.Format("Timer with Id {0} not found", id));
|
||||
throw new ResourceNotFoundException(string.Format(CultureInfo.InvariantCulture, "Timer with Id {0} not found", id));
|
||||
}
|
||||
|
||||
var service = GetService(timer.ServiceName);
|
||||
@@ -1731,7 +1740,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
if (timer == null)
|
||||
{
|
||||
throw new ResourceNotFoundException(string.Format("SeriesTimer with Id {0} not found", id));
|
||||
throw new ResourceNotFoundException(string.Format(CultureInfo.InvariantCulture, "SeriesTimer with Id {0} not found", id));
|
||||
}
|
||||
|
||||
var service = GetService(timer.ServiceName);
|
||||
@@ -1743,10 +1752,12 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
public async Task<TimerInfoDto> GetTimer(string id, CancellationToken cancellationToken)
|
||||
{
|
||||
var results = await GetTimers(new TimerQuery
|
||||
{
|
||||
Id = id
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
var results = await GetTimers(
|
||||
new TimerQuery
|
||||
{
|
||||
Id = id
|
||||
},
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
@@ -1794,10 +1805,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
}
|
||||
|
||||
var returnArray = timers
|
||||
.Select(i =>
|
||||
{
|
||||
return i.Item1;
|
||||
})
|
||||
.Select(i => i.Item1)
|
||||
.ToArray();
|
||||
|
||||
return new QueryResult<SeriesTimerInfo>
|
||||
@@ -1968,7 +1976,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
if (service == null)
|
||||
{
|
||||
service = _services.First();
|
||||
service = _services[0];
|
||||
}
|
||||
|
||||
var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false);
|
||||
@@ -1994,9 +2002,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
{
|
||||
var info = await GetNewTimerDefaultsInternal(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var obj = _tvDtoService.GetSeriesTimerInfoDto(info.Item1, info.Item2, null);
|
||||
|
||||
return obj;
|
||||
return _tvDtoService.GetSeriesTimerInfoDto(info.Item1, info.Item2, null);
|
||||
}
|
||||
|
||||
public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(string programId, CancellationToken cancellationToken)
|
||||
@@ -2125,6 +2131,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private bool _disposed = false;
|
||||
@@ -2447,8 +2454,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
.SelectMany(i => i.Locations)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.Select(i => _libraryManager.FindByPath(i, true))
|
||||
.Where(i => i != null)
|
||||
.Where(i => i.IsVisibleStandalone(user))
|
||||
.Where(i => i != null && i.IsVisibleStandalone(user))
|
||||
.SelectMany(i => _libraryManager.GetCollectionFolders(i))
|
||||
.GroupBy(x => x.Id)
|
||||
.Select(x => x.First())
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||
private readonly INetworkManager _networkManager;
|
||||
private readonly IStreamHelper _streamHelper;
|
||||
|
||||
private readonly Dictionary<string, DiscoverResponse> _modelCache = new Dictionary<string, DiscoverResponse>();
|
||||
|
||||
public HdHomerunHost(
|
||||
IServerConfigurationManager config,
|
||||
ILogger<HdHomerunHost> logger,
|
||||
@@ -114,7 +116,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||
}).Cast<ChannelInfo>().ToList();
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, DiscoverResponse> _modelCache = new Dictionary<string, DiscoverResponse>();
|
||||
private async Task<DiscoverResponse> GetModelInfo(TunerHostInfo info, bool throwAllExceptions, CancellationToken cancellationToken)
|
||||
{
|
||||
var cacheKey = info.Id;
|
||||
@@ -157,10 +158,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||
{
|
||||
if (!throwAllExceptions && ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound)
|
||||
{
|
||||
var defaultValue = "HDHR";
|
||||
const string DefaultValue = "HDHR";
|
||||
var response = new DiscoverResponse
|
||||
{
|
||||
ModelNumber = defaultValue
|
||||
ModelNumber = DefaultValue
|
||||
};
|
||||
if (!string.IsNullOrEmpty(cacheKey))
|
||||
{
|
||||
@@ -182,12 +183,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||
{
|
||||
var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
using (var response = await _httpClient.SendAsync(new HttpRequestOptions()
|
||||
{
|
||||
Url = string.Format("{0}/tuners.html", GetApiUrl(info)),
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = false
|
||||
}, HttpMethod.Get).ConfigureAwait(false))
|
||||
using (var response = await _httpClient.SendAsync(
|
||||
new HttpRequestOptions()
|
||||
{
|
||||
Url = string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)),
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = false
|
||||
},
|
||||
HttpMethod.Get).ConfigureAwait(false))
|
||||
using (var stream = response.Content)
|
||||
using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8))
|
||||
{
|
||||
@@ -730,7 +733,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||
// Need a way to set the Receive timeout on the socket otherwise this might never timeout?
|
||||
try
|
||||
{
|
||||
await udpClient.SendToAsync(discBytes, 0, discBytes.Length, new IPEndPoint(IPAddress.Parse("255.255.255.255"), 65001), cancellationToken);
|
||||
await udpClient.SendToAsync(discBytes, 0, discBytes.Length, new IPEndPoint(IPAddress.Parse("255.255.255.255"), 65001), cancellationToken).ConfigureAwait(false);
|
||||
var receiveBuffer = new byte[8192];
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Albums": "Album",
|
||||
"AuthenticationSucceededWithUserName": "{0} berhasil diautentikasi",
|
||||
"AppDeviceValues": "Aplikasi: {0}, Alat: {1}",
|
||||
"AppDeviceValues": "Aplikasi : {0}, Alat : {1}",
|
||||
"LabelRunningTimeValue": "Waktu berjalan: {0}",
|
||||
"MessageApplicationUpdatedTo": "Jellyfin Server sudah diperbarui ke {0}",
|
||||
"MessageApplicationUpdated": "Jellyfin Server sudah diperbarui",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"HeaderFavoriteAlbums": "Избранные альбомы",
|
||||
"HeaderFavoriteArtists": "Избранные исполнители",
|
||||
"HeaderFavoriteEpisodes": "Избранные эпизоды",
|
||||
"HeaderFavoriteShows": "Избранные передачи",
|
||||
"HeaderFavoriteShows": "Избранные сериалы",
|
||||
"HeaderFavoriteSongs": "Избранные композиции",
|
||||
"HeaderLiveTV": "Эфир",
|
||||
"HeaderNextUp": "Очередное",
|
||||
|
||||
@@ -152,10 +152,10 @@ namespace Emby.Server.Implementations.Playlists
|
||||
|
||||
if (options.ItemIdList.Length > 0)
|
||||
{
|
||||
AddToPlaylistInternal(playlist.Id.ToString("N", CultureInfo.InvariantCulture), options.ItemIdList, user, new DtoOptions(false)
|
||||
await AddToPlaylistInternal(playlist.Id, options.ItemIdList, user, new DtoOptions(false)
|
||||
{
|
||||
EnableImages = true
|
||||
});
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return new PlaylistCreationResult(playlist.Id.ToString("N", CultureInfo.InvariantCulture));
|
||||
@@ -184,17 +184,17 @@ namespace Emby.Server.Implementations.Playlists
|
||||
return Playlist.GetPlaylistItems(playlistMediaType, items, user, options);
|
||||
}
|
||||
|
||||
public void AddToPlaylist(string playlistId, ICollection<Guid> itemIds, Guid userId)
|
||||
public Task AddToPlaylistAsync(Guid playlistId, ICollection<Guid> itemIds, Guid userId)
|
||||
{
|
||||
var user = userId.Equals(Guid.Empty) ? null : _userManager.GetUserById(userId);
|
||||
|
||||
AddToPlaylistInternal(playlistId, itemIds, user, new DtoOptions(false)
|
||||
return AddToPlaylistInternal(playlistId, itemIds, user, new DtoOptions(false)
|
||||
{
|
||||
EnableImages = true
|
||||
});
|
||||
}
|
||||
|
||||
private void AddToPlaylistInternal(string playlistId, ICollection<Guid> newItemIds, User user, DtoOptions options)
|
||||
private async Task AddToPlaylistInternal(Guid playlistId, ICollection<Guid> newItemIds, User user, DtoOptions options)
|
||||
{
|
||||
// Retrieve the existing playlist
|
||||
var playlist = _libraryManager.GetItemById(playlistId) as Playlist
|
||||
@@ -238,7 +238,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||
|
||||
// Update the playlist in the repository
|
||||
playlist.LinkedChildren = newLinkedChildren;
|
||||
playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
||||
await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
// Update the playlist on disk
|
||||
if (playlist.IsFile)
|
||||
@@ -256,7 +256,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||
RefreshPriority.High);
|
||||
}
|
||||
|
||||
public void RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds)
|
||||
public async Task RemoveFromPlaylistAsync(string playlistId, IEnumerable<string> entryIds)
|
||||
{
|
||||
if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist))
|
||||
{
|
||||
@@ -273,7 +273,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||
.Select(i => i.Item1)
|
||||
.ToArray();
|
||||
|
||||
playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
||||
await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
if (playlist.IsFile)
|
||||
{
|
||||
@@ -289,7 +289,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||
RefreshPriority.High);
|
||||
}
|
||||
|
||||
public void MoveItem(string playlistId, string entryId, int newIndex)
|
||||
public async Task MoveItemAsync(string playlistId, string entryId, int newIndex)
|
||||
{
|
||||
if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist))
|
||||
{
|
||||
@@ -322,7 +322,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||
|
||||
playlist.LinkedChildren = newList.ToArray();
|
||||
|
||||
playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
||||
await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
if (playlist.IsFile)
|
||||
{
|
||||
|
||||
@@ -21,37 +21,53 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
/// </summary>
|
||||
public class ScheduledTaskWorker : IScheduledTaskWorker
|
||||
{
|
||||
public event EventHandler<GenericEventArgs<double>> TaskProgress;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the scheduled task.
|
||||
/// </summary>
|
||||
/// <value>The scheduled task.</value>
|
||||
public IScheduledTask ScheduledTask { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the json serializer.
|
||||
/// </summary>
|
||||
/// <value>The json serializer.</value>
|
||||
private IJsonSerializer JsonSerializer { get; set; }
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the application paths.
|
||||
/// </summary>
|
||||
/// <value>The application paths.</value>
|
||||
private IApplicationPaths ApplicationPaths { get; set; }
|
||||
private readonly IApplicationPaths _applicationPaths;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logger.
|
||||
/// Gets or sets the logger.
|
||||
/// </summary>
|
||||
/// <value>The logger.</value>
|
||||
private ILogger Logger { get; set; }
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the task manager.
|
||||
/// Gets or sets the task manager.
|
||||
/// </summary>
|
||||
/// <value>The task manager.</value>
|
||||
private ITaskManager TaskManager { get; set; }
|
||||
private readonly ITaskManager _taskManager;
|
||||
|
||||
/// <summary>
|
||||
/// The _last execution result sync lock.
|
||||
/// </summary>
|
||||
private readonly object _lastExecutionResultSyncLock = new object();
|
||||
|
||||
private bool _readFromFile = false;
|
||||
|
||||
/// <summary>
|
||||
/// The _last execution result.
|
||||
/// </summary>
|
||||
private TaskResult _lastExecutionResult;
|
||||
|
||||
private Task _currentTask;
|
||||
|
||||
/// <summary>
|
||||
/// The _triggers.
|
||||
/// </summary>
|
||||
private Tuple<TaskTriggerInfo, ITaskTrigger>[] _triggers;
|
||||
|
||||
/// <summary>
|
||||
/// The _id.
|
||||
/// </summary>
|
||||
private string _id;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class.
|
||||
@@ -70,7 +86,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
/// or
|
||||
/// jsonSerializer
|
||||
/// or
|
||||
/// logger
|
||||
/// logger.
|
||||
/// </exception>
|
||||
public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger)
|
||||
{
|
||||
@@ -100,23 +116,22 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
}
|
||||
|
||||
ScheduledTask = scheduledTask;
|
||||
ApplicationPaths = applicationPaths;
|
||||
TaskManager = taskManager;
|
||||
JsonSerializer = jsonSerializer;
|
||||
Logger = logger;
|
||||
_applicationPaths = applicationPaths;
|
||||
_taskManager = taskManager;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_logger = logger;
|
||||
|
||||
InitTriggerEvents();
|
||||
}
|
||||
|
||||
private bool _readFromFile = false;
|
||||
public event EventHandler<GenericEventArgs<double>> TaskProgress;
|
||||
|
||||
/// <summary>
|
||||
/// The _last execution result.
|
||||
/// Gets the scheduled task.
|
||||
/// </summary>
|
||||
private TaskResult _lastExecutionResult;
|
||||
/// <summary>
|
||||
/// The _last execution result sync lock.
|
||||
/// </summary>
|
||||
private readonly object _lastExecutionResultSyncLock = new object();
|
||||
/// <value>The scheduled task.</value>
|
||||
public IScheduledTask ScheduledTask { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last execution result.
|
||||
/// </summary>
|
||||
@@ -135,11 +150,11 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
try
|
||||
{
|
||||
_lastExecutionResult = JsonSerializer.DeserializeFromFile<TaskResult>(path);
|
||||
_lastExecutionResult = _jsonSerializer.DeserializeFromFile<TaskResult>(path);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error deserializing {File}", path);
|
||||
_logger.LogError(ex, "Error deserializing {File}", path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +174,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
|
||||
lock (_lastExecutionResultSyncLock)
|
||||
{
|
||||
JsonSerializer.SerializeToFile(value, path);
|
||||
_jsonSerializer.SerializeToFile(value, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,7 +198,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
public string Category => ScheduledTask.Category;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current cancellation token.
|
||||
/// Gets or sets the current cancellation token.
|
||||
/// </summary>
|
||||
/// <value>The current cancellation token source.</value>
|
||||
private CancellationTokenSource CurrentCancellationTokenSource { get; set; }
|
||||
@@ -220,12 +235,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
public double? CurrentProgress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The _triggers.
|
||||
/// </summary>
|
||||
private Tuple<TaskTriggerInfo, ITaskTrigger>[] _triggers;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the triggers that define when the task will run.
|
||||
/// Gets or sets the triggers that define when the task will run.
|
||||
/// </summary>
|
||||
/// <value>The triggers.</value>
|
||||
private Tuple<TaskTriggerInfo, ITaskTrigger>[] InternalTriggers
|
||||
@@ -254,7 +264,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
/// Gets the triggers that define when the task will run.
|
||||
/// </summary>
|
||||
/// <value>The triggers.</value>
|
||||
/// <exception cref="ArgumentNullException">value</exception>
|
||||
/// <exception cref="ArgumentNullException"><c>value</c> is <c>null</c>.</exception>
|
||||
public TaskTriggerInfo[] Triggers
|
||||
{
|
||||
get
|
||||
@@ -279,11 +289,6 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The _id.
|
||||
/// </summary>
|
||||
private string _id;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique id.
|
||||
/// </summary>
|
||||
@@ -324,9 +329,9 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
|
||||
trigger.Stop();
|
||||
|
||||
trigger.Triggered -= trigger_Triggered;
|
||||
trigger.Triggered += trigger_Triggered;
|
||||
trigger.Start(LastExecutionResult, Logger, Name, isApplicationStartup);
|
||||
trigger.Triggered -= OnTriggerTriggered;
|
||||
trigger.Triggered += OnTriggerTriggered;
|
||||
trigger.Start(LastExecutionResult, _logger, Name, isApplicationStartup);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +340,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
/// </summary>
|
||||
/// <param name="sender">The source of the event.</param>
|
||||
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
||||
async void trigger_Triggered(object sender, EventArgs e)
|
||||
private async void OnTriggerTriggered(object sender, EventArgs e)
|
||||
{
|
||||
var trigger = (ITaskTrigger)sender;
|
||||
|
||||
@@ -346,19 +351,17 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInformation("{0} fired for task: {1}", trigger.GetType().Name, Name);
|
||||
_logger.LogInformation("{0} fired for task: {1}", trigger.GetType().Name, Name);
|
||||
|
||||
trigger.Stop();
|
||||
|
||||
TaskManager.QueueScheduledTask(ScheduledTask, trigger.TaskOptions);
|
||||
_taskManager.QueueScheduledTask(ScheduledTask, trigger.TaskOptions);
|
||||
|
||||
await Task.Delay(1000).ConfigureAwait(false);
|
||||
|
||||
trigger.Start(LastExecutionResult, Logger, Name, false);
|
||||
trigger.Start(LastExecutionResult, _logger, Name, false);
|
||||
}
|
||||
|
||||
private Task _currentTask;
|
||||
|
||||
/// <summary>
|
||||
/// Executes the task.
|
||||
/// </summary>
|
||||
@@ -394,9 +397,9 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
|
||||
CurrentCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
Logger.LogInformation("Executing {0}", Name);
|
||||
_logger.LogInformation("Executing {0}", Name);
|
||||
|
||||
((TaskManager)TaskManager).OnTaskExecuting(this);
|
||||
((TaskManager)_taskManager).OnTaskExecuting(this);
|
||||
|
||||
progress.ProgressChanged += OnProgressChanged;
|
||||
|
||||
@@ -422,7 +425,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error");
|
||||
_logger.LogError(ex, "Error");
|
||||
|
||||
failureException = ex;
|
||||
|
||||
@@ -475,7 +478,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
if (State == TaskState.Running)
|
||||
{
|
||||
Logger.LogInformation("Attempting to cancel Scheduled Task {0}", Name);
|
||||
_logger.LogInformation("Attempting to cancel Scheduled Task {0}", Name);
|
||||
CurrentCancellationTokenSource.Cancel();
|
||||
}
|
||||
}
|
||||
@@ -486,7 +489,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
/// <returns>System.String.</returns>
|
||||
private string GetScheduledTasksConfigurationDirectory()
|
||||
{
|
||||
return Path.Combine(ApplicationPaths.ConfigurationDirectoryPath, "ScheduledTasks");
|
||||
return Path.Combine(_applicationPaths.ConfigurationDirectoryPath, "ScheduledTasks");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -495,7 +498,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
/// <returns>System.String.</returns>
|
||||
private string GetScheduledTasksDataDirectory()
|
||||
{
|
||||
return Path.Combine(ApplicationPaths.DataPath, "ScheduledTasks");
|
||||
return Path.Combine(_applicationPaths.DataPath, "ScheduledTasks");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -534,7 +537,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
TaskTriggerInfo[] list = null;
|
||||
if (File.Exists(path))
|
||||
{
|
||||
list = JsonSerializer.DeserializeFromFile<TaskTriggerInfo[]>(path);
|
||||
list = _jsonSerializer.DeserializeFromFile<TaskTriggerInfo[]>(path);
|
||||
}
|
||||
|
||||
// Return defaults if file doesn't exist.
|
||||
@@ -570,7 +573,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
|
||||
JsonSerializer.SerializeToFile(triggers, path);
|
||||
_jsonSerializer.SerializeToFile(triggers, path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -584,7 +587,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
var elapsedTime = endTime - startTime;
|
||||
|
||||
Logger.LogInformation("{0} {1} after {2} minute(s) and {3} seconds", Name, status, Math.Truncate(elapsedTime.TotalMinutes), elapsedTime.Seconds);
|
||||
_logger.LogInformation("{0} {1} after {2} minute(s) and {3} seconds", Name, status, Math.Truncate(elapsedTime.TotalMinutes), elapsedTime.Seconds);
|
||||
|
||||
var result = new TaskResult
|
||||
{
|
||||
@@ -605,7 +608,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
|
||||
LastExecutionResult = result;
|
||||
|
||||
((TaskManager)TaskManager).OnTaskCompleted(this, result);
|
||||
((TaskManager)_taskManager).OnTaskCompleted(this, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -614,6 +617,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -634,12 +638,12 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogInformation(Name + ": Cancelling");
|
||||
_logger.LogInformation(Name + ": Cancelling");
|
||||
token.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error calling CancellationToken.Cancel();");
|
||||
_logger.LogError(ex, "Error calling CancellationToken.Cancel();");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -648,21 +652,21 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogInformation(Name + ": Waiting on Task");
|
||||
_logger.LogInformation(Name + ": Waiting on Task");
|
||||
var exited = Task.WaitAll(new[] { task }, 2000);
|
||||
|
||||
if (exited)
|
||||
{
|
||||
Logger.LogInformation(Name + ": Task exited");
|
||||
_logger.LogInformation(Name + ": Task exited");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInformation(Name + ": Timed out waiting for task to stop");
|
||||
_logger.LogInformation(Name + ": Timed out waiting for task to stop");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error calling Task.WaitAll();");
|
||||
_logger.LogError(ex, "Error calling Task.WaitAll();");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -670,12 +674,12 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogDebug(Name + ": Disposing CancellationToken");
|
||||
_logger.LogDebug(Name + ": Disposing CancellationToken");
|
||||
token.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error calling CancellationToken.Dispose();");
|
||||
_logger.LogError(ex, "Error calling CancellationToken.Dispose();");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,8 +695,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
/// </summary>
|
||||
/// <param name="info">The info.</param>
|
||||
/// <returns>BaseTaskTrigger.</returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
/// <exception cref="ArgumentException">Invalid trigger type: + info.Type</exception>
|
||||
/// <exception cref="ArgumentException">Invalid trigger type: + info.Type.</exception>
|
||||
private ITaskTrigger GetTrigger(TaskTriggerInfo info)
|
||||
{
|
||||
var options = new TaskOptions
|
||||
@@ -764,7 +767,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
foreach (var triggerInfo in InternalTriggers)
|
||||
{
|
||||
var trigger = triggerInfo.Item2;
|
||||
trigger.Triggered -= trigger_Triggered;
|
||||
trigger.Triggered -= OnTriggerTriggered;
|
||||
trigger.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +207,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
||||
namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
{
|
||||
@@ -15,12 +16,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
/// </summary>
|
||||
public class DeleteLogFileTask : IScheduledTask, IConfigurableScheduledTask
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the configuration manager.
|
||||
/// </summary>
|
||||
/// <value>The configuration manager.</value>
|
||||
private IConfigurationManager ConfigurationManager { get; set; }
|
||||
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
@@ -32,18 +28,43 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
/// <param name="localization">The localization manager.</param>
|
||||
public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization)
|
||||
{
|
||||
ConfigurationManager = configurationManager;
|
||||
_configurationManager = configurationManager;
|
||||
_fileSystem = fileSystem;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => _localization.GetLocalizedString("TaskCleanLogs");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
_localization.GetLocalizedString("TaskCleanLogsDescription"),
|
||||
_configurationManager.CommonConfiguration.LogFileRetentionDays);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => "CleanLogFiles";
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsLogged => true;
|
||||
|
||||
/// <summary>
|
||||
/// Creates the triggers that define when the task will run.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{BaseTaskTrigger}.</returns>
|
||||
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||
{
|
||||
return new[] {
|
||||
return new[]
|
||||
{
|
||||
new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
|
||||
};
|
||||
}
|
||||
@@ -57,10 +78,10 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
|
||||
{
|
||||
// Delete log files more than n days old
|
||||
var minDateModified = DateTime.UtcNow.AddDays(-ConfigurationManager.CommonConfiguration.LogFileRetentionDays);
|
||||
var minDateModified = DateTime.UtcNow.AddDays(-_configurationManager.CommonConfiguration.LogFileRetentionDays);
|
||||
|
||||
// Only delete the .txt log files, the *.log files created by serilog get managed by itself
|
||||
var filesToDelete = _fileSystem.GetFiles(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath, new[] { ".txt" }, true, true)
|
||||
var filesToDelete = _fileSystem.GetFiles(_configurationManager.CommonApplicationPaths.LogDirectoryPath, new[] { ".txt" }, true, true)
|
||||
.Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
|
||||
.ToList();
|
||||
|
||||
@@ -83,26 +104,5 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => _localization.GetLocalizedString("TaskCleanLogs");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => string.Format(_localization.GetLocalizedString("TaskCleanLogsDescription"), ConfigurationManager.CommonConfiguration.LogFileRetentionDays);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => "CleanLogFiles";
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsLogged => true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,8 +80,8 @@ namespace Emby.Server.Implementations.Services
|
||||
|
||||
public static List<string> GetFirstMatchWildCardHashKeys(string[] pathPartsForMatching)
|
||||
{
|
||||
const string hashPrefix = WildCard + PathSeperator;
|
||||
return GetPotentialMatchesWithPrefix(hashPrefix, pathPartsForMatching);
|
||||
const string HashPrefix = WildCard + PathSeperator;
|
||||
return GetPotentialMatchesWithPrefix(HashPrefix, pathPartsForMatching);
|
||||
}
|
||||
|
||||
private static List<string> GetPotentialMatchesWithPrefix(string hashPrefix, string[] pathPartsForMatching)
|
||||
@@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.Services
|
||||
{
|
||||
list.Add(hashPrefix + part);
|
||||
|
||||
if (part.IndexOf(ComponentSeperator) == -1)
|
||||
if (part.IndexOf(ComponentSeperator, StringComparison.Ordinal) == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -130,7 +130,7 @@ namespace Emby.Server.Implementations.Services
|
||||
}
|
||||
|
||||
if (component.IndexOf(VariablePrefix, StringComparison.OrdinalIgnoreCase) != -1
|
||||
&& component.IndexOf(ComponentSeperator) != -1)
|
||||
&& component.IndexOf(ComponentSeperator, StringComparison.Ordinal) != -1)
|
||||
{
|
||||
hasSeparators.Add(true);
|
||||
componentsList.AddRange(component.Split(ComponentSeperator));
|
||||
|
||||
Reference in New Issue
Block a user