private Series CreateNewSeries( EpisodeFileOrganizationRequest request, BaseItem targetFolder, RemoteSearchResult result, TvFileOrganizationOptions options, CancellationToken cancellationToken) { Series series; series = GetMatchingSeries(request.NewSeriesName, request.NewSeriesYear, targetFolder, null); if (series != null) { return(series); } var seriesFolderName = GetSeriesDirectoryName(request.NewSeriesName, request.NewSeriesYear, options); var seriesName = request.NewSeriesName; var seriesPath = Path.Combine(request.TargetFolder, seriesFolderName); return(new Series { Name = seriesName, Path = seriesPath, ProviderIds = request.NewSeriesProviderIds, ProductionYear = request.NewSeriesYear }); }
public async Task PerformEpisodeOrganization(EpisodeFileOrganizationRequest request) { var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); await organizer.OrganizeWithCorrection(request, _config.Configuration.TvFileOrganizationOptions, CancellationToken.None).ConfigureAwait(false); }
public async Task PerformOrganization(EpisodeFileOrganizationRequest request) { var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); var options = GetAutoOrganizeOptions(); var result = await organizer.OrganizeWithCorrection(request, options.TvOptions, CancellationToken.None).ConfigureAwait(false); }
public async Task <FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, AutoOrganizeOptions options, CancellationToken cancellationToken) { var result = _organizationService.GetResult(request.ResultId); Series series = null; if (request.NewSeriesProviderIds.Count > 0) { // We're having a new series here SeriesInfo seriesRequest = new SeriesInfo(); seriesRequest.ProviderIds = request.NewSeriesProviderIds; var refreshOptions = new MetadataRefreshOptions(_fileSystem); series = new Series(); series.Id = Guid.NewGuid(); series.Name = request.NewSeriesName; int year; if (int.TryParse(request.NewSeriesYear, out year)) { series.ProductionYear = year; } var seriesFolderName = series.Name; if (series.ProductionYear.HasValue) { seriesFolderName = string.Format("{0} ({1})", seriesFolderName, series.ProductionYear); } series.Path = Path.Combine(request.TargetFolder, seriesFolderName); series.ProviderIds = request.NewSeriesProviderIds; await series.RefreshMetadata(refreshOptions, cancellationToken); } if (series == null) { // Existing Series series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId)); } await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, null, options, true, request.RememberCorrection, result, cancellationToken).ConfigureAwait(false); await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false); return(result); }
private async Task <Series> AutoDetectSeries( string seriesName, int?seriesYear, TvFileOrganizationOptions options, CancellationToken cancellationToken) { if (options.AutoDetectSeries) { RemoteSearchResult finalResult = null; // Perform remote search var seriesInfo = new SeriesInfo { Name = seriesName, Year = seriesYear }; var searchQuery = new RemoteSearchQuery <SeriesInfo> { SearchInfo = seriesInfo }; var searchResults = await _providerManager.GetRemoteSearchResults <Series, SeriesInfo>(searchQuery, cancellationToken).ConfigureAwait(false); // Group series by name and year (if 2 series with the exact same name, the same year ...) var groupedResult = searchResults.GroupBy( p => new { p.Name, p.ProductionYear }, p => p, (key, g) => new { Key = key, Result = g.ToList() }).ToList(); if (groupedResult.Count == 1) { finalResult = groupedResult.First().Result.First(); } else if (groupedResult.Count > 1) { var filtredResult = groupedResult .Select(i => new { Ref = i, Score = NameUtils.GetMatchScore(seriesName, seriesYear, i.Key.Name, i.Key.ProductionYear) }) .Where(i => i.Score > 0) .OrderByDescending(i => i.Score) .Select(i => i.Ref) .FirstOrDefault(); finalResult = filtredResult?.Result.First(); } if (finalResult != null) { // We are in the good position, we can create the item var organizationRequest = new EpisodeFileOrganizationRequest { NewSeriesName = finalResult.Name, NewSeriesProviderIds = finalResult.ProviderIds, NewSeriesYear = finalResult.ProductionYear, TargetFolder = options.DefaultSeriesLibraryPath }; return(await CreateNewSeries(organizationRequest, finalResult, options, cancellationToken).ConfigureAwait(false)); } } return(null); }
private async Task <Series> AutoDetectSeries( string seriesName, int?seriesYear, TvFileOrganizationOptions options, CancellationToken cancellationToken) { if (options.AutoDetectSeries) { string metadataLanguage = null; string metadataCountryCode = null; BaseItem targetFolder = null; if (!string.IsNullOrEmpty(options.DefaultSeriesLibraryPath)) { targetFolder = _libraryManager.FindByPath(options.DefaultSeriesLibraryPath, true); } if (targetFolder != null) { metadataLanguage = targetFolder.GetPreferredMetadataLanguage(); metadataCountryCode = targetFolder.GetPreferredMetadataCountryCode(); } var seriesInfo = new SeriesInfo { Name = seriesName, Year = seriesYear, MetadataCountryCode = metadataCountryCode, MetadataLanguage = metadataLanguage }; var searchResultsTask = await _providerManager.GetRemoteSearchResults <Series, SeriesInfo>(new RemoteSearchQuery <SeriesInfo> { SearchInfo = seriesInfo }, targetFolder, cancellationToken); var finalResult = searchResultsTask.FirstOrDefault(); if (finalResult != null) { // We are in the good position, we can create the item var organizationRequest = new EpisodeFileOrganizationRequest { NewSeriesName = finalResult.Name, NewSeriesProviderIds = finalResult.ProviderIds, NewSeriesYear = finalResult.ProductionYear, TargetFolder = options.DefaultSeriesLibraryPath }; return(CreateNewSeries(organizationRequest, targetFolder, finalResult, options, cancellationToken)); } } return(null); }
public async Task <FileOrganizationResult> OrganizeWithCorrection( EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options, CancellationToken cancellationToken) { var result = _organizationService.GetResult(request.ResultId); try { Series series = null; if (request.NewSeriesProviderIds.Count > 0) { BaseItem targetFolder = null; if (!string.IsNullOrEmpty(options.DefaultSeriesLibraryPath)) { targetFolder = _libraryManager.FindByPath(options.DefaultSeriesLibraryPath, true); } series = CreateNewSeries(request, targetFolder, null, options, cancellationToken); } if (series == null) { // Existing Series series = (Series)_libraryManager.GetItemById(request.SeriesId); } // We manually set the media as Series result.Type = CurrentFileOrganizerType; await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, null, options, request.RememberCorrection, result, cancellationToken).ConfigureAwait(false); _organizationService.SaveResult(result, CancellationToken.None); } catch (Exception ex) { result.Status = FileSortingStatus.Failure; result.StatusMessage = ex.Message; _logger.ErrorException("Error organizing file {0}", ex, result.OriginalPath); } return(result); }
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)); await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, options, true, result, cancellationToken).ConfigureAwait(false); await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false); return(result); }
public async Task PerformEpisodeOrganization(EpisodeFileOrganizationRequest request) { var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); var result = await organizer.OrganizeWithCorrection(request, GetAutoOrganizeOptions(), CancellationToken.None).ConfigureAwait(false); if (result.Status != FileSortingStatus.Success) { throw new Exception(result.StatusMessage); } }
private async Task <Series> CreateNewSeries( EpisodeFileOrganizationRequest request, RemoteSearchResult result, TvFileOrganizationOptions options, CancellationToken cancellationToken) { Series series; // Ensure that we don't create the same series multiple time // We create series one at a time var seriesCreationLock = new Object(); lock (seriesCreationLock) { series = GetMatchingSeries(request.NewSeriesName, request.NewSeriesYear, request.TargetFolder, null); if (series == null) { // We're having a new series here series = new Series { Id = Guid.NewGuid(), Name = request.NewSeriesName, ProductionYear = request.NewSeriesYear }; var seriesFolderName = GetSeriesDirectoryName(series, options); series.Path = Path.Combine(request.TargetFolder, seriesFolderName); // Create the folder _fileSystem.CreateDirectory(series.Path); series.ProviderIds = request.NewSeriesProviderIds; _libraryManager.CreateItem(series, null); } } // async outside of the lock for perfs var refreshOptions = new MetadataRefreshOptions(_fileSystem) { SearchResult = result }; await series.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); return(series); }
/// <summary> /// Organize an episode file with parameters provided by the end-user. /// </summary> /// <param name="request">The parameters provided by the user via API request.</param> /// <param name="options">The organization options to use.</param> /// <param name="cancellationToken">A cancellation token for the operation.</param> /// <returns>A task representing the organization operation and containing the operation result.</returns> public async Task <FileOrganizationResult> OrganizeWithCorrection( EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options, CancellationToken cancellationToken) { var result = _organizationService.GetResult(request.ResultId); try { Series series = null; if (request.NewSeriesProviderIds.Count > 0) { series = await CreateNewSeries(request, null, options, cancellationToken).ConfigureAwait(false); } if (series == null) { // Existing Series series = (Series)_libraryManager.GetItemById(request.SeriesId); } // We manually set the media as Series result.Type = CurrentFileOrganizerType; await OrganizeEpisode( result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, null, options, request.RememberCorrection, result, cancellationToken).ConfigureAwait(false); _organizationService.SaveResult(result, CancellationToken.None); } catch (Exception ex) { result.Status = FileSortingStatus.Failure; result.StatusMessage = ex.Message; } return(result); }