diff options
10 files changed, 138 insertions, 154 deletions
diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index dfe7d70ee..1688fac8b 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -92,7 +92,6 @@ <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="ScheduledTasks\ScheduledTaskWorker.cs" /> <Compile Include="ScheduledTasks\TaskManager.cs" /> - <Compile Include="ScheduledTasks\Tasks\StatisticsTask.cs" /> <Compile Include="ScheduledTasks\Tasks\DeleteCacheFileTask.cs" /> <Compile Include="ScheduledTasks\Tasks\DeleteLogFileTask.cs" /> <Compile Include="ScheduledTasks\Tasks\PluginUpdateTask.cs" /> @@ -105,6 +104,7 @@ <Compile Include="Serialization\XmlSerializer.cs" /> <Compile Include="Updates\ApplicationUpdater.cs" /> <Compile Include="Updates\InstallationManager.cs" /> + <Compile Include="Security\UsageReporter.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/StatisticsTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/StatisticsTask.cs deleted file mode 100644 index 9c0fe165d..000000000 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/StatisticsTask.cs +++ /dev/null @@ -1,127 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks -{ - /// <summary> - /// Class ReloadLoggerFileTask - /// </summary> - public class StatisticsTask : IScheduledTask, IConfigurableScheduledTask - { - /// <summary> - /// Gets or sets the log manager. - /// </summary> - /// <value>The log manager.</value> - private ILogManager LogManager { get; set; } - /// <summary> - /// Gets or sets the app host - /// </summary> - /// <value>The application host.</value> - private IApplicationHost ApplicationHost { get; set; } - - /// <summary> - /// The network manager - /// </summary> - private INetworkManager NetworkManager { get; set; } - - /// <summary> - /// The http client - /// </summary> - private IHttpClient HttpClient { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="ReloadLoggerFileTask" /> class. - /// </summary> - /// <param name="logManager">The logManager.</param> - /// <param name="appHost"></param> - /// <param name="httpClient"></param> - public StatisticsTask(ILogManager logManager, IApplicationHost appHost, INetworkManager networkManager, IHttpClient httpClient) - { - LogManager = logManager; - ApplicationHost = appHost; - NetworkManager = networkManager; - HttpClient = httpClient; - } - - /// <summary> - /// Gets the default triggers. - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - var trigger = new DailyTrigger { TimeOfDay = TimeSpan.FromHours(20) }; //8pm - when the system is most likely to be active - var trigger2 = new StartupTrigger(); //and also at system start - - return new ITaskTrigger[] { trigger, trigger2 }; - } - - /// <summary> - /// Executes the internal. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - cancellationToken.ThrowIfCancellationRequested(); - - progress.Report(0); - var mac = NetworkManager.GetMacAddress(); - - var data = new Dictionary<string, string> - { - { "feature", ApplicationHost.Name }, - { "mac", mac }, - { "ver", ApplicationHost.ApplicationVersion.ToString() }, - { "platform", Environment.OSVersion.VersionString }, - { "isservice", ApplicationHost.IsRunningAsService.ToString().ToLower()} - }; - - await HttpClient.Post(Constants.Constants.MbAdminUrl + "service/registration/ping", data, CancellationToken.None).ConfigureAwait(false); - progress.Report(100); - - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return "Collect anonymous usage stats"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public string Description - { - get { return "Pings the admin site just so we know how many folks are out there and what version they are on."; } - } - - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> - public string Category - { - get { return "Application"; } - } - - public bool IsHidden - { - get { return true; } - } - - public bool IsEnabled - { - get { return true; } - } - } -} diff --git a/MediaBrowser.Common.Implementations/Security/UsageReporter.cs b/MediaBrowser.Common.Implementations/Security/UsageReporter.cs new file mode 100644 index 000000000..e32940be9 --- /dev/null +++ b/MediaBrowser.Common.Implementations/Security/UsageReporter.cs @@ -0,0 +1,40 @@ +using MediaBrowser.Common.Net; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Common.Implementations.Security +{ + public class UsageReporter + { + private readonly IApplicationHost _applicationHost; + private readonly INetworkManager _networkManager; + private readonly IHttpClient _httpClient; + + public UsageReporter(IApplicationHost applicationHost, INetworkManager networkManager, IHttpClient httpClient) + { + _applicationHost = applicationHost; + _networkManager = networkManager; + _httpClient = httpClient; + } + + public Task ReportUsage(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var mac = _networkManager.GetMacAddress(); + + var data = new Dictionary<string, string> + { + { "feature", _applicationHost.Name }, + { "mac", mac }, + { "ver", _applicationHost.ApplicationVersion.ToString() }, + { "platform", Environment.OSVersion.VersionString }, + { "isservice", _applicationHost.IsRunningAsService.ToString().ToLower()} + }; + + return _httpClient.Post(Constants.Constants.MbAdminUrl + "service/registration/ping", data, cancellationToken); + } + } +} diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index e68790e61..2583450a3 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -142,7 +142,7 @@ namespace MediaBrowser.Controller.Entities.Audio // Refresh songs foreach (var item in songs) { - if (tasks.Count >= 2) + if (tasks.Count >= 3) { await Task.WhenAll(tasks).ConfigureAwait(false); tasks.Clear(); @@ -166,7 +166,8 @@ namespace MediaBrowser.Controller.Entities.Audio } }); - tasks.Add(RefreshItem(item, refreshOptions, innerProgress, cancellationToken)); + var taskChild = item; + tasks.Add(Task.Run(async () => await RefreshItem(taskChild, refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false), cancellationToken)); } await Task.WhenAll(tasks).ConfigureAwait(false); @@ -178,7 +179,7 @@ namespace MediaBrowser.Controller.Entities.Audio // Refresh all non-songs foreach (var item in others) { - if (tasks.Count > 4) + if (tasks.Count > 3) { await Task.WhenAll(tasks).ConfigureAwait(false); tasks.Clear(); diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs index d53eba11a..e07db88c4 100644 --- a/MediaBrowser.Controller/Entities/IHasImages.cs +++ b/MediaBrowser.Controller/Entities/IHasImages.cs @@ -142,6 +142,12 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value><c>true</c> if [supports local metadata]; otherwise, <c>false</c>.</value> bool SupportsLocalMetadata { get; } + + /// <summary> + /// Gets a value indicating whether this instance is in mixed folder. + /// </summary> + /// <value><c>true</c> if this instance is in mixed folder; otherwise, <c>false</c>.</value> + bool IsInMixedFolder { get; } } public static class HasImagesExtensions diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 691a5add6..4aeb86a6a 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="imageIndex">Index of the image.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - Task SaveImage(BaseItem item, string url, SemaphoreSlim resourcePool, ImageType type, int? imageIndex, CancellationToken cancellationToken); + Task SaveImage(IHasImages item, string url, SemaphoreSlim resourcePool, ImageType type, int? imageIndex, CancellationToken cancellationToken); /// <summary> /// Saves the image. @@ -46,7 +46,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="imageIndex">Index of the image.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken); + Task SaveImage(IHasImages item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken); /// <summary> /// Adds the metadata providers. diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index bac90ae37..0e184d163 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -62,14 +62,14 @@ namespace MediaBrowser.Providers.Manager /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException">mimeType</exception> - public async Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken) + public async Task SaveImage(IHasImages item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(mimeType)) { throw new ArgumentNullException("mimeType"); } - var saveLocally = item.IsSaveLocalMetadataEnabled() && item.Parent != null && !(item is Audio); + var saveLocally = item.SupportsLocalMetadata && item.IsSaveLocalMetadataEnabled() && !item.IsOwnedItem && !(item is Audio); if (item is IItemByName || item is User) { @@ -93,7 +93,7 @@ namespace MediaBrowser.Providers.Manager { var series = season.Series; - if (series != null && series.SupportsLocalMetadata) + if (series != null && series.SupportsLocalMetadata && series.IsSaveLocalMetadataEnabled()) { saveLocally = true; } @@ -224,7 +224,7 @@ namespace MediaBrowser.Providers.Manager /// <param name="mimeType">Type of the MIME.</param> /// <param name="saveLocally">if set to <c>true</c> [save locally].</param> /// <returns>IEnumerable{System.String}.</returns> - private string[] GetSavePaths(BaseItem item, ImageType type, int? imageIndex, string mimeType, bool saveLocally) + private string[] GetSavePaths(IHasImages item, ImageType type, int? imageIndex, string mimeType, bool saveLocally) { if (_config.Configuration.ImageSavingConvention == ImageSavingConvention.Legacy || !saveLocally) { @@ -261,7 +261,7 @@ namespace MediaBrowser.Providers.Manager /// <exception cref="System.ArgumentNullException">imageIndex /// or /// imageIndex</exception> - private void SetImagePath(BaseItem item, ImageType type, int? imageIndex, string path) + private void SetImagePath(IHasImages item, ImageType type, int? imageIndex, string path) { item.SetImagePath(type, imageIndex ?? 0, new FileInfo(path)); } @@ -280,7 +280,7 @@ namespace MediaBrowser.Providers.Manager /// or /// imageIndex /// </exception> - private string GetStandardSavePath(BaseItem item, ImageType type, int? imageIndex, string mimeType, bool saveLocally) + private string GetStandardSavePath(IHasImages item, ImageType type, int? imageIndex, string mimeType, bool saveLocally) { string filename; @@ -378,7 +378,7 @@ namespace MediaBrowser.Providers.Manager /// <param name="mimeType">Type of the MIME.</param> /// <returns>IEnumerable{System.String}.</returns> /// <exception cref="System.ArgumentNullException">imageIndex</exception> - private string[] GetCompatibleSavePaths(BaseItem item, ImageType type, int? imageIndex, string mimeType) + private string[] GetCompatibleSavePaths(IHasImages item, ImageType type, int? imageIndex, string mimeType) { var season = item as Season; @@ -405,13 +405,13 @@ namespace MediaBrowser.Providers.Manager return new[] { GetSavePathForItemInMixedFolder(item, type, "fanart", extension) }; } - if (season != null && item.IndexNumber.HasValue) + if (season != null && season.IndexNumber.HasValue) { var seriesFolder = season.SeriesPath; - var seasonMarker = item.IndexNumber.Value == 0 + var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : item.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", UsCulture); var imageFilename = "season" + seasonMarker + "-fanart" + extension; @@ -442,13 +442,13 @@ namespace MediaBrowser.Providers.Manager if (type == ImageType.Primary) { - if (season != null && item.IndexNumber.HasValue) + if (season != null && season.IndexNumber.HasValue) { var seriesFolder = season.SeriesPath; - var seasonMarker = item.IndexNumber.Value == 0 + var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : item.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", UsCulture); var imageFilename = "season" + seasonMarker + "-poster" + extension; @@ -479,13 +479,13 @@ namespace MediaBrowser.Providers.Manager if (type == ImageType.Banner) { - if (season != null && item.IndexNumber.HasValue) + if (season != null && season.IndexNumber.HasValue) { var seriesFolder = season.SeriesPath; - var seasonMarker = item.IndexNumber.Value == 0 + var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : item.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", UsCulture); var imageFilename = "season" + seasonMarker + "-banner" + extension; @@ -495,13 +495,13 @@ namespace MediaBrowser.Providers.Manager if (type == ImageType.Thumb) { - if (season != null && item.IndexNumber.HasValue) + if (season != null && season.IndexNumber.HasValue) { var seriesFolder = season.SeriesPath; - var seasonMarker = item.IndexNumber.Value == 0 + var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : item.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", UsCulture); var imageFilename = "season" + seasonMarker + "-landscape" + extension; diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 119ab0c66..ced9e4868 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -172,7 +172,7 @@ namespace MediaBrowser.Providers.Manager /// <param name="imageIndex">Index of the image.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public async Task SaveImage(BaseItem item, string url, SemaphoreSlim resourcePool, ImageType type, int? imageIndex, CancellationToken cancellationToken) + public async Task SaveImage(IHasImages item, string url, SemaphoreSlim resourcePool, ImageType type, int? imageIndex, CancellationToken cancellationToken) { var response = await _httpClient.GetResponse(new HttpRequestOptions { @@ -196,7 +196,7 @@ namespace MediaBrowser.Providers.Manager /// <param name="imageIndex">Index of the image.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken) + public Task SaveImage(IHasImages item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken) { return new ImageSaver(ConfigurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, source, mimeType, type, imageIndex, cancellationToken); } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs new file mode 100644 index 000000000..3ab47f51b --- /dev/null +++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs @@ -0,0 +1,63 @@ +using MediaBrowser.Common; +using MediaBrowser.Common.Implementations.Security; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Model.Logging; +using System; +using System.Threading; + +namespace MediaBrowser.Server.Implementations.EntryPoints +{ + /// <summary> + /// Class UsageEntryPoint + /// </summary> + public class UsageEntryPoint : IServerEntryPoint + { + private readonly IApplicationHost _applicationHost; + private readonly INetworkManager _networkManager; + private readonly IHttpClient _httpClient; + private readonly ILogger _logger; + + private Timer _timer; + private readonly TimeSpan _frequency = TimeSpan.FromHours(24); + + public UsageEntryPoint(ILogger logger, IApplicationHost applicationHost, INetworkManager networkManager, IHttpClient httpClient) + { + _logger = logger; + _applicationHost = applicationHost; + _networkManager = networkManager; + _httpClient = httpClient; + } + + public void Run() + { + _timer = new Timer(OnTimerFired, null, TimeSpan.FromMilliseconds(5000), _frequency); + } + + /// <summary> + /// Called when [timer fired]. + /// </summary> + /// <param name="state">The state.</param> + private async void OnTimerFired(object state) + { + try + { + await new UsageReporter(_applicationHost, _networkManager, _httpClient).ReportUsage(CancellationToken.None) + .ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error sending anonymous usage statistics.", ex); + } + } + + public void Dispose() + { + if (_timer != null) + { + _timer.Dispose(); + _timer = null; + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 050af69d0..5060dbed3 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -117,6 +117,7 @@ <Compile Include="EntryPoints\Notifications\RemoteNotifications.cs" /> <Compile Include="EntryPoints\Notifications\WebSocketNotifier.cs" /> <Compile Include="EntryPoints\RefreshUsersMetadata.cs" /> + <Compile Include="EntryPoints\UsageEntryPoint.cs" /> <Compile Include="FileOrganization\EpisodeFileOrganizer.cs" /> <Compile Include="FileOrganization\FileOrganizationService.cs" /> <Compile Include="FileOrganization\NameUtils.cs" /> |
