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)); } } } } }
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)); } } }
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 } }); } }
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); }
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); }
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())); } }
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); }
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); }
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); }
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); }
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); }
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)); }
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; } } }
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); }
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)); } } }
public void Handle(SeriesAddedEvent message) { _commandQueueManager.Push(new RefreshSeriesCommand(message.Series.Id)); }
private void QueueRefresh() { _manageCommandQueue.Push(new RefreshMonitoredDownloadsCommand(), CommandPriority.High); }
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)); }
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); }
private void QueueRefresh() { _manageCommandQueue.Push(new RefreshMonitoredDownloadsCommand()); }
public void Handle(ArtistAddedEvent message) { _commandQueueManager.Push(new RefreshArtistCommand(message.Artist.Id, true)); }
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); }
public void Handle(ProviderUpdatedEvent <IImportList> message) { _commandQueueManager.Push(new ImportListSyncCommand(message.Definition.Id)); }
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)); }
public void Handle(MovieAddedEvent message) { _commandQueueManager.Push(new RefreshMovieCommand(new List <int> { message.Movie.Id }, true)); }
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())); }
public void Handle(MovieAddedEvent message) { _commandQueueManager.Push(new RefreshMovieCommand(message.Movie.Id)); }
private void QueueRefresh() { _manageCommandQueue.Push(new CheckForFinishedDownloadCommand()); }
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)); }