public void Import(TrackedDownload trackedDownload) { trackedDownload.State = TrackedDownloadState.Importing; var outputPath = trackedDownload.DownloadItem.OutputPath.FullPath; var importResults = _downloadedTracksImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteBook.Author, trackedDownload.DownloadItem); if (importResults.Empty()) { trackedDownload.State = TrackedDownloadState.ImportFailed; trackedDownload.Warn("No files found are eligible for import in {0}", outputPath); _eventAggregator.PublishEvent(new BookImportIncompleteEvent(trackedDownload)); return; } if (VerifyImport(trackedDownload, importResults)) { return; } trackedDownload.State = TrackedDownloadState.ImportPending; if (importResults.Any(c => c.Result != ImportResultType.Imported)) { trackedDownload.State = TrackedDownloadState.ImportFailed; var statusMessages = importResults .Where(v => v.Result != ImportResultType.Imported) .Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.Item.Path), v.Errors)) .ToArray(); trackedDownload.Warn(statusMessages); _eventAggregator.PublishEvent(new BookImportIncompleteEvent(trackedDownload)); return; } }
public bool IgnoreDownload(TrackedDownload trackedDownload) { var movie = trackedDownload.RemoteMovie.Movie; if (movie == null) { _logger.Warn("Unable to ignore download for unknown movie"); return(false); } var downloadIgnoredEvent = new DownloadIgnoredEvent { MovieId = movie.Id, Languages = trackedDownload.RemoteMovie.ParsedMovieInfo.Languages, Quality = trackedDownload.RemoteMovie.ParsedMovieInfo.Quality, SourceTitle = trackedDownload.DownloadItem.Title, DownloadClientInfo = trackedDownload.DownloadItem.DownloadClientInfo, DownloadId = trackedDownload.DownloadItem.DownloadId, TrackedDownload = trackedDownload, Message = "Manually ignored" }; _eventAggregator.PublishEvent(downloadIgnoredEvent); return(true); }
public void Process(TrackedDownload trackedDownload) { string failure = null; if (trackedDownload.DownloadItem.IsEncrypted) { failure = "Encrypted download detected"; } else if (trackedDownload.DownloadItem.Status == DownloadItemStatus.Failed) { failure = trackedDownload.DownloadItem.Message ?? "Failed download detected"; } if (failure != null) { var grabbedItems = _historyService.Find(trackedDownload.DownloadItem.DownloadId, HistoryEventType.Grabbed) .ToList(); if (grabbedItems.Empty()) { trackedDownload.Warn("Download wasn't grabbed by Bonarr, skipping"); return; } trackedDownload.State = TrackedDownloadStage.DownloadFailed; PublishDownloadFailedEvent(grabbedItems, failure, trackedDownload); } }
public void Import(TrackedDownload trackedDownload) { trackedDownload.State = TrackedDownloadState.Importing; var outputPath = trackedDownload.DownloadItem.OutputPath.FullPath; var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteEpisode.Series, trackedDownload.DownloadItem); if (VerifyImport(trackedDownload, importResults)) { return; } trackedDownload.State = TrackedDownloadState.ImportPending; if (importResults.Empty()) { trackedDownload.Warn("No files found are eligible for import in {0}", outputPath); } if (importResults.Any(c => c.Result != ImportResultType.Imported)) { var statusMessages = importResults .Where(v => v.Result != ImportResultType.Imported && v.ImportDecision.LocalEpisode != null) .Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors)) .ToArray(); trackedDownload.Warn(statusMessages); } }
public bool IgnoreDownload(TrackedDownload trackedDownload) { var artist = trackedDownload.RemoteAlbum.Artist; var albums = trackedDownload.RemoteAlbum.Albums; if (artist == null || albums.Empty()) { _logger.Warn("Unable to ignore download for unknown artist/album"); return(false); } var downloadIgnoredEvent = new DownloadIgnoredEvent { ArtistId = artist.Id, AlbumIds = albums.Select(e => e.Id).ToList(), Quality = trackedDownload.RemoteAlbum.ParsedAlbumInfo.Quality, SourceTitle = trackedDownload.DownloadItem.Title, DownloadClientInfo = trackedDownload.DownloadItem.DownloadClientInfo, DownloadId = trackedDownload.DownloadItem.DownloadId, Message = "Manually ignored" }; _eventAggregator.PublishEvent(downloadIgnoredEvent); return(true); }
private void Import(TrackedDownload trackedDownload) { var outputPath = trackedDownload.DownloadItem.OutputPath.FullPath; var importResults = _downloadedTracksImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteAlbum.Artist, trackedDownload.DownloadItem); if (importResults.Empty()) { trackedDownload.State = TrackedDownloadStage.ImportFailed; trackedDownload.Warn("No files found are eligible for import in {0}", outputPath); _eventAggregator.PublishEvent(new AlbumImportIncompleteEvent(trackedDownload)); return; } if (importResults.All(c => c.Result == ImportResultType.Imported) || importResults.Count(c => c.Result == ImportResultType.Imported) >= Math.Max(1, trackedDownload.RemoteAlbum.Albums.Sum(x => x.AlbumReleases.Value.Where(y => y.Monitored).Sum(z => z.TrackCount)))) { trackedDownload.State = TrackedDownloadStage.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload)); return; } if (importResults.Any(c => c.Result != ImportResultType.Imported)) { trackedDownload.State = TrackedDownloadStage.ImportFailed; var statusMessages = importResults .Where(v => v.Result != ImportResultType.Imported) .Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.Item.Path), v.Errors)) .ToArray(); trackedDownload.Warn(statusMessages); _eventAggregator.PublishEvent(new AlbumImportIncompleteEvent(trackedDownload)); } }
private void Import(TrackedDownload trackedDownload) { var outputPath = trackedDownload.DownloadItem.OutputPath.FullPath; var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, trackedDownload.RemoteEpisode.Series, trackedDownload.DownloadItem); if (importResults.Empty()) { trackedDownload.Warn("No files found are eligible for import in {0}", outputPath); return; } if (importResults.Count(c => c.Result == ImportResultType.Imported) >= Math.Max(1, trackedDownload.RemoteEpisode.Episodes.Count)) { trackedDownload.State = TrackedDownloadStage.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload)); return; } if (importResults.Any(c => c.Result != ImportResultType.Imported)) { var statusMessages = importResults .Where(v => v.Result != ImportResultType.Imported) .Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors)) .ToArray(); trackedDownload.Warn(statusMessages); } }
public bool IgnoreDownload(TrackedDownload trackedDownload) { var series = trackedDownload.RemoteEpisode.Series; if (series == null) { _logger.Warn("Unable to ignore download for unknown series"); return(false); } var episodes = trackedDownload.RemoteEpisode.Episodes; var downloadIgnoredEvent = new DownloadIgnoredEvent { SeriesId = series.Id, EpisodeIds = episodes.Select(e => e.Id).ToList(), Language = trackedDownload.RemoteEpisode.ParsedEpisodeInfo.Language, Quality = trackedDownload.RemoteEpisode.ParsedEpisodeInfo.Quality, SourceTitle = trackedDownload.DownloadItem.Title, DownloadClientInfo = trackedDownload.DownloadItem.DownloadClientInfo, DownloadId = trackedDownload.DownloadItem.DownloadId, TrackedDownload = trackedDownload, Message = "Manually ignored" }; _eventAggregator.PublishEvent(downloadIgnoredEvent); return(true); }
private void RemoveCompleted(TrackedDownload trackedDownload, IDownloadClient downloadClient) { if (trackedDownload.State == TrackedDownloadState.Imported && !trackedDownload.DownloadItem.IsReadOnly) { try { _logger.Debug("[{0}] Removing completed download from history.", trackedDownload.DownloadItem.Title); downloadClient.RemoveItem(trackedDownload.DownloadItem.DownloadClientId); if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath)) { _logger.Debug("Removing completed download directory: {0}", trackedDownload.DownloadItem.OutputPath); _diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath, true); } else if (_diskProvider.FileExists(trackedDownload.DownloadItem.OutputPath)) { _logger.Debug("Removing completed download file: {0}", trackedDownload.DownloadItem.OutputPath); _diskProvider.DeleteFile(trackedDownload.DownloadItem.OutputPath); } trackedDownload.State = TrackedDownloadState.Removed; } catch (NotSupportedException) { UpdateStatusMessage(trackedDownload, LogLevel.Debug, "Removing item not supported by your download client."); } } }
private TrackedDownload GetTrackedDownload(String trackingId, Int32 downloadClient, DownloadClientItem downloadItem, List <History.History> grabbedHistory) { var trackedDownload = new TrackedDownload { TrackingId = trackingId, DownloadClient = downloadClient, DownloadItem = downloadItem, StartedTracking = DateTime.UtcNow, State = TrackedDownloadState.Unknown, Status = TrackedDownloadStatus.Ok, }; try { var historyItems = grabbedHistory.Where(h => { var downloadClientId = h.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID); if (downloadClientId == null) { return(false); } return(downloadClientId.Equals(trackedDownload.DownloadItem.DownloadClientId)); }).ToList(); var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title); if (parsedEpisodeInfo == null) { return(null); } var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0); if (remoteEpisode.Series == null) { if (historyItems.Empty()) { return(null); } trackedDownload.Status = TrackedDownloadStatus.Warning; trackedDownload.StatusMessages.Add(new TrackedDownloadStatusMessage( trackedDownload.DownloadItem.Title, "Series title mismatch, automatic import is not possible") ); remoteEpisode = _parsingService.Map(parsedEpisodeInfo, historyItems.First().SeriesId, historyItems.Select(h => h.EpisodeId)); } trackedDownload.RemoteEpisode = remoteEpisode; } catch (Exception e) { _logger.DebugException("Failed to find episode for " + downloadItem.Title, e); return(null); } return(trackedDownload); }
private void AssociateWithPreviouslyImported(TrackedDownload trackedDownload, List <History.History> grabbedItems, List <History.History> importedHistory) { if (grabbedItems.Any()) { var episodeIds = trackedDownload.RemoteEpisode.Episodes.Select(v => v.Id).ToList(); // Check if we can associate it with a previous drone factory import. var importedItems = importedHistory.Where(v => v.Data.GetValueOrDefault(DownloadTrackingService.DOWNLOAD_CLIENT_ID) == null && episodeIds.Contains(v.EpisodeId) && v.Data.GetValueOrDefault("droppedPath") != null && new FileInfo(v.Data["droppedPath"]).Directory.Name == grabbedItems.First().SourceTitle ).ToList(); if (importedItems.Count == 1) { var importedFile = new FileInfo(importedItems.First().Data["droppedPath"]); if (importedFile.Directory.Name == grabbedItems.First().SourceTitle) { trackedDownload.State = TrackedDownloadState.Imported; importedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT] = grabbedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT]; importedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT_ID] = grabbedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT_ID]; _historyService.UpdateHistoryData(importedItems.First().Id, importedItems.First().Data); UpdateStatusMessage(trackedDownload, LogLevel.Debug, "Intermediate Download path does not exist, but found probable drone factory ImportEvent."); return; } } } UpdateStatusMessage(trackedDownload, LogLevel.Error, "Intermediate Download path does not exist: {0}", trackedDownload.DownloadItem.OutputPath); }
private void ProcessImportResults(TrackedDownload trackedDownload, String outputPath, List <ImportResult> importResults) { if (importResults.Empty()) { UpdateStatusMessage(trackedDownload, LogLevel.Error, "No files found are eligible for import in {0}", outputPath); } else if (importResults.Any(v => v.Result == ImportResultType.Imported) && importResults.All(v => v.Result == ImportResultType.Imported || v.Result == ImportResultType.Rejected)) { UpdateStatusMessage(trackedDownload, LogLevel.Info, "Imported {0} files.", importResults.Count(v => v.Result == ImportResultType.Imported)); trackedDownload.State = TrackedDownloadState.Imported; } else { var errors = importResults .Where(v => v.Result == ImportResultType.Skipped || v.Result == ImportResultType.Rejected) .Select(v => v.Errors.Aggregate(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), (a, r) => a + "\r\n- " + r)) .Aggregate("Failed to import:", (a, r) => a + "\r\n" + r); trackedDownload.StatusMessages = importResults.Where(v => v.Result == ImportResultType.Skipped || v.Result == ImportResultType.Rejected) .Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors)).ToList(); UpdateStatusMessage(trackedDownload, LogLevel.Error, errors); } }
public void ProcessFailed(TrackedDownload trackedDownload) { if (trackedDownload.State != TrackedDownloadState.FailedPending) { return; } var grabbedItems = _historyService .Find(trackedDownload.DownloadItem.DownloadId, HistoryEventType.Grabbed) .ToList(); if (grabbedItems.Empty()) { return; } var failure = "Failed download detected"; if (trackedDownload.DownloadItem.IsEncrypted) { failure = "Encrypted download detected"; } else if (trackedDownload.DownloadItem.Status == DownloadItemStatus.Failed && trackedDownload.DownloadItem.Message.IsNotNullOrWhiteSpace()) { failure = trackedDownload.DownloadItem.Message; } trackedDownload.State = TrackedDownloadState.Failed; PublishDownloadFailedEvent(grabbedItems, failure, trackedDownload); }
public void Check(TrackedDownload trackedDownload) { if (trackedDownload.DownloadItem.Status != DownloadItemStatus.Completed) { return; } SetImportItem(trackedDownload); // Only process tracked downloads that are still downloading if (trackedDownload.State != TrackedDownloadState.Downloading) { return; } var historyItem = _historyService.MostRecentForDownloadId(trackedDownload.DownloadItem.DownloadId); if (historyItem == null && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace()) { trackedDownload.Warn("Download wasn't grabbed by Readarr and not in a category, Skipping."); return; } if (!ValidatePath(trackedDownload)) { return; } trackedDownload.State = TrackedDownloadState.ImportPending; }
public bool IgnoreDownload(TrackedDownload trackedDownload) { var author = trackedDownload.RemoteBook.Author; var books = trackedDownload.RemoteBook.Books; if (author == null || books.Empty()) { _logger.Warn("Unable to ignore download for unknown author/book"); return(false); } var downloadIgnoredEvent = new DownloadIgnoredEvent { AuthorId = author.Id, BookIds = books.Select(e => e.Id).ToList(), Quality = trackedDownload.RemoteBook.ParsedBookInfo.Quality, SourceTitle = trackedDownload.DownloadItem.Title, DownloadClient = trackedDownload.DownloadItem.DownloadClient, DownloadId = trackedDownload.DownloadItem.DownloadId, Message = "Manually ignored" }; _eventAggregator.PublishEvent(downloadIgnoredEvent); return(true); }
private Boolean UpdateTrackedDownloads() { var downloadClients = _downloadClientProvider.GetDownloadClients(); var oldTrackedDownloads = GetTrackedDownloads().ToDictionary(v => v.TrackingId); var newTrackedDownloads = new Dictionary <String, TrackedDownload>(); var stateChanged = false; foreach (var downloadClient in downloadClients) { var downloadClientHistory = downloadClient.GetItems().ToList(); foreach (var downloadItem in downloadClientHistory) { var trackingId = String.Format("{0}-{1}", downloadClient.Definition.Id, downloadItem.DownloadClientId); TrackedDownload trackedDownload; if (newTrackedDownloads.ContainsKey(trackingId)) { continue; } if (!oldTrackedDownloads.TryGetValue(trackingId, out trackedDownload)) { trackedDownload = new TrackedDownload { TrackingId = trackingId, DownloadClient = downloadClient.Definition.Id, StartedTracking = DateTime.UtcNow, State = TrackedDownloadState.Unknown }; _logger.Debug("[{0}] Started tracking download with id {1}.", downloadItem.Title, trackingId); stateChanged = true; } trackedDownload.DownloadItem = downloadItem; newTrackedDownloads[trackingId] = trackedDownload; } } foreach (var trackedDownload in oldTrackedDownloads.Values.Where(v => !newTrackedDownloads.ContainsKey(v.TrackingId))) { if (trackedDownload.State != TrackedDownloadState.Removed) { trackedDownload.State = TrackedDownloadState.Removed; stateChanged = true; _logger.Debug("[{0}] Item with id {1} removed from download client directly (possibly by user).", trackedDownload.DownloadItem.Title, trackedDownload.TrackingId); } _logger.Debug("[{0}] Stopped tracking download with id {1}.", trackedDownload.DownloadItem.Title, trackedDownload.TrackingId); } _trackedDownloadCache.Set("tracked", newTrackedDownloads.Values.ToArray()); return(stateChanged); }
public void Process(TrackedDownload trackedDownload, bool ignoreWarnings = false) { if (trackedDownload.DownloadItem.Status != DownloadItemStatus.Completed) { return; } if (!ignoreWarnings) { var historyItem = _historyService.MostRecentForDownloadId(trackedDownload.DownloadItem.DownloadId); if (historyItem == null && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace()) { trackedDownload.Warn("Download wasn't grabbed by Sonarr and not in a category, Skipping."); return; } var downloadItemOutputPath = trackedDownload.DownloadItem.OutputPath; if (downloadItemOutputPath.IsEmpty) { trackedDownload.Warn("Download doesn't contain intermediate path, Skipping."); return; } if ((OsInfo.IsWindows && !downloadItemOutputPath.IsWindowsPath) || (OsInfo.IsNotWindows && !downloadItemOutputPath.IsUnixPath)) { trackedDownload.Warn("[{0}] is not a valid local path. You may need a Remote Path Mapping.", downloadItemOutputPath); return; } var downloadedEpisodesFolder = new OsPath(_configService.DownloadedEpisodesFolder); if (downloadedEpisodesFolder.Contains(downloadItemOutputPath)) { trackedDownload.Warn("Intermediate Download path inside drone factory, Skipping."); return; } var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title); if (series == null) { if (historyItem != null) { series = _seriesService.GetSeries(historyItem.SeriesId); } if (series == null) { trackedDownload.Warn("Series title mismatch, automatic import is not possible."); return; } } } Import(trackedDownload); }
public void Check(TrackedDownload trackedDownload) { if (trackedDownload.DownloadItem.Status != DownloadItemStatus.Completed || trackedDownload.RemoteBook == null) { return; } trackedDownload.ImportItem = _importItemService.ProvideImportItem(trackedDownload.DownloadItem, trackedDownload.ImportItem); // Only process tracked downloads that are still downloading if (trackedDownload.State != TrackedDownloadState.Downloading) { return; } var historyItem = _historyService.MostRecentForDownloadId(trackedDownload.DownloadItem.DownloadId); if (historyItem == null && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace()) { trackedDownload.Warn("Download wasn't grabbed by Readarr and not in a category, Skipping."); return; } var downloadItemOutputPath = trackedDownload.ImportItem.OutputPath; if (downloadItemOutputPath.IsEmpty) { trackedDownload.Warn("Download doesn't contain intermediate path, Skipping."); return; } if ((OsInfo.IsWindows && !downloadItemOutputPath.IsWindowsPath) || (OsInfo.IsNotWindows && !downloadItemOutputPath.IsUnixPath)) { trackedDownload.Warn("[{0}] is not a valid local path. You may need a Remote Path Mapping.", downloadItemOutputPath); return; } var author = trackedDownload.RemoteBook.Author; if (author == null) { if (historyItem != null) { author = _authorService.GetAuthor(historyItem.AuthorId); } if (author == null) { trackedDownload.Warn("Author name mismatch, automatic import is not possible."); return; } } trackedDownload.State = TrackedDownloadState.ImportPending; }
public void Import(TrackedDownload trackedDownload) { SetImportItem(trackedDownload); if (!ValidatePath(trackedDownload)) { return; } if (trackedDownload.RemoteEpisode == null) { trackedDownload.Warn("Unable to parse download, automatic import is not possible."); return; } trackedDownload.State = TrackedDownloadState.Importing; var outputPath = trackedDownload.ImportItem.OutputPath.FullPath; var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteEpisode.Series, trackedDownload.ImportItem); if (VerifyImport(trackedDownload, importResults)) { return; } trackedDownload.State = TrackedDownloadState.ImportPending; if (importResults.Empty()) { trackedDownload.Warn("No files found are eligible for import in {0}", outputPath); return; } var statusMessages = new List <TrackedDownloadStatusMessage> { new TrackedDownloadStatusMessage("One or more episodes expected in this release were not imported or missing", new List <string>()) }; if (importResults.Any(c => c.Result != ImportResultType.Imported)) { statusMessages.AddRange( importResults .Where(v => v.Result != ImportResultType.Imported && v.ImportDecision.LocalEpisode != null) .OrderBy(v => v.ImportDecision.LocalEpisode.Path) .Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors)) ); } if (statusMessages.Any()) { trackedDownload.Warn(statusMessages.ToArray()); } }
public void Import(TrackedDownload trackedDownload) { trackedDownload.State = TrackedDownloadState.Importing; var outputPath = trackedDownload.DownloadItem.OutputPath.FullPath; var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteEpisode.Series, trackedDownload.DownloadItem); var allEpisodesImported = importResults.Where(c => c.Result == ImportResultType.Imported) .SelectMany(c => c.ImportDecision.LocalEpisode.Episodes) .Count() >= Math.Max(1, trackedDownload.RemoteEpisode.Episodes.Count); if (allEpisodesImported) { trackedDownload.State = TrackedDownloadState.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload)); return; } // Double check if all episodes were imported by checking the history if at least one // file was imported. This will allow the decision engine to reject already imported // episode files and still mark the download complete when all files are imported. if (importResults.Any(c => c.Result == ImportResultType.Imported)) { var historyItems = _historyService.FindByDownloadId(trackedDownload.DownloadItem.DownloadId) .OrderByDescending(h => h.Date) .ToList(); var allEpisodesImportedInHistory = _trackedDownloadAlreadyImported.IsImported(trackedDownload, historyItems); if (allEpisodesImportedInHistory) { trackedDownload.State = TrackedDownloadState.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload)); return; } } trackedDownload.State = TrackedDownloadState.ImportPending; if (importResults.Empty()) { trackedDownload.Warn("No files found are eligible for import in {0}", outputPath); } if (importResults.Any(c => c.Result != ImportResultType.Imported)) { var statusMessages = importResults .Where(v => v.Result != ImportResultType.Imported) .Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors)) .ToArray(); trackedDownload.Warn(statusMessages); } }
public bool VerifyImport(TrackedDownload trackedDownload, List <ImportResult> importResults) { var allEpisodesImported = importResults.Where(c => c.Result == ImportResultType.Imported) .SelectMany(c => c.ImportDecision.LocalEpisode.Episodes) .Count() >= Math.Max(1, trackedDownload.RemoteEpisode.Episodes.Count); if (allEpisodesImported) { _logger.Debug("All episodes were imported for {0}", trackedDownload.DownloadItem.Title); trackedDownload.State = TrackedDownloadState.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, trackedDownload.RemoteEpisode.Series.Id)); return(true); } // Double check if all episodes were imported by checking the history if at least one // file was imported. This will allow the decision engine to reject already imported // episode files and still mark the download complete when all files are imported. // EDGE CASE: This process relies on EpisodeIds being consistent between executions, if a series is updated // and an episode is removed, but later comes back with a different ID then Sonarr will treat it as incomplete. // Since imports should be relatively fast and these types of data changes are infrequent this should be quite // safe, but commenting for future benefit. var atLeastOneEpisodeImported = importResults.Any(c => c.Result == ImportResultType.Imported); var historyItems = _historyService.FindByDownloadId(trackedDownload.DownloadItem.DownloadId) .OrderByDescending(h => h.Date) .ToList(); var allEpisodesImportedInHistory = _trackedDownloadAlreadyImported.IsImported(trackedDownload, historyItems); if (allEpisodesImportedInHistory) { if (atLeastOneEpisodeImported) { _logger.Debug("All episodes were imported in history for {0}", trackedDownload.DownloadItem.Title); trackedDownload.State = TrackedDownloadState.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, trackedDownload.RemoteEpisode.Series.Id)); return(true); } _logger.Debug() .Message("No Episodes were just imported, but all episodes were previously imported, possible issue with download history.") .Property("SeriesId", trackedDownload.RemoteEpisode.Series.Id) .Property("DownloadId", trackedDownload.DownloadItem.DownloadId) .Property("Title", trackedDownload.DownloadItem.Title) .Property("Path", trackedDownload.DownloadItem.OutputPath.ToString()) .WriteSentryWarn("DownloadHistoryIncomplete") .Write(); } _logger.Debug("Not all episodes have been imported for {0}", trackedDownload.DownloadItem.Title); return(false); }
public bool VerifyImport(TrackedDownload trackedDownload, List <ImportResult> importResults) { var allMoviesImported = importResults.Where(c => c.Result == ImportResultType.Imported) .Select(c => c.ImportDecision.LocalMovie.Movie) .Any(); if (allMoviesImported) { _logger.Debug("All movies were imported for {0}", trackedDownload.DownloadItem.Title); trackedDownload.State = TrackedDownloadState.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, trackedDownload.RemoteMovie.Movie.Id)); return(true); } // Double check if all movies were imported by checking the history if at least one // file was imported. This will allow the decision engine to reject already imported // episode files and still mark the download complete when all files are imported. var atLeastOneMovieImported = importResults.Any(c => c.Result == ImportResultType.Imported); var historyItems = _historyService.FindByDownloadId(trackedDownload.DownloadItem.DownloadId) .OrderByDescending(h => h.Date) .ToList(); var allMoviesImportedInHistory = _trackedDownloadAlreadyImported.IsImported(trackedDownload, historyItems); if (allMoviesImportedInHistory) { // Log different error messages depending on the circumstances, but treat both as fully imported, because that's the reality. // The second message shouldn't be logged in most cases, but continued reporting would indicate an ongoing issue. if (atLeastOneMovieImported) { _logger.Debug("All movies were imported in history for {0}", trackedDownload.DownloadItem.Title); } else { _logger.Debug() .Message("No Movies were just imported, but all movies were previously imported, possible issue with download history.") .Property("MovieId", trackedDownload.RemoteMovie.Movie.Id) .Property("DownloadId", trackedDownload.DownloadItem.DownloadId) .Property("Title", trackedDownload.DownloadItem.Title) .Property("Path", trackedDownload.ImportItem.OutputPath.ToString()) .WriteSentryWarn("DownloadHistoryIncomplete") .Write(); } trackedDownload.State = TrackedDownloadState.Imported; _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, trackedDownload.RemoteMovie.Movie.Id)); return(true); } _logger.Debug("Not all movies have been imported for {0}", trackedDownload.DownloadItem.Title); return(false); }
public void Check(TrackedDownload trackedDownload) { if (trackedDownload.DownloadItem.Status != DownloadItemStatus.Completed) { return; } // Only process tracked downloads that are still downloading if (trackedDownload.State != TrackedDownloadState.Downloading) { return; } var historyItem = _historyService.MostRecentForDownloadId(trackedDownload.DownloadItem.DownloadId); if (historyItem == null && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace()) { trackedDownload.Warn("Download wasn't grabbed by Sonarr and not in a category, Skipping."); return; } var downloadItemOutputPath = trackedDownload.DownloadItem.OutputPath; if (downloadItemOutputPath.IsEmpty) { trackedDownload.Warn("Download doesn't contain intermediate path, Skipping."); return; } if ((OsInfo.IsWindows && !downloadItemOutputPath.IsWindowsPath) || (OsInfo.IsNotWindows && !downloadItemOutputPath.IsUnixPath)) { trackedDownload.Warn("[{0}] is not a valid local path. You may need a Remote Path Mapping.", downloadItemOutputPath); return; } var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title); if (series == null) { if (historyItem != null) { series = _seriesService.GetSeries(historyItem.SeriesId); } if (series == null) { trackedDownload.Warn("Series title mismatch, automatic import is not possible."); return; } } trackedDownload.State = TrackedDownloadState.ImportPending; }
public void Check(TrackedDownload trackedDownload) { if (trackedDownload.DownloadItem.Status != DownloadItemStatus.Completed) { return; } SetImportItem(trackedDownload); // Only process tracked downloads that are still downloading if (trackedDownload.State != TrackedDownloadState.Downloading) { return; } var historyItem = _historyService.MostRecentForDownloadId(trackedDownload.DownloadItem.DownloadId); if (historyItem == null && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace()) { trackedDownload.Warn("Download wasn't grabbed by Sonarr and not in a category, Skipping."); return; } if (!ValidatePath(trackedDownload)) { return; } var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title); if (series == null) { if (historyItem != null) { series = _seriesService.GetSeries(historyItem.SeriesId); } if (series == null) { trackedDownload.Warn("Series title mismatch; automatic import is not possible."); return; } Enum.TryParse(historyItem.Data.GetValueOrDefault(EpisodeHistory.SERIES_MATCH_TYPE, SeriesMatchType.Unknown.ToString()), out SeriesMatchType seriesMatchType); if (seriesMatchType == SeriesMatchType.Id) { trackedDownload.Warn("Found matching series via grab history, but release was matched to series by ID. Automatic import is not possible."); return; } } trackedDownload.State = TrackedDownloadState.ImportPending; }
public void Process(TrackedDownload trackedDownload, bool ignoreWarnings = false) { if (trackedDownload.DownloadItem.Status != DownloadItemStatus.Completed || trackedDownload.RemoteAlbum == null) { return; } if (!ignoreWarnings) { var historyItem = _historyService.MostRecentForDownloadId(trackedDownload.DownloadItem.DownloadId); if (historyItem == null && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace()) { trackedDownload.Warn("Download wasn't grabbed by Lidarr and not in a category, Skipping."); return; } var downloadItemOutputPath = trackedDownload.DownloadItem.OutputPath; if (downloadItemOutputPath.IsEmpty) { trackedDownload.Warn("Download doesn't contain intermediate path, Skipping."); return; } if ((OsInfo.IsWindows && !downloadItemOutputPath.IsWindowsPath) || (OsInfo.IsNotWindows && !downloadItemOutputPath.IsUnixPath)) { trackedDownload.Warn("[{0}] is not a valid local path. You may need a Remote Path Mapping.", downloadItemOutputPath); return; } var artist = trackedDownload.RemoteAlbum.Artist; if (artist == null) { if (historyItem != null) { artist = _artistService.GetArtist(historyItem.ArtistId); } if (artist == null) { trackedDownload.Warn("Artist name mismatch, automatic import is not possible."); return; } } } Import(trackedDownload); }
private void MarkItemAsImported(TrackedDownload trackedDownload, IDownloadClient downloadClient) { try { _logger.Debug("[{0}] Marking download as imported from {1}", trackedDownload.DownloadItem.Title, trackedDownload.DownloadItem.DownloadClientInfo.Name); downloadClient.MarkItemAsImported(trackedDownload.DownloadItem); } catch (NotSupportedException e) { _logger.Debug(e.Message); } catch (Exception e) { _logger.Error(e, "Couldn't mark item {0} as imported from client {1}", trackedDownload.DownloadItem.Title, downloadClient.Name); } }
private void UpdateStatusMessage(TrackedDownload trackedDownload, LogLevel logLevel, String message, params object[] args) { var statusMessage = String.Format(message, args); var logMessage = String.Format("[{0}] {1}", trackedDownload.DownloadItem.Title, statusMessage); if (trackedDownload.StatusMessage != statusMessage) { trackedDownload.HasError = logLevel >= LogLevel.Warn; trackedDownload.StatusMessage = statusMessage; _logger.Log(logLevel, logMessage); } else { _logger.Debug(logMessage); } }
public void Check(TrackedDownload trackedDownload) { if (trackedDownload.DownloadItem.Status != DownloadItemStatus.Completed || trackedDownload.RemoteAlbum == null) { return; } SetImportItem(trackedDownload); // Only process tracked downloads that are still downloading if (trackedDownload.State != TrackedDownloadState.Downloading) { return; } var historyItem = _historyService.MostRecentForDownloadId(trackedDownload.DownloadItem.DownloadId); if (historyItem == null && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace()) { trackedDownload.Warn("Download wasn't grabbed by Lidarr and not in a category, Skipping."); return; } if (!ValidatePath(trackedDownload)) { return; } var artist = trackedDownload.RemoteAlbum.Artist; if (artist == null) { if (historyItem != null) { artist = _artistService.GetArtist(historyItem.ArtistId); } if (artist == null) { trackedDownload.Warn("Artist name mismatch, automatic import is not possible."); return; } } trackedDownload.State = TrackedDownloadState.ImportPending; }
public void Check(TrackedDownload trackedDownload) { if (trackedDownload.DownloadItem.Status != DownloadItemStatus.Completed) { return; } SetImportItem(trackedDownload); // Only process tracked downloads that are still downloading if (trackedDownload.State != TrackedDownloadState.Downloading) { return; } var historyItem = _historyService.MostRecentForDownloadId(trackedDownload.DownloadItem.DownloadId); if (historyItem == null && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace()) { trackedDownload.Warn("Download wasn't grabbed by Sonarr and not in a category, Skipping."); return; } if (!ValidatePath(trackedDownload)) { return; } var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title); if (series == null) { if (historyItem != null) { series = _seriesService.GetSeries(historyItem.SeriesId); } if (series == null) { trackedDownload.Warn("Series title mismatch, automatic import is not possible."); return; } } trackedDownload.State = TrackedDownloadState.ImportPending; }
private void RemoveFromDownloadClient(TrackedDownload trackedDownload, IDownloadClient downloadClient) { try { _logger.Debug("[{0}] Removing download from {1} history", trackedDownload.DownloadItem.Title, trackedDownload.DownloadItem.DownloadClientInfo.Name); downloadClient.RemoveItem(trackedDownload.DownloadItem, true); trackedDownload.DownloadItem.Removed = true; } catch (NotSupportedException) { _logger.Warn("Removing item not supported by your download client ({0}).", downloadClient.Definition.Name); } catch (Exception e) { _logger.Error(e, "Couldn't remove item {0} from client {1}", trackedDownload.DownloadItem.Title, downloadClient.Name); } }
public void CheckForCompletedItem(IDownloadClient downloadClient, TrackedDownload trackedDownload, List<History.History> grabbedHistory, List<History.History> importedHistory) { if (!_configService.EnableCompletedDownloadHandling) { return; } if (trackedDownload.DownloadItem.Status == DownloadItemStatus.Completed && trackedDownload.State == TrackedDownloadState.Downloading) { var grabbedItems = GetHistoryItems(grabbedHistory, trackedDownload.DownloadItem.DownloadClientId); if (!grabbedItems.Any() && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace()) { _logger.Trace("Ignoring download that wasn't grabbed by drone: " + trackedDownload.DownloadItem.Title); return; } var importedItems = GetHistoryItems(importedHistory, trackedDownload.DownloadItem.DownloadClientId); if (importedItems.Any()) { trackedDownload.State = TrackedDownloadState.Imported; _logger.Debug("Already added to history as imported: " + trackedDownload.DownloadItem.Title); } else { string downloadedEpisodesFolder = _configService.DownloadedEpisodesFolder; string downloadItemOutputPath = trackedDownload.DownloadItem.OutputPath; if (downloadItemOutputPath.IsNullOrWhiteSpace()) { _logger.Trace("Storage path not specified: " + trackedDownload.DownloadItem.Title); return; } if (!downloadedEpisodesFolder.IsNullOrWhiteSpace() && (downloadedEpisodesFolder.PathEquals(downloadItemOutputPath) || downloadedEpisodesFolder.IsParentPath(downloadItemOutputPath))) { _logger.Trace("Storage path inside drone factory, ignoring download: " + trackedDownload.DownloadItem.Title); return; } if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath)) { var decisions = _downloadedEpisodesImportService.ProcessFolder(new DirectoryInfo(trackedDownload.DownloadItem.OutputPath), trackedDownload.DownloadItem); if (decisions.Any()) { trackedDownload.State = TrackedDownloadState.Imported; } } else if (_diskProvider.FileExists(trackedDownload.DownloadItem.OutputPath)) { var decisions = _downloadedEpisodesImportService.ProcessFile(new FileInfo(trackedDownload.DownloadItem.OutputPath), trackedDownload.DownloadItem); if (decisions.Any()) { trackedDownload.State = TrackedDownloadState.Imported; } } else { if (grabbedItems.Any()) { var episodeIds = trackedDownload.DownloadItem.RemoteEpisode.Episodes.Select(v => v.Id).ToList(); // Check if we can associate it with a previous drone factory import. importedItems = importedHistory.Where(v => v.Data.GetValueOrDefault(DownloadTrackingService.DOWNLOAD_CLIENT_ID) == null && episodeIds.Contains(v.EpisodeId) && v.Data.GetValueOrDefault("droppedPath") != null && new FileInfo(v.Data["droppedPath"]).Directory.Name == grabbedItems.First().SourceTitle ).ToList(); if (importedItems.Count == 1) { var importedFile = new FileInfo(importedItems.First().Data["droppedPath"]); if (importedFile.Directory.Name == grabbedItems.First().SourceTitle) { trackedDownload.State = TrackedDownloadState.Imported; importedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT] = grabbedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT]; importedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT_ID] = grabbedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT_ID]; _historyService.UpdateHistoryData(importedItems.First().Id, importedItems.First().Data); _logger.Debug("Storage path does not exist, but found probable drone factory ImportEvent: " + trackedDownload.DownloadItem.Title); return; } } } _logger.Debug("Storage path does not exist: " + trackedDownload.DownloadItem.Title); return; } } } if (_configService.RemoveCompletedDownloads && trackedDownload.State == TrackedDownloadState.Imported && !trackedDownload.DownloadItem.IsReadOnly) { try { _logger.Info("Removing completed download from history: {0}", trackedDownload.DownloadItem.Title); downloadClient.RemoveItem(trackedDownload.DownloadItem.DownloadClientId); if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath)) { _logger.Info("Removing completed download directory: {0}", trackedDownload.DownloadItem.OutputPath); _diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath, true); } else if (_diskProvider.FileExists(trackedDownload.DownloadItem.OutputPath)) { _logger.Info("Removing completed download file: {0}", trackedDownload.DownloadItem.OutputPath); _diskProvider.DeleteFile(trackedDownload.DownloadItem.OutputPath); } trackedDownload.State = TrackedDownloadState.Removed; } catch (NotSupportedException) { _logger.Debug("Removing item not supported by your download client"); } } }
public void CheckForFailedItem(IDownloadClient downloadClient, TrackedDownload trackedDownload, List<History.History> grabbedHistory, List<History.History> failedHistory) { if (!_configService.EnableFailedDownloadHandling) { return; } if (trackedDownload.DownloadItem.IsEncrypted && trackedDownload.State == TrackedDownloadState.Downloading) { var grabbedItems = GetHistoryItems(grabbedHistory, trackedDownload.DownloadItem.DownloadClientId); if (!grabbedItems.Any()) { _logger.Debug("Download was not grabbed by drone, ignoring."); return; } trackedDownload.State = TrackedDownloadState.DownloadFailed; var failedItems = GetHistoryItems(failedHistory, trackedDownload.DownloadItem.DownloadClientId); if (failedItems.Any()) { _logger.Debug("Already added to history as failed"); } else { PublishDownloadFailedEvent(grabbedItems, "Encrypted download detected"); } } if (trackedDownload.DownloadItem.Status == DownloadItemStatus.Failed && trackedDownload.State == TrackedDownloadState.Downloading) { var grabbedItems = GetHistoryItems(grabbedHistory, trackedDownload.DownloadItem.DownloadClientId); if (!grabbedItems.Any()) { _logger.Debug("Download was not grabbed by drone, ignoring."); return; } //TODO: Make this more configurable (ignore failure reasons) to support changes and other failures that should be ignored if (trackedDownload.DownloadItem.Message.Equals("Unpacking failed, write error or disk is full?", StringComparison.InvariantCultureIgnoreCase)) { _logger.Debug("Failed due to lack of disk space, do not blacklist"); return; } if (FailedDownloadForRecentRelease(downloadClient, trackedDownload, grabbedItems)) { _logger.Debug("Recent release Failed, do not blacklist"); return; } trackedDownload.State = TrackedDownloadState.DownloadFailed; var failedItems = GetHistoryItems(failedHistory, trackedDownload.DownloadItem.DownloadClientId); if (failedItems.Any()) { _logger.Debug("Already added to history as failed"); } else { PublishDownloadFailedEvent(grabbedItems, trackedDownload.DownloadItem.Message); } } if (_configService.RemoveFailedDownloads && trackedDownload.State == TrackedDownloadState.DownloadFailed) { try { _logger.Info("Removing failed download from client: {0}", trackedDownload.DownloadItem.Title); downloadClient.RemoveItem(trackedDownload.DownloadItem.DownloadClientId); trackedDownload.State = TrackedDownloadState.Removed; } catch (NotSupportedException) { _logger.Debug("Removing item not supported by your download client"); } } }
public void CheckForCompletedItem(IDownloadClient downloadClient, TrackedDownload trackedDownload, List<History.History> grabbedHistory, List<History.History> importedHistory) { if (!_configService.EnableCompletedDownloadHandling) { return; } if (trackedDownload.DownloadItem.Status == DownloadItemStatus.Completed && trackedDownload.State == TrackedDownloadState.Downloading) { var grabbedItems = GetHistoryItems(grabbedHistory, trackedDownload.DownloadItem.DownloadClientId); if (!grabbedItems.Any() && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace()) { UpdateStatusMessage(trackedDownload, LogLevel.Debug, "Download wasn't grabbed by drone or not in a category, ignoring download."); return; } var importedItems = GetHistoryItems(importedHistory, trackedDownload.DownloadItem.DownloadClientId); if (importedItems.Any()) { trackedDownload.State = TrackedDownloadState.Imported; UpdateStatusMessage(trackedDownload, LogLevel.Debug, "Already added to history as imported."); } else { string downloadedEpisodesFolder = _configService.DownloadedEpisodesFolder; string downloadItemOutputPath = trackedDownload.DownloadItem.OutputPath; if (downloadItemOutputPath.IsNullOrWhiteSpace()) { UpdateStatusMessage(trackedDownload, LogLevel.Warn, "Download doesn't contain intermediate path, ignoring download."); return; } if (!downloadedEpisodesFolder.IsNullOrWhiteSpace() && (downloadedEpisodesFolder.PathEquals(downloadItemOutputPath) || downloadedEpisodesFolder.IsParentPath(downloadItemOutputPath))) { UpdateStatusMessage(trackedDownload, LogLevel.Warn, "Intermediate Download path inside drone factory, ignoring download."); return; } if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath)) { var decisions = _downloadedEpisodesImportService.ProcessFolder(new DirectoryInfo(trackedDownload.DownloadItem.OutputPath), trackedDownload.DownloadItem); if (!decisions.Any()) { UpdateStatusMessage(trackedDownload, LogLevel.Error, "No files found eligible for import in {0}", trackedDownload.DownloadItem.OutputPath); } else if (decisions.Any(v => v.Approved)) { UpdateStatusMessage(trackedDownload, LogLevel.Info, "Imported {0} files.", decisions.Count(v => v.Approved)); trackedDownload.State = TrackedDownloadState.Imported; } else { var rejections = decisions .Where(v => !v.Approved) .Select(v => v.Rejections.Aggregate(Path.GetFileName(v.LocalEpisode.Path), (a, r) => a + "\r\n- " + r)) .Aggregate("Failed to import:", (a, r) => a + "\r\n" + r); UpdateStatusMessage(trackedDownload, LogLevel.Error, rejections); } } else if (_diskProvider.FileExists(trackedDownload.DownloadItem.OutputPath)) { var decisions = _downloadedEpisodesImportService.ProcessFile(new FileInfo(trackedDownload.DownloadItem.OutputPath), trackedDownload.DownloadItem); if (!decisions.Any()) { UpdateStatusMessage(trackedDownload, LogLevel.Error, "No files found eligible for import in {0}", trackedDownload.DownloadItem.OutputPath); } else if (decisions.Any(v => v.Approved)) { UpdateStatusMessage(trackedDownload, LogLevel.Info, "Imported {0} files.", decisions.Count(v => v.Approved)); trackedDownload.State = TrackedDownloadState.Imported; } else { var rejections = decisions .Where(v => !v.Approved) .Select(v => v.Rejections.Aggregate(Path.GetFileName(v.LocalEpisode.Path), (a, r) => a + "\r\n- " + r)) .Aggregate("Failed to import:", (a, r) => a + "\r\n" + r); UpdateStatusMessage(trackedDownload, LogLevel.Error, rejections); } } else { if (grabbedItems.Any()) { var episodeIds = trackedDownload.DownloadItem.RemoteEpisode.Episodes.Select(v => v.Id).ToList(); // Check if we can associate it with a previous drone factory import. importedItems = importedHistory.Where(v => v.Data.GetValueOrDefault(DownloadTrackingService.DOWNLOAD_CLIENT_ID) == null && episodeIds.Contains(v.EpisodeId) && v.Data.GetValueOrDefault("droppedPath") != null && new FileInfo(v.Data["droppedPath"]).Directory.Name == grabbedItems.First().SourceTitle ).ToList(); if (importedItems.Count == 1) { var importedFile = new FileInfo(importedItems.First().Data["droppedPath"]); if (importedFile.Directory.Name == grabbedItems.First().SourceTitle) { trackedDownload.State = TrackedDownloadState.Imported; importedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT] = grabbedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT]; importedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT_ID] = grabbedItems.First().Data[DownloadTrackingService.DOWNLOAD_CLIENT_ID]; _historyService.UpdateHistoryData(importedItems.First().Id, importedItems.First().Data); UpdateStatusMessage(trackedDownload, LogLevel.Debug, "Intermediate Download path does not exist, but found probable drone factory ImportEvent."); return; } } } UpdateStatusMessage(trackedDownload, LogLevel.Error, "Intermediate Download path does not exist: {0}", trackedDownload.DownloadItem.OutputPath); return; } } } if (_configService.RemoveCompletedDownloads && trackedDownload.State == TrackedDownloadState.Imported && !trackedDownload.DownloadItem.IsReadOnly) { try { _logger.Debug("[{0}] Removing completed download from history.", trackedDownload.DownloadItem.Title); downloadClient.RemoveItem(trackedDownload.DownloadItem.DownloadClientId); if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath)) { _logger.Debug("Removing completed download directory: {0}", trackedDownload.DownloadItem.OutputPath); _diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath, true); } else if (_diskProvider.FileExists(trackedDownload.DownloadItem.OutputPath)) { _logger.Debug("Removing completed download file: {0}", trackedDownload.DownloadItem.OutputPath); _diskProvider.DeleteFile(trackedDownload.DownloadItem.OutputPath); } trackedDownload.State = TrackedDownloadState.Removed; } catch (NotSupportedException) { UpdateStatusMessage(trackedDownload, LogLevel.Debug, "Removing item not supported by your download client."); } } }
private bool FailedDownloadForRecentRelease(IDownloadClient downloadClient, TrackedDownload trackedDownload, List<History.History> matchingHistoryItems) { double ageHours; if (!Double.TryParse(matchingHistoryItems.First().Data.GetValueOrDefault("ageHours"), out ageHours)) { _logger.Debug("Unable to determine age of failed download"); return false; } if (ageHours > _configService.BlacklistGracePeriod) { _logger.Debug("Failed download is older than the grace period"); return false; } if (trackedDownload.RetryCount >= _configService.BlacklistRetryLimit) { _logger.Debug("Retry limit reached"); return false; } if (trackedDownload.RetryCount == 0 || trackedDownload.LastRetry.AddMinutes(_configService.BlacklistRetryInterval) < DateTime.UtcNow) { _logger.Debug("Retrying failed release"); trackedDownload.LastRetry = DateTime.UtcNow; trackedDownload.RetryCount++; try { downloadClient.RetryDownload(trackedDownload.DownloadItem.DownloadClientId); } catch (NotSupportedException ex) { _logger.Debug("Retrying failed downloads is not supported by your download client"); return false; } } return true; }