예제 #1
0
        private Movie CreateNewMovie(MovieFileOrganizationRequest request, FileOrganizationResult result, MovieFileOrganizationOptions options)
        {
            // To avoid Movie duplicate by mistake (Missing SmartMatch and wrong selection in UI)
            var movie = GetMatchingMovie(request.NewMovieName, request.NewMovieYear, request.TargetFolder, result);

            if (movie == null)
            {
                // We're having a new movie here
                movie = new Movie
                {
                    Id              = Guid.NewGuid(),
                    Name            = request.NewMovieName,
                    ProductionYear  = request.NewMovieYear,
                    IsInMixedFolder = !options.MovieFolder,
                    ProviderIds     = request.NewMovieProviderIds.ToDictionary(x => x.Key, x => x.Value),
                };

                var newPath = GetMoviePath(result.OriginalPath, movie, options);

                if (string.IsNullOrEmpty(newPath))
                {
                    var msg = $"Unable to sort {result.OriginalPath} because target path could not be determined.";
                    throw new OrganizationException(msg);
                }

                movie.Path = Path.Combine(request.TargetFolder, newPath);
            }

            return(movie);
        }
예제 #2
0
        private Movie CreateNewMovie(MovieFileOrganizationRequest request, BaseItem targetFolder, FileOrganizationResult result, MovieFileOrganizationOptions options, CancellationToken cancellationToken)
        {
            // To avoid Movie duplicate by mistake (Missing SmartMatch and wrong selection in UI)
            var movie = GetMatchingMovie(request.NewMovieName, request.NewMovieYear, targetFolder, result, options);

            if (movie == null)
            {
                // We're having a new movie here
                movie = new Movie
                {
                    Name            = request.NewMovieName,
                    ProductionYear  = request.NewMovieYear,
                    IsInMixedFolder = !options.MovieFolder,
                    ProviderIds     = request.NewMovieProviderIds,
                };

                var newPath = GetMoviePath(result.OriginalPath, movie, options);

                if (string.IsNullOrEmpty(newPath))
                {
                    var msg = string.Format("Unable to sort {0} because target path could not be determined.", result.OriginalPath);
                    throw new OrganizationException(msg);
                }

                movie.Path = Path.Combine(request.TargetFolder, newPath);
            }

            return(movie);
        }
        public void PerformOrganization(MovieFileOrganizationRequest request)
        {
            var organizer = new MovieFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager,
                                                   _libraryMonitor, _providerManager);

            var options = GetAutoOrganizeOptions();
            var result  = organizer.OrganizeWithCorrection(request, options.MovieOptions, CancellationToken.None);
        }
예제 #4
0
        public FileOrganizationResult OrganizeWithCorrection(MovieFileOrganizationRequest request, MovieFileOrganizationOptions options, CancellationToken cancellationToken)
        {
            var result = _organizationService.GetResult(request.ResultId);

            try
            {
                Movie movie = null;

                if (request.NewMovieProviderIds.Count > 0)
                {
                    BaseItem targetFolder = null;

                    if (!string.IsNullOrEmpty(options.DefaultMovieLibraryPath))
                    {
                        targetFolder = _libraryManager.FindByPath(options.DefaultMovieLibraryPath, true);
                    }

                    // To avoid Series duplicate by mistake (Missing SmartMatch and wrong selection in UI)
                    movie = CreateNewMovie(request, targetFolder, result, options, cancellationToken);
                }

                if (movie == null)
                {
                    // Existing movie
                    movie = (Movie)_libraryManager.GetItemById(request.MovieId);
                    var newPath      = GetMoviePath(result.OriginalPath, movie, options);
                    var targetFolder = _libraryManager
                                       .GetVirtualFolders()
                                       .Where(i => string.Equals(i.CollectionType, CollectionType.Movies.ToString(), StringComparison.OrdinalIgnoreCase))
                                       .FirstOrDefault()
                                       .Locations
                                       .Where(i => movie.Path.Contains(i))
                                       .FirstOrDefault();
                    movie.Path = Path.Combine(targetFolder, newPath);
                }

                // We manually set the media as Movie
                result.Type = CurrentFileOrganizerType;

                OrganizeMovie(result.OriginalPath,
                              movie,
                              options,
                              null,
                              result,
                              cancellationToken);

                _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);
        }
        /// <inheritdoc/>
        public async Task PerformOrganization(MovieFileOrganizationRequest request)
        {
            var organizer = new MovieFileOrganizer(this, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager);

            var options = _config.GetAutoOrganizeOptions();
            var result  = await organizer.OrganizeWithCorrection(request, options.MovieOptions, CancellationToken.None).ConfigureAwait(false);

            if (result.Status != FileSortingStatus.Success)
            {
                throw new Exception(result.StatusMessage);
            }
        }
예제 #6
0
        public async Task <FileOrganizationResult> OrganizeWithCorrection(MovieFileOrganizationRequest request, MovieFileOrganizationOptions options, CancellationToken cancellationToken)
        {
            var result = _organizationService.GetResult(request.ResultId);

            try
            {
                Movie movie = null;

                if (request.NewMovieProviderIds.Count > 0)
                {
                    // To avoid Series duplicate by mistake (Missing SmartMatch and wrong selection in UI)
                    movie = CreateNewMovie(request, result, options, cancellationToken);
                }

                if (movie == null)
                {
                    // Existing movie
                    movie = (Movie)_libraryManager.GetItemById(request.MovieId);
                    var newPath      = GetMoviePath(result.OriginalPath, movie, options);
                    var targetFolder = _libraryManager
                                       .GetVirtualFolders()
                                       .Where(i => i.CollectionType == CollectionType.Movies)
                                       .FirstOrDefault()
                                       .Locations
                                       .Where(i => movie.Path.Contains(i))
                                       .FirstOrDefault();
                    movie.Path = Path.Combine(targetFolder, newPath);
                }

                // We manually set the media as Movie
                result.Type = CurrentFileOrganizerType;

                await OrganizeMovie(result.OriginalPath,
                                    movie,
                                    options,
                                    null,
                                    result,
                                    cancellationToken).ConfigureAwait(false);

                _organizationService.SaveResult(result, CancellationToken.None);
            }
            catch (Exception ex)
            {
                result.Status        = FileSortingStatus.Failure;
                result.StatusMessage = ex.Message;
            }

            return(result);
        }
        public async Task <FileOrganizationResult> OrganizeWithCorrection(MovieFileOrganizationRequest request, MovieFileOrganizationOptions options, CancellationToken cancellationToken)
        {
            var result = _organizationService.GetResult(request.ResultId);

            try
            {
                Movie movie = null;

                if (request.NewMovieProviderIds.Count > 0)
                {
                    // To avoid Series duplicate by mistake (Missing SmartMatch and wrong selection in UI)
                    movie = CreateNewMovie(request, result.OriginalPath, options, cancellationToken);
                }

                if (movie == null)
                {
                    // Existing movie
                    movie = (Movie)_libraryManager.GetItemById(new Guid(request.MovieId));
                }

                // We manually set the media as Movie
                result.Type = CurrentFileOrganizerType;

                await OrganizeMovie(result.OriginalPath,
                                    movie,
                                    options,
                                    null,
                                    true,
                                    result,
                                    cancellationToken).ConfigureAwait(false);

                await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                result.Status        = FileSortingStatus.Failure;
                result.StatusMessage = ex.Message;
            }

            return(result);
        }
예제 #8
0
        private async Task <Tuple <Movie, RemoteSearchResult> > AutoDetectMovie(string movieName, int?movieYear, FileOrganizationResult result, MovieFileOrganizationOptions options, CancellationToken cancellationToken)
        {
            if (options.AutoDetectMovie)
            {
                var parsedName = _libraryManager.ParseName(movieName.AsSpan());

                var yearInName      = parsedName.Year;
                var nameWithoutYear = parsedName.Name;

                if (string.IsNullOrWhiteSpace(nameWithoutYear))
                {
                    nameWithoutYear = movieName;
                }

                if (!yearInName.HasValue)
                {
                    yearInName = movieYear;
                }

                string   metadataLanguage    = null;
                string   metadataCountryCode = null;
                BaseItem targetFolder        = null;

                if (!string.IsNullOrEmpty(options.DefaultMovieLibraryPath))
                {
                    targetFolder = _libraryManager.FindByPath(options.DefaultMovieLibraryPath, true);
                }

                if (targetFolder != null)
                {
                    metadataLanguage    = targetFolder.GetPreferredMetadataLanguage();
                    metadataCountryCode = targetFolder.GetPreferredMetadataCountryCode();
                }

                var movieInfo = new MovieInfo
                {
                    Name = nameWithoutYear,
                    Year = yearInName,
                    MetadataCountryCode = metadataCountryCode,
                    MetadataLanguage    = metadataLanguage
                };

                var searchResultsTask = await _providerManager.GetRemoteSearchResults <Movie, MovieInfo>(new RemoteSearchQuery <MovieInfo>
                {
                    SearchInfo = movieInfo
                }, targetFolder, cancellationToken);

                var finalResult = searchResultsTask.FirstOrDefault();

                if (finalResult != null)
                {
                    // We are in the good position, we can create the item
                    var organizationRequest = new MovieFileOrganizationRequest
                    {
                        NewMovieName        = finalResult.Name,
                        NewMovieProviderIds = finalResult.ProviderIds,
                        NewMovieYear        = finalResult.ProductionYear,
                        TargetFolder        = options.DefaultMovieLibraryPath
                    };

                    var movie = CreateNewMovie(organizationRequest, targetFolder, result, options, cancellationToken);

                    return(new Tuple <Movie, RemoteSearchResult>(movie, finalResult));
                }
            }

            return(null);
        }
        private async Task <Tuple <Movie, RemoteSearchResult> > AutoDetectMovie(string movieName, int?movieYear, FileOrganizationResult result, MovieFileOrganizationOptions options, CancellationToken cancellationToken)
        {
            if (options.AutoDetectMovie)
            {
                var parsedName = _libraryManager.ParseName(movieName);

                var yearInName                 = parsedName.Year;
                var nameWithoutYear            = parsedName.Name;
                RemoteSearchResult finalResult = null;

                if (string.IsNullOrWhiteSpace(nameWithoutYear))
                {
                    nameWithoutYear = movieName;
                }

                if (!yearInName.HasValue)
                {
                    yearInName = movieYear;
                }

                #region Search One

                var movieInfo = new MovieInfo
                {
                    Name = nameWithoutYear,
                    Year = yearInName,
                };

                var searchResultsTask = await _providerManager.GetRemoteSearchResults <Movie, MovieInfo>(new RemoteSearchQuery <MovieInfo>
                {
                    SearchInfo = movieInfo
                }, cancellationToken);

                #endregion

                // Group movies by name and year (if 2 movie with the exact same name, the same year ...)
                var groupedResult = searchResultsTask.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(nameWithoutYear, yearInName, 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 MovieFileOrganizationRequest
                    {
                        NewMovieName        = finalResult.Name,
                        NewMovieProviderIds = finalResult.ProviderIds,
                        NewMovieYear        = finalResult.ProductionYear,
                        TargetFolder        = options.DefaultMovieLibraryPath
                    };

                    var movie = CreateNewMovie(organizationRequest, result.OriginalPath, options, cancellationToken);

                    return(new Tuple <Movie, RemoteSearchResult>(movie, finalResult));
                }
            }

            return(null);
        }