add search methods to remote metadata providers

This commit is contained in:
Luke Pulverenti
2014-02-19 23:53:15 -05:00
parent 120c8bcbb9
commit 13e4b2a6a7
45 changed files with 524 additions and 166 deletions

View File

@@ -2,7 +2,6 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
@@ -28,10 +27,11 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
private readonly IFileSystem _fileSystem;
private readonly IFileOrganizationService _organizationService;
private readonly IServerConfigurationManager _config;
private readonly IProviderManager _providerManager;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
public EpisodeFileOrganizer(IFileOrganizationService organizationService, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor)
public EpisodeFileOrganizer(IFileOrganizationService organizationService, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager)
{
_organizationService = organizationService;
_config = config;
@@ -39,9 +39,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_logger = logger;
_libraryManager = libraryManager;
_libraryMonitor = libraryMonitor;
_providerManager = providerManager;
}
public async Task<FileOrganizationResult> OrganizeEpisodeFile(string path, TvFileOrganizationOptions options, bool overwriteExisting)
public async Task<FileOrganizationResult> OrganizeEpisodeFile(string path, TvFileOrganizationOptions options, bool overwriteExisting, CancellationToken cancellationToken)
{
_logger.Info("Sorting file {0}", path);
@@ -77,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;
OrganizeEpisode(path, seriesName, season.Value, episode.Value, endingEpisodeNumber, options, overwriteExisting, result);
await OrganizeEpisode(path, seriesName, season.Value, episode.Value, endingEpisodeNumber, options, overwriteExisting, result, cancellationToken).ConfigureAwait(false);
}
else
{
@@ -119,20 +120,20 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
return result;
}
public async Task<FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options)
public async Task<FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options, CancellationToken cancellationToken)
{
var result = _organizationService.GetResult(request.ResultId);
var series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId));
OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, _config.Configuration.TvFileOrganizationOptions, true, result);
await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, _config.Configuration.TvFileOrganizationOptions, true, result, cancellationToken).ConfigureAwait(false);
await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
return result;
}
private void OrganizeEpisode(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result)
private Task OrganizeEpisode(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result, CancellationToken cancellationToken)
{
var series = GetMatchingSeries(seriesName, result);
@@ -142,18 +143,18 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
result.Status = FileSortingStatus.Failure;
result.StatusMessage = msg;
_logger.Warn(msg);
return;
return Task.FromResult(true);
}
OrganizeEpisode(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, overwriteExisting, result);
return OrganizeEpisode(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, overwriteExisting, result, cancellationToken);
}
private void OrganizeEpisode(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result)
private async Task OrganizeEpisode(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result, CancellationToken cancellationToken)
{
_logger.Info("Sorting file {0} into series {1}", sourcePath, series.Path);
// Proceed to sort the file
var newPath = GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options);
var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, cancellationToken).ConfigureAwait(false);
if (string.IsNullOrEmpty(newPath))
{
@@ -326,25 +327,33 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
/// <param name="endingEpisodeNumber">The ending episode number.</param>
/// <param name="options">The options.</param>
/// <returns>System.String.</returns>
private string GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, TvFileOrganizationOptions options)
private async Task<string> GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, TvFileOrganizationOptions options, CancellationToken cancellationToken)
{
// If season and episode numbers match
var currentEpisodes = series.RecursiveChildren.OfType<Episode>()
.Where(i => i.IndexNumber.HasValue &&
i.IndexNumber.Value == episodeNumber &&
i.ParentIndexNumber.HasValue &&
i.ParentIndexNumber.Value == seasonNumber)
.ToList();
var episodeInfo = new EpisodeInfo
{
IndexNumber = episodeNumber,
IndexNumberEnd = endingEpisodeNumber,
MetadataCountryCode = series.GetPreferredMetadataCountryCode(),
MetadataLanguage = series.GetPreferredMetadataLanguage(),
ParentIndexNumber = seasonNumber,
SeriesProviderIds = series.ProviderIds
};
if (currentEpisodes.Count == 0)
var searchResults = await _providerManager.GetRemoteSearchResults<Episode, EpisodeInfo>(new RemoteSearchQuery<EpisodeInfo>
{
SearchInfo = episodeInfo
}, cancellationToken).ConfigureAwait(false);
var episode = searchResults.FirstOrDefault();
if (episode == null)
{
return null;
}
var newPath = GetSeasonFolderPath(series, seasonNumber, options);
var episode = currentEpisodes.First();
var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options);
newPath = Path.Combine(newPath, episodeFileName);

View File

@@ -3,9 +3,9 @@ using MediaBrowser.Common.IO;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.FileOrganization;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
@@ -25,8 +25,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
private readonly IProviderManager _providerManager;
public FileOrganizationService(ITaskManager taskManager, IFileOrganizationRepository repo, ILogger logger, ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, IServerConfigurationManager config, IFileSystem fileSystem)
public FileOrganizationService(ITaskManager taskManager, IFileOrganizationRepository repo, ILogger logger, ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager)
{
_taskManager = taskManager;
_repo = repo;
@@ -35,6 +36,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_libraryManager = libraryManager;
_config = config;
_fileSystem = fileSystem;
_providerManager = providerManager;
}
public void BeginProcessNewFiles()
@@ -103,9 +105,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
}
var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager,
_libraryMonitor);
_libraryMonitor, _providerManager);
await organizer.OrganizeEpisodeFile(result.OriginalPath, _config.Configuration.TvFileOrganizationOptions, true)
await organizer.OrganizeEpisodeFile(result.OriginalPath, _config.Configuration.TvFileOrganizationOptions, true, CancellationToken.None)
.ConfigureAwait(false);
}
@@ -117,9 +119,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
public async Task PerformEpisodeOrganization(EpisodeFileOrganizationRequest request)
{
var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager,
_libraryMonitor);
_libraryMonitor, _providerManager);
await organizer.OrganizeWithCorrection(request, _config.Configuration.TvFileOrganizationOptions).ConfigureAwait(false);
await organizer.OrganizeWithCorrection(request, _config.Configuration.TvFileOrganizationOptions, CancellationToken.None).ConfigureAwait(false);
}
}
}

View File

@@ -2,8 +2,8 @@
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
@@ -20,8 +20,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
private readonly IFileSystem _fileSystem;
private readonly IServerConfigurationManager _config;
private readonly IFileOrganizationService _organizationService;
private readonly IProviderManager _providerManager;
public OrganizerScheduledTask(ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IServerConfigurationManager config, IFileOrganizationService organizationService)
public OrganizerScheduledTask(ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IServerConfigurationManager config, IFileOrganizationService organizationService, IProviderManager providerManager)
{
_libraryMonitor = libraryMonitor;
_libraryManager = libraryManager;
@@ -29,6 +30,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_fileSystem = fileSystem;
_config = config;
_organizationService = organizationService;
_providerManager = providerManager;
}
public string Name
@@ -48,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{
return new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config)
return new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config, _providerManager)
.Organize(_config.Configuration.TvFileOrganizationOptions, cancellationToken, progress);
}

View File

@@ -1,8 +1,8 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.FileOrganization;
@@ -24,8 +24,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
private readonly IFileSystem _fileSystem;
private readonly IFileOrganizationService _organizationService;
private readonly IServerConfigurationManager _config;
private readonly IProviderManager _providerManager;
public TvFolderOrganizer(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IFileOrganizationService organizationService, IServerConfigurationManager config)
public TvFolderOrganizer(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IFileOrganizationService organizationService, IServerConfigurationManager config, IProviderManager providerManager)
{
_libraryManager = libraryManager;
_logger = logger;
@@ -33,6 +34,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_libraryMonitor = libraryMonitor;
_organizationService = organizationService;
_config = config;
_providerManager = providerManager;
}
public async Task Organize(TvFileOrganizationOptions options, CancellationToken cancellationToken, IProgress<double> progress)
@@ -57,9 +59,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
foreach (var file in eligibleFiles)
{
var organizer = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager,
_libraryMonitor);
_libraryMonitor, _providerManager);
var result = await organizer.OrganizeEpisodeFile(file.FullName, options, false).ConfigureAwait(false);
var result = await organizer.OrganizeEpisodeFile(file.FullName, options, false, cancellationToken).ConfigureAwait(false);
if (result.Status == FileSortingStatus.Success)
{

View File

@@ -1,4 +1,5 @@
using Funq;
using System.Net.Sockets;
using Funq;
using MediaBrowser.Common;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;

View File

@@ -3,7 +3,6 @@ using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations.ScheduledTasks;
using Microsoft.Win32;

View File

@@ -408,8 +408,14 @@ namespace MediaBrowser.Server.Implementations.Library
LibraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; });
}
public async Task DeleteItem(BaseItem item)
public async Task DeleteItem(BaseItem item, DeleteOptions options)
{
_logger.Debug("Deleting item, Type: {0}, Name: {1}, Path: {2}, Id: {3}",
item.GetType().Name,
item.Name,
item.Path ?? string.Empty,
item.Id);
var parent = item.Parent;
var locationType = item.LocationType;
@@ -436,7 +442,7 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
if (locationType == LocationType.FileSystem || locationType == LocationType.Offline)
if (options.DeleteFileLocation && (locationType == LocationType.FileSystem || locationType == LocationType.Offline))
{
foreach (var path in item.GetDeletePaths().ToList())
{
@@ -462,15 +468,14 @@ namespace MediaBrowser.Server.Implementations.Library
{
await parent.RemoveChild(item, CancellationToken.None).ConfigureAwait(false);
}
else
{
throw new InvalidOperationException("Don't know how to delete " + item.Name);
}
await ItemRepository.DeleteItem(item.Id, CancellationToken.None).ConfigureAwait(false);
foreach (var child in children)
{
await ItemRepository.DeleteItem(child.Id, CancellationToken.None).ConfigureAwait(false);
}
ReportItemRemoved(item);
}
private IEnumerable<string> GetMetadataPaths(BaseItem item, IEnumerable<BaseItem> children)

View File

@@ -726,7 +726,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
foreach (var channelInfo in allChannelsList)
{
cancellationToken.ThrowIfCancellationRequested();
try
{
var item = await GetChannel(channelInfo.Item2, channelInfo.Item1, cancellationToken).ConfigureAwait(false);
@@ -764,7 +764,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
foreach (var item in list)
{
cancellationToken.ThrowIfCancellationRequested();
// Avoid implicitly captured closure
var currentChannel = item;
@@ -793,17 +793,44 @@ namespace MediaBrowser.Server.Implementations.LiveTv
double percent = numComplete;
percent /= allChannelsList.Count;
progress.Report(80 * percent + 10);
progress.Report(70 * percent + 10);
}
_programs = programs.ToDictionary(i => i.Id);
progress.Report(80);
// Load these now which will prefetch metadata
await GetRecordings(new RecordingQuery(), cancellationToken).ConfigureAwait(false);
progress.Report(85);
await DeleteOldPrograms(_programs.Keys.ToList(), progress, cancellationToken).ConfigureAwait(false);
progress.Report(100);
}
private async Task DeleteOldPrograms(List<Guid> currentIdList, IProgress<double> progress, CancellationToken cancellationToken)
{
var list = _itemRepo.GetItemsOfType(typeof(LiveTvProgram)).ToList();
var numComplete = 0;
foreach (var program in list)
{
cancellationToken.ThrowIfCancellationRequested();
if (!currentIdList.Contains(program.Id))
{
await _libraryManager.DeleteItem(program).ConfigureAwait(false);
}
numComplete++;
double percent = numComplete;
percent /= list.Count;
progress.Report(15 * percent + 85);
}
}
private double GetGuideDays(int channelCount)
{
if (_config.Configuration.LiveTvOptions.GuideDays.HasValue)

View File

@@ -281,27 +281,32 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
if (reader.Read())
{
var typeString = reader.GetString(0);
var type = _typeMapper.GetType(typeString);
if (type == null)
{
_logger.Debug("Unknown type {0}", typeString);
return null;
}
using (var stream = reader.GetMemoryStream(1))
{
return _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem;
}
return GetItem(reader);
}
}
return null;
}
}
private BaseItem GetItem(IDataReader reader)
{
var typeString = reader.GetString(0);
var type = _typeMapper.GetType(typeString);
if (type == null)
{
_logger.Debug("Unknown type {0}", typeString);
return null;
}
using (var stream = reader.GetMemoryStream(1))
{
return _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem;
}
}
/// <summary>
/// Gets the critic reviews.
/// </summary>
@@ -468,6 +473,34 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
public IEnumerable<BaseItem> GetItemsOfType(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select type,data from TypedBaseItems where type = @type";
cmd.Parameters.Add(cmd, "@type", DbType.String).Value = type.FullName;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
var item = GetItem(reader);
if (item != null)
{
yield return item;
}
}
}
}
}
public async Task DeleteItem(Guid id, CancellationToken cancellationToken)
{
if (id == Guid.Empty)