コード例 #1
0
        public void Execute(RefreshMovieCommand message)
        {
            _eventAggregator.PublishEvent(new MovieRefreshStartingEvent(message.Trigger == CommandTrigger.Manual));

            if (message.MovieId.HasValue)
            {
                var movie = _movieService.GetMovie(message.MovieId.Value);
                RefreshMovieInfo(movie);
            }
            else
            {
                var allMovie = _movieService.GetAllMovies().OrderBy(c => c.SortTitle).ToList();

                foreach (var movie in allMovie)
                {
                    if (message.Trigger == CommandTrigger.Manual || _checkIfMovieShouldBeRefreshed.ShouldRefresh(movie))
                    {
                        try
                        {
                            RefreshMovieInfo(movie);
                        }
                        catch (Exception e)
                        {
                            _logger.Error(e, "Couldn't refresh info for {0}".Inject(movie));
                        }
                    }

                    else
                    {
                        try
                        {
                            _logger.Info("Skipping refresh of movie: {0}", movie.Title);
                            _commandQueueManager.Push(new RenameMovieFolderCommand(new List <int> {
                                movie.Id
                            }));
                            _diskScanService.Scan(movie);
                        }
                        catch (Exception e)
                        {
                            _logger.Error(e, "Couldn't rescan movie {0}".Inject(movie));
                        }
                    }
                }
            }
        }
コード例 #2
0
ファイル: AlbumEditedService.cs プロジェクト: zobe123/Lidarr
        public void Handle(AlbumEditedEvent message)
        {
            if (message.Album.AlbumReleases.IsLoaded && message.OldAlbum.AlbumReleases.IsLoaded)
            {
                var new_monitored = new HashSet <int>(message.Album.AlbumReleases.Value.Where(x => x.Monitored).Select(x => x.Id));
                var old_monitored = new HashSet <int>(message.OldAlbum.AlbumReleases.Value.Where(x => x.Monitored).Select(x => x.Id));
                if (!new_monitored.SetEquals(old_monitored) ||
                    (message.OldAlbum.AnyReleaseOk == false && message.Album.AnyReleaseOk == true))
                {
                    // Unlink any old track files
                    var tracks = _trackService.GetTracksByAlbum(message.Album.Id);
                    tracks.ForEach(x => x.TrackFileId = 0);
                    _trackService.SetFileIds(tracks);

                    _commandQueueManager.Push(new RescanArtistCommand(message.Album.ArtistId, FilterFilesType.Matched));
                }
            }
        }
コード例 #3
0
        public void HandleAsync(DownloadFailedEvent message)
        {
            if (!_configService.AutoRedownloadFailed)
            {
                _logger.Debug("Auto redownloading failed episodes is disabled");
                return;
            }

            if (message.MovieId != 0)
            {
                _logger.Debug("Failed download contains a movie, searching again.");
                _commandQueueManager.Push(new MoviesSearchCommand {
                    MovieIds = new List <int> {
                        message.MovieId
                    }
                });
            }
        }
コード例 #4
0
        private void HandleScanEvents(Author author)
        {
            if (author.AddOptions != null)
            {
                _logger.Info("[{0}] was recently added, performing post-add actions", author.Name);
                _bookMonitoredService.SetBookMonitoredStatus(author, author.AddOptions);

                if (author.AddOptions.SearchForMissingBooks)
                {
                    _commandQueueManager.Push(new MissingBookSearchCommand(author.Id));
                }

                author.AddOptions = null;
                _authorService.RemoveAddOptions(author);
            }

            _bookAddedService.SearchForRecentlyAdded(author.Id);
        }
コード例 #5
0
        private void HandleScanEvents(Artist artist)
        {
            if (artist.AddOptions != null)
            {
                _logger.Info("[{0}] was recently added, performing post-add actions", artist.Name);
                _albumMonitoredService.SetAlbumMonitoredStatus(artist, artist.AddOptions);

                if (artist.AddOptions.SearchForMissingAlbums)
                {
                    _commandQueueManager.Push(new MissingAlbumSearchCommand(artist.Id));
                }

                artist.AddOptions = null;
                _artistService.RemoveAddOptions(artist);
            }

            _albumAddedService.SearchForRecentlyAdded(artist.Id);
        }
コード例 #6
0
        private void Rescan(List <Artist> artists, bool isNew, CommandTrigger trigger, bool infoUpdated)
        {
            var rescanAfterRefresh = _configService.RescanAfterRefresh;
            var shouldRescan       = true;
            var filter             = FilterFilesType.Matched;
            var folders            = _rootFolderService.All().Select(x => x.Path).ToList();

            if (isNew)
            {
                _logger.Trace("Forcing rescan. Reason: New artist added");
                shouldRescan = true;

                // only rescan artist folders - otherwise it can be super slow for
                // badly organized / partly matched libraries
                folders = artists.Select(x => x.Path).ToList();
            }
            else if (rescanAfterRefresh == RescanAfterRefreshType.Never)
            {
                _logger.Trace("Skipping rescan. Reason: never rescan after refresh");
                shouldRescan = false;
            }
            else if (rescanAfterRefresh == RescanAfterRefreshType.AfterManual && trigger != CommandTrigger.Manual)
            {
                _logger.Trace("Skipping rescan. Reason: not after automatic refreshes");
                shouldRescan = false;
            }
            else if (!infoUpdated && trigger != CommandTrigger.Manual)
            {
                _logger.Trace("Skipping rescan. Reason: no metadata updated after automatic refresh");
                shouldRescan = false;
            }
            else if (!infoUpdated)
            {
                _logger.Trace("No metadata updated, only scanning new files");
                filter = FilterFilesType.Known;
            }

            if (shouldRescan)
            {
                // some metadata has updated so rescan unmatched
                // (but don't add new artists to reduce repeated searches against api)
                _commandQueueManager.Push(new RescanFoldersCommand(folders, filter, false, artists.Select(x => x.Id).ToList()));
            }
        }
コード例 #7
0
        private int StartCommand(CommandResource commandResource)
        {
            var commandType = _serviceFactory.GetImplementations(typeof(Command))
                              .SingleOrDefault(c => c.Name.Replace("Command", "").Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase));

            if (commandType == null)
            {
                _logger.Error("Found no matching command for {0}", commandResource.Name);
                return(0);
            }

            dynamic command = Request.Body.FromJson(commandType);

            command.Trigger = CommandTrigger.Manual;

            var trackedCommand = _commandQueueManager.Push(command, CommandPriority.Normal, CommandTrigger.Manual);

            return(trackedCommand.Id);
        }
コード例 #8
0
        public RootFolder Add(RootFolder rootFolder)
        {
            VerifyRootFolder(rootFolder);

            if (All().Exists(r => r.Path.PathEquals(rootFolder.Path)))
            {
                throw new InvalidOperationException("Root folder already exists.");
            }

            _rootFolderRepository.Insert(rootFolder);

            _commandQueueManager.Push(new RescanFoldersCommand(new List <string> {
                rootFolder.Path
            }, FilterFilesType.None, true, null));

            GetDetails(rootFolder);

            return(rootFolder);
        }
コード例 #9
0
ファイル: SeriesScannedHandler.cs プロジェクト: Gadarr/Gadarr
        private void HandleScanEvents(Series series)
        {
            if (series.AddOptions == null)
            {
                _episodeAddedService.SearchForRecentlyAdded(series.Id);
                return;
            }

            _logger.Info("[{0}] was recently added, performing post-add actions", series.Title);
            _episodeMonitoredService.SetEpisodeMonitoredStatus(series, series.AddOptions);

            if (series.AddOptions.SearchForMissingEpisodes)
            {
                _commandQueueManager.Push(new MissingEpisodeSearchCommand(series.Id));
            }

            series.AddOptions = null;
            _seriesService.RemoveAddOptions(series);
        }
コード例 #10
0
ファイル: CommandModule.cs プロジェクト: edward-scroop/Radarr
        private int StartCommand(CommandResource commandResource)
        {
            var commandType =
                _serviceFactory.GetImplementations(typeof(Command))
                .Single(c => c.Name.Replace("Command", "")
                        .Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase));

            dynamic command = Request.Body.FromJson(commandType);

            command.Trigger             = CommandTrigger.Manual;
            command.SuppressMessages    = !command.SendUpdatesToClient;
            command.SendUpdatesToClient = true;

            command.ClientUserAgent = Request.Headers.UserAgent;

            var trackedCommand = _commandQueueManager.Push(command, CommandPriority.Normal, CommandTrigger.Manual);

            return(trackedCommand.Id);
        }
コード例 #11
0
        private void HandleScanEvents(Movie movie)
        {
            if (movie.AddOptions == null)
            {
                return;
            }

            _logger.Info("[{0}] was recently added, performing post-add actions", movie.Title);

            if (movie.AddOptions.SearchForMovie)
            {
                _commandQueueManager.Push(new MoviesSearchCommand {
                    MovieIds = new List <int> {
                        movie.Id
                    }
                });
            }

            movie.AddOptions = null;
            _movieService.RemoveAddOptions(movie);
        }
コード例 #12
0
ファイル: CommandController.cs プロジェクト: sirimore/Readarr
        public ActionResult <CommandResource> StartCommand(CommandResource commandResource)
        {
            var commandType =
                _knownTypes.GetImplementations(typeof(Command))
                .Single(c => c.Name.Replace("Command", "")
                        .Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase));

            Request.Body.Seek(0, SeekOrigin.Begin);
            using var reader = new StreamReader(Request.Body);
            var body = reader.ReadToEnd();

            dynamic command = STJson.Deserialize(body, commandType);

            command.Trigger             = CommandTrigger.Manual;
            command.SuppressMessages    = !command.SendUpdatesToClient;
            command.SendUpdatesToClient = true;

            var trackedCommand = _commandQueueManager.Push(command, CommandPriority.Normal, CommandTrigger.Manual);

            return(Created(trackedCommand.Id));
        }
コード例 #13
0
ファイル: Scheduler.cs プロジェクト: bakerboy448/Prowlarr
        private void ExecuteCommands()
        {
            try
            {
                Timer.Enabled = false;

                var tasks = _taskManager.GetPending().ToList();

                _logger.Trace("Pending Tasks: {0}", tasks.Count);

                foreach (var task in tasks)
                {
                    _commandQueueManager.Push(task.TypeName, task.LastExecution, task.LastStartTime, task.Priority, CommandTrigger.Scheduled);
                }
            }
            finally
            {
                if (!_cancellationTokenSource.IsCancellationRequested)
                {
                    Timer.Enabled = true;
                }
            }
        }
コード例 #14
0
ファイル: ArtistModule.cs プロジェクト: debbielobo1/Lidarr
        private void UpdateArtist(ArtistResource artistResource)
        {
            var moveFiles = Request.GetBooleanQueryParameter("moveFiles");
            var artist    = _artistService.GetArtist(artistResource.Id);

            var sourcePath      = artist.Path;
            var destinationPath = artistResource.Path;

            _commandQueueManager.Push(new MoveArtistCommand
            {
                ArtistId        = artist.Id,
                SourcePath      = sourcePath,
                DestinationPath = destinationPath,
                MoveFiles       = moveFiles,
                Trigger         = CommandTrigger.Manual
            });

            var model = artistResource.ToModel(artist);

            _artistService.UpdateArtist(model);

            BroadcastResourceChange(ModelAction.Updated, artistResource);
        }
コード例 #15
0
        public void Execute(RefreshAlbumCommand message)
        {
            if (message.AlbumId.HasValue)
            {
                var album   = _albumService.GetAlbum(message.AlbumId.Value);
                var artist  = _artistService.GetArtistByMetadataId(album.ArtistMetadataId);
                var updated = RefreshAlbumInfo(album, null, false);
                if (updated)
                {
                    _eventAggregator.PublishEvent(new ArtistUpdatedEvent(artist));
                    _eventAggregator.PublishEvent(new AlbumUpdatedEvent(album));
                }

                if (message.IsNewAlbum)
                {
                    // Just scan the artist path - triggering a full rescan is too painful
                    var folders = new List <string> {
                        artist.Path
                    };
                    _commandQueueManager.Push(new RescanFoldersCommand(folders, FilterFilesType.Matched, false, null));
                }
            }
        }
コード例 #16
0
 public void Handle(SeriesAddedEvent message)
 {
     _commandQueueManager.Push(new RefreshSeriesCommand(message.Series.Id));
 }
コード例 #17
0
 private void QueueRefresh()
 {
     _manageCommandQueue.Push(new RefreshMonitoredDownloadsCommand(), CommandPriority.High);
 }
コード例 #18
0
ファイル: ArtistEditorModule.cs プロジェクト: tjman92/Lidarr
        private object SaveAll()
        {
            var resource       = Request.Body.FromJson <ArtistEditorResource>();
            var artistToUpdate = _artistService.GetArtists(resource.ArtistIds);
            var artistToMove   = new List <BulkMoveArtist>();

            foreach (var artist in artistToUpdate)
            {
                if (resource.Monitored.HasValue)
                {
                    artist.Monitored = resource.Monitored.Value;
                }

                if (resource.QualityProfileId.HasValue)
                {
                    artist.QualityProfileId = resource.QualityProfileId.Value;
                }

                if (resource.MetadataProfileId.HasValue)
                {
                    artist.MetadataProfileId = resource.MetadataProfileId.Value;
                }

                if (resource.AlbumFolder.HasValue)
                {
                    artist.AlbumFolder = resource.AlbumFolder.Value;
                }

                if (resource.RootFolderPath.IsNotNullOrWhiteSpace())
                {
                    artist.RootFolderPath = resource.RootFolderPath;
                    artistToMove.Add(new BulkMoveArtist
                    {
                        ArtistId   = artist.Id,
                        SourcePath = artist.Path
                    });
                }

                if (resource.Tags != null)
                {
                    var newTags   = resource.Tags;
                    var applyTags = resource.ApplyTags;

                    switch (applyTags)
                    {
                    case ApplyTags.Add:
                        newTags.ForEach(t => artist.Tags.Add(t));
                        break;

                    case ApplyTags.Remove:
                        newTags.ForEach(t => artist.Tags.Remove(t));
                        break;

                    case ApplyTags.Replace:
                        artist.Tags = new HashSet <int>(newTags);
                        break;
                    }
                }
            }

            if (resource.MoveFiles && artistToMove.Any())
            {
                _commandQueueManager.Push(new BulkMoveArtistCommand
                {
                    DestinationRootFolder = resource.RootFolderPath,
                    Artist = artistToMove
                });
            }

            return(ResponseWithCode(_artistService.UpdateArtists(artistToUpdate, !resource.MoveFiles)
                                    .ToResource()
                                    , HttpStatusCode.Accepted));
        }
コード例 #19
0
        public List <ImportResult> Import(List <ImportDecision <LocalBook> > decisions, bool replaceExisting, DownloadClientItem downloadClientItem = null, ImportMode importMode = ImportMode.Auto)
        {
            var importResults         = new List <ImportResult>();
            var allImportedTrackFiles = new List <BookFile>();
            var allOldTrackFiles      = new List <BookFile>();
            var addedAuthors          = new List <Author>();

            var bookDecisions = decisions.Where(e => e.Item.Book != null && e.Approved)
                                .GroupBy(e => e.Item.Book.ForeignBookId).ToList();

            var iDecision = 1;

            foreach (var albumDecision in bookDecisions)
            {
                _logger.ProgressInfo($"Importing book {iDecision++}/{bookDecisions.Count} {albumDecision.First().Item.Book}");

                var decisionList = albumDecision.ToList();

                var author = EnsureAuthorAdded(decisionList, addedAuthors);

                if (author == null)
                {
                    // failed to add the author, carry on with next book
                    continue;
                }

                var book = EnsureBookAdded(decisionList);

                if (book == null)
                {
                    // failed to add the book, carry on with next one
                    continue;
                }

                if (replaceExisting)
                {
                    RemoveExistingTrackFiles(author, book);
                }

                // set the correct release to be monitored before importing the new files
                var newRelease = albumDecision.First().Item.Edition;
                _logger.Debug("Updating release to {0}", newRelease);
                book.Editions = _editionService.SetMonitored(newRelease);

                // Publish book edited event.
                // Deliberatly don't put in the old book since we don't want to trigger an ArtistScan.
                _eventAggregator.PublishEvent(new BookEditedEvent(book, book));
            }

            var qualifiedImports = decisions.Where(c => c.Approved)
                                   .GroupBy(c => c.Item.Author.Id, (i, s) => s
                                            .OrderByDescending(c => c.Item.Quality, new QualityModelComparer(s.First().Item.Author.QualityProfile))
                                            .ThenByDescending(c => c.Item.Size))
                                   .SelectMany(c => c)
                                   .ToList();

            _logger.ProgressInfo($"Importing {qualifiedImports.Count} files");
            _logger.Debug($"Importing {qualifiedImports.Count} files. replaceExisting: {replaceExisting}");

            var filesToAdd          = new List <BookFile>(qualifiedImports.Count);
            var trackImportedEvents = new List <TrackImportedEvent>(qualifiedImports.Count);

            foreach (var importDecision in qualifiedImports.OrderByDescending(e => e.Item.Size))
            {
                var localTrack = importDecision.Item;
                var oldFiles   = new List <BookFile>();

                try
                {
                    //check if already imported
                    if (importResults.Select(r => r.ImportDecision.Item.Book.Id).Contains(localTrack.Book.Id))
                    {
                        if (!(localTrack.FileTrackInfo.TrackNumbers != null && localTrack.FileTrackInfo.TrackNumbers.Any()))
                        {
                            importResults.Add(new ImportResult(importDecision, "Book has already been imported"));
                            continue;
                        }
                        else
                        {
                            var matchingImportResults = importResults.Where(r => r.ImportDecision.Item.Book.Id == localTrack.Book.Id);
                            if (matchingImportResults.Select(r => r.ImportDecision.Item.FileTrackInfo.TrackNumbers).Contains(localTrack.FileTrackInfo.TrackNumbers))
                            {
                                importResults.Add(new ImportResult(importDecision, "Audiobook track has already been imported"));
                                continue;
                            }
                        }
                    }

                    localTrack.Book.Author = localTrack.Author;

                    var bookFile = new BookFile
                    {
                        Path         = localTrack.Path.CleanFilePath(),
                        Size         = localTrack.Size,
                        Modified     = localTrack.Modified,
                        DateAdded    = DateTime.UtcNow,
                        ReleaseGroup = localTrack.ReleaseGroup,
                        Quality      = localTrack.Quality,
                        MediaInfo    = localTrack.FileTrackInfo.MediaInfo,
                        EditionId    = localTrack.Edition.Id,
                        Author       = localTrack.Author,
                        Edition      = localTrack.Edition
                    };

                    bool copyOnly;
                    switch (importMode)
                    {
                    default:
                    case ImportMode.Auto:
                        copyOnly = downloadClientItem != null && !downloadClientItem.CanMoveFiles;
                        break;

                    case ImportMode.Move:
                        copyOnly = false;
                        break;

                    case ImportMode.Copy:
                        copyOnly = true;
                        break;
                    }

                    if (!localTrack.ExistingFile)
                    {
                        bookFile.SceneName = GetSceneReleaseName(downloadClientItem);

                        var moveResult = _bookFileUpgrader.UpgradeBookFile(bookFile, localTrack, copyOnly);
                        oldFiles = moveResult.OldFiles;
                    }
                    else
                    {
                        // Delete existing files from the DB mapped to this path
                        var previousFile = _mediaFileService.GetFileWithPath(bookFile.Path);

                        if (previousFile != null)
                        {
                            _mediaFileService.Delete(previousFile, DeleteMediaFileReason.ManualOverride);
                        }

                        var rootFolder = _rootFolderService.GetBestRootFolder(localTrack.Path);
                        if (rootFolder.IsCalibreLibrary)
                        {
                            bookFile.CalibreId = bookFile.Path.ParseCalibreId();
                        }

                        _audioTagService.WriteTags(bookFile, false);
                    }

                    filesToAdd.Add(bookFile);
                    importResults.Add(new ImportResult(importDecision));

                    if (!localTrack.ExistingFile)
                    {
                        _extraService.ImportTrack(localTrack, bookFile, copyOnly);
                    }

                    allImportedTrackFiles.Add(bookFile);
                    allOldTrackFiles.AddRange(oldFiles);

                    // create all the import events here, but we can't publish until the trackfiles have been
                    // inserted and ids created
                    trackImportedEvents.Add(new TrackImportedEvent(localTrack, bookFile, oldFiles, !localTrack.ExistingFile, downloadClientItem));
                }
                catch (RootFolderNotFoundException e)
                {
                    _logger.Warn(e, "Couldn't import book " + localTrack);
                    _eventAggregator.PublishEvent(new TrackImportFailedEvent(e, localTrack, !localTrack.ExistingFile, downloadClientItem));

                    importResults.Add(new ImportResult(importDecision, "Failed to import book, Root folder missing."));
                }
                catch (DestinationAlreadyExistsException e)
                {
                    _logger.Warn(e, "Couldn't import book " + localTrack);
                    importResults.Add(new ImportResult(importDecision, "Failed to import book, Destination already exists."));
                }
                catch (UnauthorizedAccessException e)
                {
                    _logger.Warn(e, "Couldn't import book " + localTrack);
                    _eventAggregator.PublishEvent(new TrackImportFailedEvent(e, localTrack, !localTrack.ExistingFile, downloadClientItem));

                    importResults.Add(new ImportResult(importDecision, "Failed to import book, Permissions error"));
                }
                catch (Exception)
                {
                    throw;
                }
            }

            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();
            _mediaFileService.AddMany(filesToAdd);
            _logger.Debug($"Inserted new trackfiles in {watch.ElapsedMilliseconds}ms");

            // now that trackfiles have been inserted and ids generated, publish the import events
            foreach (var trackImportedEvent in trackImportedEvents)
            {
                _eventAggregator.PublishEvent(trackImportedEvent);
            }

            var albumImports = importResults.Where(e => e.ImportDecision.Item.Book != null)
                               .GroupBy(e => e.ImportDecision.Item.Book.Id).ToList();

            foreach (var albumImport in albumImports)
            {
                var book   = albumImport.First().ImportDecision.Item.Book;
                var author = albumImport.First().ImportDecision.Item.Author;

                if (albumImport.Where(e => e.Errors.Count == 0).ToList().Count > 0 && author != null && book != null)
                {
                    _eventAggregator.PublishEvent(new BookImportedEvent(
                                                      author,
                                                      book,
                                                      allImportedTrackFiles.Where(s => s.EditionId == book.Id).ToList(),
                                                      allOldTrackFiles.Where(s => s.EditionId == book.Id).ToList(),
                                                      replaceExisting,
                                                      downloadClientItem));
                }
            }

            //Adding all the rejected decisions
            importResults.AddRange(decisions.Where(c => !c.Approved)
                                   .Select(d => new ImportResult(d, d.Rejections.Select(r => r.Reason).ToArray())));

            // Refresh any artists we added
            if (addedAuthors.Any())
            {
                _commandQueueManager.Push(new BulkRefreshAuthorCommand(addedAuthors.Select(x => x.Id).ToList(), true));
            }

            return(importResults);
        }
コード例 #20
0
 private void QueueRefresh()
 {
     _manageCommandQueue.Push(new RefreshMonitoredDownloadsCommand());
 }
コード例 #21
0
 public void Handle(ArtistAddedEvent message)
 {
     _commandQueueManager.Push(new RefreshArtistCommand(message.Artist.Id, true));
 }
コード例 #22
0
        public List <ImportResult> Import(List <ImportDecision <LocalTrack> > decisions, bool replaceExisting, DownloadClientItem downloadClientItem = null, ImportMode importMode = ImportMode.Auto)
        {
            var importResults         = new List <ImportResult>();
            var allImportedTrackFiles = new List <TrackFile>();
            var allOldTrackFiles      = new List <TrackFile>();
            var addedArtists          = new List <Artist>();

            var albumDecisions = decisions.Where(e => e.Item.Album != null && e.Approved)
                                 .GroupBy(e => e.Item.Album.ForeignAlbumId).ToList();

            int iDecision = 1;

            foreach (var albumDecision in albumDecisions)
            {
                _logger.ProgressInfo($"Importing album {iDecision++}/{albumDecisions.Count}");

                var decisionList = albumDecision.ToList();

                var artist = EnsureArtistAdded(decisionList, addedArtists);

                if (artist == null)
                {
                    // failed to add the artist, carry on with next album
                    continue;
                }

                var album = EnsureAlbumAdded(decisionList);

                if (album == null)
                {
                    // failed to add the album, carry on with next one
                    continue;
                }

                if (replaceExisting)
                {
                    RemoveExistingTrackFiles(artist, album);
                }

                // set the correct release to be monitored before importing the new files
                var newRelease = albumDecision.First().Item.Release;
                _logger.Debug("Updating release to {0} [{1} tracks]", newRelease, newRelease.TrackCount);
                album.AlbumReleases = _releaseService.SetMonitored(newRelease);

                // Publish album edited event.
                // Deliberatly don't put in the old album since we don't want to trigger an ArtistScan.
                _eventAggregator.PublishEvent(new AlbumEditedEvent(album, album));
            }

            var qualifiedImports = decisions.Where(c => c.Approved)
                                   .GroupBy(c => c.Item.Artist.Id, (i, s) => s
                                            .OrderByDescending(c => c.Item.Quality, new QualityModelComparer(s.First().Item.Artist.QualityProfile))
                                            .ThenByDescending(c => c.Item.Size))
                                   .SelectMany(c => c)
                                   .ToList();

            _logger.ProgressInfo($"Importing {qualifiedImports.Count} tracks");
            _logger.Debug($"Importing {qualifiedImports.Count} files. replaceExisting: {replaceExisting}");

            var filesToAdd          = new List <TrackFile>(qualifiedImports.Count);
            var albumReleasesDict   = new Dictionary <int, List <AlbumRelease> >(albumDecisions.Count);
            var trackImportedEvents = new List <TrackImportedEvent>(qualifiedImports.Count);

            foreach (var importDecision in qualifiedImports.OrderBy(e => e.Item.Tracks.Select(track => track.AbsoluteTrackNumber).MinOrDefault())
                     .ThenByDescending(e => e.Item.Size))
            {
                var localTrack = importDecision.Item;
                var oldFiles   = new List <TrackFile>();

                try
                {
                    //check if already imported
                    if (importResults.SelectMany(r => r.ImportDecision.Item.Tracks)
                        .Select(e => e.Id)
                        .Intersect(localTrack.Tracks.Select(e => e.Id))
                        .Any())
                    {
                        importResults.Add(new ImportResult(importDecision, "Track has already been imported"));
                        continue;
                    }

                    // cache album releases and set artist to speed up firing the TrackImported events
                    // (otherwise they'll be retrieved from the DB for each track)
                    if (!albumReleasesDict.ContainsKey(localTrack.Album.Id))
                    {
                        albumReleasesDict.Add(localTrack.Album.Id, localTrack.Album.AlbumReleases.Value);
                    }

                    if (!localTrack.Album.AlbumReleases.IsLoaded)
                    {
                        localTrack.Album.AlbumReleases = albumReleasesDict[localTrack.Album.Id];
                    }

                    localTrack.Album.Artist = localTrack.Artist;

                    foreach (var track in localTrack.Tracks)
                    {
                        track.Artist       = localTrack.Artist;
                        track.AlbumRelease = localTrack.Release;
                        track.Album        = localTrack.Album;
                    }

                    var trackFile = new TrackFile
                    {
                        Path         = localTrack.Path.CleanFilePath(),
                        Size         = localTrack.Size,
                        Modified     = localTrack.Modified,
                        DateAdded    = DateTime.UtcNow,
                        ReleaseGroup = localTrack.ReleaseGroup,
                        Quality      = localTrack.Quality,
                        MediaInfo    = localTrack.FileTrackInfo.MediaInfo,
                        AlbumId      = localTrack.Album.Id,
                        Artist       = localTrack.Artist,
                        Album        = localTrack.Album,
                        Tracks       = localTrack.Tracks
                    };

                    bool copyOnly;
                    switch (importMode)
                    {
                    default:
                    case ImportMode.Auto:
                        copyOnly = downloadClientItem != null && !downloadClientItem.CanMoveFiles;
                        break;

                    case ImportMode.Move:
                        copyOnly = false;
                        break;

                    case ImportMode.Copy:
                        copyOnly = true;
                        break;
                    }

                    if (!localTrack.ExistingFile)
                    {
                        trackFile.SceneName = GetSceneReleaseName(downloadClientItem);

                        var moveResult = _trackFileUpgrader.UpgradeTrackFile(trackFile, localTrack, copyOnly);
                        oldFiles = moveResult.OldFiles;
                    }
                    else
                    {
                        // Delete existing files from the DB mapped to this path
                        var previousFile = _mediaFileService.GetFileWithPath(trackFile.Path);

                        if (previousFile != null)
                        {
                            _mediaFileService.Delete(previousFile, DeleteMediaFileReason.ManualOverride);
                        }

                        _audioTagService.WriteTags(trackFile, false);
                    }

                    filesToAdd.Add(trackFile);
                    importResults.Add(new ImportResult(importDecision));

                    if (!localTrack.ExistingFile)
                    {
                        _extraService.ImportTrack(localTrack, trackFile, copyOnly);
                    }

                    allImportedTrackFiles.Add(trackFile);
                    allOldTrackFiles.AddRange(oldFiles);

                    // create all the import events here, but we can't publish until the trackfiles have been
                    // inserted and ids created
                    trackImportedEvents.Add(new TrackImportedEvent(localTrack, trackFile, oldFiles, !localTrack.ExistingFile, downloadClientItem));
                }
                catch (RootFolderNotFoundException e)
                {
                    _logger.Warn(e, "Couldn't import track " + localTrack);
                    _eventAggregator.PublishEvent(new TrackImportFailedEvent(e, localTrack, !localTrack.ExistingFile, downloadClientItem));

                    importResults.Add(new ImportResult(importDecision, "Failed to import track, Root folder missing."));
                }
                catch (DestinationAlreadyExistsException e)
                {
                    _logger.Warn(e, "Couldn't import track " + localTrack);
                    importResults.Add(new ImportResult(importDecision, "Failed to import track, Destination already exists."));
                }
                catch (UnauthorizedAccessException e)
                {
                    _logger.Warn(e, "Couldn't import track " + localTrack);
                    _eventAggregator.PublishEvent(new TrackImportFailedEvent(e, localTrack, !localTrack.ExistingFile, downloadClientItem));

                    importResults.Add(new ImportResult(importDecision, "Failed to import track, Permissions error"));
                }
                catch (Exception e)
                {
                    _logger.Warn(e, "Couldn't import track " + localTrack);
                    importResults.Add(new ImportResult(importDecision, "Failed to import track"));
                }
            }

            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();
            _mediaFileService.AddMany(filesToAdd);
            _logger.Debug($"Inserted new trackfiles in {watch.ElapsedMilliseconds}ms");
            filesToAdd.ForEach(f => f.Tracks.Value.ForEach(t => t.TrackFileId = f.Id));
            _trackService.SetFileIds(filesToAdd.SelectMany(x => x.Tracks.Value).ToList());
            _logger.Debug($"TrackFileIds updated, total {watch.ElapsedMilliseconds}ms");

            // now that trackfiles have been inserted and ids generated, publish the import events
            foreach (var trackImportedEvent in trackImportedEvents)
            {
                _eventAggregator.PublishEvent(trackImportedEvent);
            }

            var albumImports = importResults.Where(e => e.ImportDecision.Item.Album != null)
                               .GroupBy(e => e.ImportDecision.Item.Album.Id).ToList();

            foreach (var albumImport in albumImports)
            {
                var release = albumImport.First().ImportDecision.Item.Release;
                var album   = albumImport.First().ImportDecision.Item.Album;
                var artist  = albumImport.First().ImportDecision.Item.Artist;

                if (albumImport.Where(e => e.Errors.Count == 0).ToList().Count > 0 && artist != null && album != null)
                {
                    _eventAggregator.PublishEvent(new AlbumImportedEvent(
                                                      artist,
                                                      album,
                                                      release,
                                                      allImportedTrackFiles.Where(s => s.AlbumId == album.Id).ToList(),
                                                      allOldTrackFiles.Where(s => s.AlbumId == album.Id).ToList(),
                                                      replaceExisting,
                                                      downloadClientItem));
                }
            }

            //Adding all the rejected decisions
            importResults.AddRange(decisions.Where(c => !c.Approved)
                                   .Select(d => new ImportResult(d, d.Rejections.Select(r => r.Reason).ToArray())));

            // Refresh any artists we added
            if (addedArtists.Any())
            {
                _commandQueueManager.Push(new BulkRefreshArtistCommand(addedArtists.Select(x => x.Id).ToList(), true));
            }

            return(importResults);
        }
コード例 #23
0
 public void Handle(ProviderUpdatedEvent <IImportList> message)
 {
     _commandQueueManager.Push(new ImportListSyncCommand(message.Definition.Id));
 }
コード例 #24
0
        private object SaveAll()
        {
            var resource       = Request.Body.FromJson <MovieEditorResource>();
            var moviesToUpdate = _movieService.GetMovies(resource.MovieIds);
            var moviesToMove   = new List <BulkMoveMovie>();

            foreach (var movie in moviesToUpdate)
            {
                if (resource.Monitored.HasValue)
                {
                    movie.Monitored = resource.Monitored.Value;
                }

                if (resource.QualityProfileId.HasValue)
                {
                    movie.ProfileId = resource.QualityProfileId.Value;
                }

                if (resource.MinimumAvailability.HasValue)
                {
                    movie.MinimumAvailability = resource.MinimumAvailability.Value;
                }

                if (resource.RootFolderPath.IsNotNullOrWhiteSpace())
                {
                    movie.RootFolderPath = resource.RootFolderPath;
                    moviesToMove.Add(new BulkMoveMovie
                    {
                        MovieId    = movie.Id,
                        SourcePath = movie.Path
                    });
                }

                if (resource.Tags != null)
                {
                    var newTags   = resource.Tags;
                    var applyTags = resource.ApplyTags;

                    switch (applyTags)
                    {
                    case ApplyTags.Add:
                        newTags.ForEach(t => movie.Tags.Add(t));
                        break;

                    case ApplyTags.Remove:
                        newTags.ForEach(t => movie.Tags.Remove(t));
                        break;

                    case ApplyTags.Replace:
                        movie.Tags = new HashSet <int>(newTags);
                        break;
                    }
                }
            }

            if (resource.MoveFiles && moviesToMove.Any())
            {
                _commandQueueManager.Push(new BulkMoveMovieCommand
                {
                    DestinationRootFolder = resource.RootFolderPath,
                    Movies = moviesToMove
                });
            }

            return(ResponseWithCode(_movieService.UpdateMovie(moviesToUpdate, !resource.MoveFiles)
                                    .ToResource(0, _upgradableSpecification),
                                    HttpStatusCode.Accepted));
        }
コード例 #25
0
 public void Handle(MovieAddedEvent message)
 {
     _commandQueueManager.Push(new RefreshMovieCommand(new List <int> {
         message.Movie.Id
     }, true));
 }
コード例 #26
0
        public IActionResult SaveAll([FromBody] AuthorEditorResource resource)
        {
            var authorsToUpdate = _authorService.GetAuthors(resource.AuthorIds);
            var authorsToMove   = new List <BulkMoveAuthor>();

            foreach (var author in authorsToUpdate)
            {
                if (resource.Monitored.HasValue)
                {
                    author.Monitored = resource.Monitored.Value;
                }

                if (resource.QualityProfileId.HasValue)
                {
                    author.QualityProfileId = resource.QualityProfileId.Value;
                }

                if (resource.MetadataProfileId.HasValue)
                {
                    author.MetadataProfileId = resource.MetadataProfileId.Value;
                }

                if (resource.RootFolderPath.IsNotNullOrWhiteSpace())
                {
                    author.RootFolderPath = resource.RootFolderPath;
                    authorsToMove.Add(new BulkMoveAuthor
                    {
                        AuthorId   = author.Id,
                        SourcePath = author.Path
                    });
                }

                if (resource.Tags != null)
                {
                    var newTags   = resource.Tags;
                    var applyTags = resource.ApplyTags;

                    switch (applyTags)
                    {
                    case ApplyTags.Add:
                        newTags.ForEach(t => author.Tags.Add(t));
                        break;

                    case ApplyTags.Remove:
                        newTags.ForEach(t => author.Tags.Remove(t));
                        break;

                    case ApplyTags.Replace:
                        author.Tags = new HashSet <int>(newTags);
                        break;
                    }
                }
            }

            if (resource.MoveFiles && authorsToMove.Any())
            {
                _commandQueueManager.Push(new BulkMoveAuthorCommand
                {
                    DestinationRootFolder = resource.RootFolderPath,
                    Author = authorsToMove
                });
            }

            return(Accepted(_authorService.UpdateAuthors(authorsToUpdate, !resource.MoveFiles).ToResource()));
        }
コード例 #27
0
ファイル: MovieAddedHandler.cs プロジェクト: wmcmilli/Bonarr
 public void Handle(MovieAddedEvent message)
 {
     _commandQueueManager.Push(new RefreshMovieCommand(message.Movie.Id));
 }
コード例 #28
0
 private void QueueRefresh()
 {
     _manageCommandQueue.Push(new CheckForFinishedDownloadCommand());
 }
コード例 #29
0
        private object SaveAll()
        {
            var resource       = Request.Body.FromJson <SeriesEditorResource>();
            var seriesToUpdate = _seriesService.GetSeries(resource.SeriesIds);
            var seriesToMove   = new List <BulkMoveSeries>();

            foreach (var series in seriesToUpdate)
            {
                if (resource.Monitored.HasValue)
                {
                    series.Monitored = resource.Monitored.Value;
                }

                if (resource.QualityProfileId.HasValue)
                {
                    series.QualityProfileId = resource.QualityProfileId.Value;
                }

                if (resource.LanguageProfileId.HasValue)
                {
                    series.LanguageProfileId = resource.LanguageProfileId.Value;
                }

                if (resource.SeriesType.HasValue)
                {
                    series.SeriesType = resource.SeriesType.Value;
                }

                if (resource.SeasonFolder.HasValue)
                {
                    series.SeasonFolder = resource.SeasonFolder.Value;
                }

                if (resource.RootFolderPath.IsNotNullOrWhiteSpace())
                {
                    series.RootFolderPath = resource.RootFolderPath;
                    seriesToMove.Add(new BulkMoveSeries
                    {
                        SeriesId   = series.Id,
                        SourcePath = series.Path
                    });
                }

                if (resource.Tags != null)
                {
                    var newTags   = resource.Tags;
                    var applyTags = resource.ApplyTags;

                    switch (applyTags)
                    {
                    case ApplyTags.Add:
                        newTags.ForEach(t => series.Tags.Add(t));
                        break;

                    case ApplyTags.Remove:
                        newTags.ForEach(t => series.Tags.Remove(t));
                        break;

                    case ApplyTags.Replace:
                        series.Tags = new HashSet <int>(newTags);
                        break;
                    }
                }
            }

            if (resource.MoveFiles && seriesToMove.Any())
            {
                _commandQueueManager.Push(new BulkMoveSeriesCommand
                {
                    DestinationRootFolder = resource.RootFolderPath,
                    Series = seriesToMove
                });
            }

            return(ResponseWithCode(_seriesService.UpdateSeries(seriesToUpdate, !resource.MoveFiles)
                                    .ToResource()
                                    , HttpStatusCode.Accepted));
        }