コード例 #1
0
        public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem)
        {
            var existingItem = Find(downloadItem.DownloadId);

            if (existingItem != null && existingItem.State != TrackedDownloadStage.Downloading)
            {
                existingItem.DownloadItem = downloadItem;
                return existingItem;
            }

            var trackedDownload = new TrackedDownload
            {
                DownloadClient = downloadClient.Id,
                DownloadItem = downloadItem,
                Protocol = downloadClient.Protocol
            };

            try
            {
                var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title);
                var historyItems = _historyService.FindByDownloadId(downloadItem.DownloadId);

                if (parsedEpisodeInfo != null)
                {
                    trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0);
                }

                if (historyItems.Any())
                {
                    var firstHistoryItem = historyItems.OrderByDescending(h => h.Date).First();
                    trackedDownload.State = GetStateFromHistory(firstHistoryItem.EventType);

                    if (parsedEpisodeInfo == null ||
                        trackedDownload.RemoteEpisode == null ||
                        trackedDownload.RemoteEpisode.Series == null ||
                        trackedDownload.RemoteEpisode.Episodes.Empty())
                    {
                        parsedEpisodeInfo = Parser.Parser.ParseTitle(firstHistoryItem.SourceTitle);
                        if (parsedEpisodeInfo != null)
                        {
                            trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, firstHistoryItem.SeriesId, historyItems.Where(v => v.EventType == HistoryEventType.Grabbed).Select(h => h.EpisodeId).Distinct());
                        }
                    }
                }

                if (trackedDownload.RemoteEpisode == null)
                {
                    return null;
                }
            }
            catch (Exception e)
            {
                _logger.DebugException("Failed to find episode for " + downloadItem.Title, e);
                return null;
            }

            _cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload);
            return trackedDownload;
        }
コード例 #2
0
        public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem)
        {
            var existingItem = Find(downloadItem.DownloadId);

            if (existingItem != null && existingItem.State != TrackedDownloadStage.Downloading)
            {
                existingItem.DownloadItem = downloadItem;
                return existingItem;
            }

            var trackedDownload = new TrackedDownload
            {
                DownloadClient = downloadClient.Id,
                DownloadItem = downloadItem,
                Protocol = downloadClient.Protocol
            };

            try
            {
                var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title);
                if (parsedEpisodeInfo == null) return null;

                var remoteEpisode = _parsingService.Map(parsedEpisodeInfo);

                if (remoteEpisode.Series == null || !remoteEpisode.Episodes.Any())
                {
                    var historyItems = _historyService.FindByDownloadId(downloadItem.DownloadId);

                    if (historyItems.Empty())
                    {
                        return null;
                    }

                    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;
            }

            var historyItem = _historyService.MostRecentForDownloadId(downloadItem.DownloadId);

            if (historyItem != null)
            {
                trackedDownload.State = GetStateFromHistory(historyItem.EventType);
            }

            _cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload);

            return trackedDownload;
        }
コード例 #3
0
        public void should_track_downloads_using_the_source_title_if_it_cannot_be_found_using_the_download_title()
        {
            GivenDownloadHistory();

            var remoteEpisode = new RemoteEpisode
            {
                Series = new Series()
                {
                    Id = 5
                },
                Episodes = new List <Episode> {
                    new Episode {
                        Id = 4
                    }
                },
                ParsedEpisodeInfo = new ParsedEpisodeInfo()
                {
                    SeriesTitle  = "TV Series",
                    SeasonNumber = 1
                }
            };

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.Is <ParsedEpisodeInfo>(i => i.SeasonNumber == 1 && i.SeriesTitle == "TV Series"), It.IsAny <int>(), It.IsAny <IEnumerable <int> >()))
            .Returns(remoteEpisode);

            var client = new DownloadClientDefinition()
            {
                Id       = 1,
                Protocol = DownloadProtocol.Torrent
            };

            var item = new DownloadClientItem()
            {
                Title      = "The torrent release folder",
                DownloadId = "35238",
            };

            var trackedDownload = Subject.TrackDownload(client, item);

            trackedDownload.Should().NotBeNull();
            trackedDownload.RemoteEpisode.Should().NotBeNull();
            trackedDownload.RemoteEpisode.Series.Should().NotBeNull();
            trackedDownload.RemoteEpisode.Series.Id.Should().Be(5);
            trackedDownload.RemoteEpisode.Episodes.First().Id.Should().Be(4);
            trackedDownload.RemoteEpisode.ParsedEpisodeInfo.SeasonNumber.Should().Be(1);
        }
コード例 #4
0
        public void should_track_downloads_using_the_source_title_if_it_cannot_be_found_using_the_download_title()
        {
            GivenDownloadHistory();

            var remoteBook = new RemoteBook
            {
                Author = new Author()
                {
                    Id = 5
                },
                Books = new List <Book> {
                    new Book {
                        Id = 4
                    }
                },
                ParsedBookInfo = new ParsedBookInfo()
                {
                    BookTitle  = "Audio Album",
                    AuthorName = "Audio Artist"
                }
            };

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.Is <ParsedBookInfo>(i => i.BookTitle == "Audio Album" && i.AuthorName == "Audio Artist"), It.IsAny <int>(), It.IsAny <IEnumerable <int> >()))
            .Returns(remoteBook);

            var client = new DownloadClientDefinition()
            {
                Id       = 1,
                Protocol = DownloadProtocol.Torrent
            };

            var item = new DownloadClientItem()
            {
                Title      = "The torrent release folder",
                DownloadId = "35238",
            };

            var trackedDownload = Subject.TrackDownload(client, item);

            trackedDownload.Should().NotBeNull();
            trackedDownload.RemoteBook.Should().NotBeNull();
            trackedDownload.RemoteBook.Author.Should().NotBeNull();
            trackedDownload.RemoteBook.Author.Id.Should().Be(5);
            trackedDownload.RemoteBook.Books.First().Id.Should().Be(4);
        }
コード例 #5
0
        public void should_track_downloads_using_the_source_title_if_it_cannot_be_found_using_the_download_title()
        {
            GivenDownloadHistory();

            var remoteEpisode = new RemoteMovie
            {
                Movie = new Movie()
                {
                    Id = 3
                },

                ParsedMovieInfo = new ParsedMovieInfo()
                {
                    MovieTitle = "A Movie",
                    Year       = 1998
                }
            };

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.Is <ParsedMovieInfo>(i => i.MovieTitle == "A Movie"), It.IsAny <string>(), null))
            .Returns(new MappingResult {
                RemoteMovie = remoteEpisode
            });

            ParseMovieTitle();

            var client = new DownloadClientDefinition()
            {
                Id       = 1,
                Protocol = DownloadProtocol.Torrent
            };

            var item = new DownloadClientItem()
            {
                Title      = "A Movie 1998",
                DownloadId = "35238",
            };

            var trackedDownload = Subject.TrackDownload(client, item);

            trackedDownload.Should().NotBeNull();
            trackedDownload.RemoteMovie.Should().NotBeNull();
            trackedDownload.RemoteMovie.Movie.Should().NotBeNull();
            trackedDownload.RemoteMovie.Movie.Id.Should().Be(3);
        }
コード例 #6
0
        public void should_unmap_tracked_download_if_book_deleted()
        {
            GivenDownloadHistory();

            var remoteBook = new RemoteBook
            {
                Author = new Author()
                {
                    Id = 5
                },
                Books = new List <Book> {
                    new Book {
                        Id = 4
                    }
                },
                ParsedBookInfo = new ParsedBookInfo()
                {
                    BookTitle  = "Audio Book",
                    AuthorName = "Audio Author"
                }
            };

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.Is <ParsedBookInfo>(i => i.BookTitle == "Audio Book" && i.AuthorName == "Audio Author"), It.IsAny <int>(), It.IsAny <IEnumerable <int> >()))
            .Returns(remoteBook);

            var client = new DownloadClientDefinition()
            {
                Id       = 1,
                Protocol = DownloadProtocol.Torrent
            };

            var item = new DownloadClientItem()
            {
                Title              = "Audio Author - Audio Book [2018 - FLAC]",
                DownloadId         = "35238",
                DownloadClientInfo = new DownloadClientItemClientInfo
                {
                    Protocol = client.Protocol,
                    Id       = client.Id,
                    Name     = client.Name
                }
            };

            // get a tracked download in place
            var trackedDownload = Subject.TrackDownload(client, item);

            Subject.GetTrackedDownloads().Should().HaveCount(1);

            // simulate deletion - book no longer maps
            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.Is <ParsedBookInfo>(i => i.BookTitle == "Audio Book" && i.AuthorName == "Audio Author"), It.IsAny <int>(), It.IsAny <IEnumerable <int> >()))
            .Returns(default(RemoteBook));

            // handle deletion event
            Subject.Handle(new BookDeletedEvent(remoteBook.Books.First(), false, false));

            // verify download has null remote book
            var trackedDownloads = Subject.GetTrackedDownloads();

            trackedDownloads.Should().HaveCount(1);
            trackedDownloads.First().RemoteBook.Should().BeNull();
        }
コード例 #7
0
        public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem)
        {
            var existingItem = Find(downloadItem.DownloadId);

            if (existingItem != null && existingItem.State != TrackedDownloadStage.Downloading)
            {
                existingItem.DownloadItem = downloadItem;
                return existingItem;
            }

            var trackedDownload = new TrackedDownload
            {
                DownloadClient = downloadClient.Id,
                DownloadItem = downloadItem,
                Protocol = downloadClient.Protocol
            };

            try
            {
                var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title);
                var historyItems = _historyService.FindByDownloadId(downloadItem.DownloadId);

                if (parsedEpisodeInfo != null)
                {
                    trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0);
                }

                if (historyItems.Any())
                {
                    var firstHistoryItem = historyItems.OrderByDescending(h => h.Date).First();
                    trackedDownload.State = GetStateFromHistory(firstHistoryItem.EventType);

                    if (parsedEpisodeInfo == null ||
                        trackedDownload.RemoteEpisode == null ||
                        trackedDownload.RemoteEpisode.Series == null ||
                        trackedDownload.RemoteEpisode.Episodes.Empty())
                    {
                        // Try parsing the original source title and if that fails, try parsing it as a special
                        // TODO: Pass the TVDB ID and TVRage IDs in as well so we have a better chance for finding the item
                        parsedEpisodeInfo = Parser.Parser.ParseTitle(firstHistoryItem.SourceTitle) ?? _parsingService.ParseSpecialEpisodeTitle(firstHistoryItem.SourceTitle, 0, 0);

                        if (parsedEpisodeInfo != null)
                        {
                            trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, firstHistoryItem.SeriesId, historyItems.Where(v => v.EventType == HistoryEventType.Grabbed).Select(h => h.EpisodeId).Distinct());
                        }
                    }
                }

                if (trackedDownload.RemoteEpisode == null)
                {
                    return null;
                }
            }
            catch (Exception e)
            {
                _logger.Debug(e, "Failed to find episode for " + downloadItem.Title);
                return null;
            }

            _cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload);
            return trackedDownload;
        }
コード例 #8
0
        public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem)
        {
            var existingItem = Find(downloadItem.DownloadId);

            if (existingItem != null && existingItem.State != TrackedDownloadState.Downloading)
            {
                LogItemChange(existingItem, existingItem.DownloadItem, downloadItem);

                existingItem.DownloadItem = downloadItem;
                existingItem.IsTrackable  = true;

                return(existingItem);
            }

            var trackedDownload = new TrackedDownload
            {
                DownloadClient = downloadClient.Id,
                DownloadItem   = downloadItem,
                Protocol       = downloadClient.Protocol,
                IsTrackable    = true
            };

            try
            {
                var historyItems = _historyService.FindByDownloadId(downloadItem.DownloadId)
                                   .OrderByDescending(h => h.Date)
                                   .ToList();
                var grabbedHistoryItem = historyItems.FirstOrDefault(h => h.EventType == MovieHistoryEventType.Grabbed);

                //TODO: Create release info from history and use that here, so we don't loose indexer flags!
                var parsedMovieInfo = _parsingService.ParseMovieInfo(trackedDownload.DownloadItem.Title, new List <object> {
                    grabbedHistoryItem
                });

                if (parsedMovieInfo != null)
                {
                    trackedDownload.RemoteMovie = _parsingService.Map(parsedMovieInfo, "", null).RemoteMovie;
                }

                var downloadHistory = _downloadHistoryService.GetLatestDownloadHistoryItem(downloadItem.DownloadId);

                if (downloadHistory != null)
                {
                    var state = GetStateFromHistory(downloadHistory.EventType);
                    trackedDownload.State = state;
                }

                if (historyItems.Any())
                {
                    var firstHistoryItem = historyItems.FirstOrDefault();
                    var grabbedEvent     = historyItems.FirstOrDefault(v => v.EventType == MovieHistoryEventType.Grabbed);

                    trackedDownload.Indexer = grabbedEvent?.Data["indexer"];

                    if (parsedMovieInfo == null ||
                        trackedDownload.RemoteMovie == null ||
                        trackedDownload.RemoteMovie.Movie == null)
                    {
                        parsedMovieInfo = _parsingService.ParseMovieInfo(firstHistoryItem.SourceTitle, new List <object> {
                            grabbedHistoryItem
                        });

                        if (parsedMovieInfo != null)
                        {
                            trackedDownload.RemoteMovie = _parsingService.Map(parsedMovieInfo, "", null).RemoteMovie;
                        }
                    }
                }

                // Calculate custom formats
                if (trackedDownload.RemoteMovie != null)
                {
                    trackedDownload.RemoteMovie.CustomFormats = _formatCalculator.ParseCustomFormat(parsedMovieInfo);
                }

                // Track it so it can be displayed in the queue even though we can't determine which movie it is for
                if (trackedDownload.RemoteMovie == null)
                {
                    _logger.Trace("No Movie found for download '{0}'", trackedDownload.DownloadItem.Title);
                }
            }
            catch (Exception e)
            {
                _logger.Debug(e, "Failed to find movie for " + downloadItem.Title);
                return(null);
            }

            LogItemChange(trackedDownload, existingItem?.DownloadItem, trackedDownload.DownloadItem);

            _cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload);
            return(trackedDownload);
        }
コード例 #9
0
        public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem)
        {
            var existingItem = Find(downloadItem.DownloadId);

            if (existingItem != null && existingItem.State != TrackedDownloadState.Downloading)
            {
                LogItemChange(existingItem, existingItem.DownloadItem, downloadItem);

                existingItem.DownloadItem = downloadItem;
                existingItem.IsTrackable  = true;

                return(existingItem);
            }

            var trackedDownload = new TrackedDownload
            {
                DownloadClient = downloadClient.Id,
                DownloadItem   = downloadItem,
                Protocol       = downloadClient.Protocol,
                IsTrackable    = true
            };

            try
            {
                var parsedBookInfo = Parser.Parser.ParseBookTitle(trackedDownload.DownloadItem.Title);
                var historyItems   = _historyService.FindByDownloadId(downloadItem.DownloadId)
                                     .OrderByDescending(h => h.Date)
                                     .ToList();

                if (parsedBookInfo != null)
                {
                    trackedDownload.RemoteBook = _parsingService.Map(parsedBookInfo);
                }

                var downloadHistory = _downloadHistoryService.GetLatestDownloadHistoryItem(downloadItem.DownloadId);

                if (downloadHistory != null)
                {
                    var state = GetStateFromHistory(downloadHistory.EventType);
                    trackedDownload.State = state;

                    if (downloadHistory.EventType == DownloadHistoryEventType.DownloadImportIncomplete)
                    {
                        var messages = Json.Deserialize <List <TrackedDownloadStatusMessage> >(downloadHistory.Data["statusMessages"]).ToArray();
                        trackedDownload.Warn(messages);
                    }
                }

                if (historyItems.Any())
                {
                    var firstHistoryItem = historyItems.First();
                    var grabbedEvent     = historyItems.FirstOrDefault(v => v.EventType == EntityHistoryEventType.Grabbed);

                    trackedDownload.Indexer = grabbedEvent?.Data["indexer"];

                    if (parsedBookInfo == null ||
                        trackedDownload.RemoteBook == null ||
                        trackedDownload.RemoteBook.Author == null ||
                        trackedDownload.RemoteBook.Books.Empty())
                    {
                        // Try parsing the original source title and if that fails, try parsing it as a special
                        var historyAuthor = firstHistoryItem.Author;
                        var historyBooks  = new List <Book> {
                            firstHistoryItem.Book
                        };

                        parsedBookInfo = Parser.Parser.ParseBookTitle(firstHistoryItem.SourceTitle);

                        if (parsedBookInfo != null)
                        {
                            trackedDownload.RemoteBook = _parsingService.Map(parsedBookInfo,
                                                                             firstHistoryItem.AuthorId,
                                                                             historyItems.Where(v => v.EventType == EntityHistoryEventType.Grabbed).Select(h => h.BookId)
                                                                             .Distinct());
                        }
                        else
                        {
                            parsedBookInfo =
                                Parser.Parser.ParseBookTitleWithSearchCriteria(firstHistoryItem.SourceTitle,
                                                                               historyAuthor,
                                                                               historyBooks);

                            if (parsedBookInfo != null)
                            {
                                trackedDownload.RemoteBook = _parsingService.Map(parsedBookInfo,
                                                                                 firstHistoryItem.AuthorId,
                                                                                 historyItems.Where(v => v.EventType == EntityHistoryEventType.Grabbed).Select(h => h.BookId)
                                                                                 .Distinct());
                            }
                        }
                    }
                }

                // Track it so it can be displayed in the queue even though we can't determine which author it is for
                if (trackedDownload.RemoteBook == null)
                {
                    _logger.Trace("No Book found for download '{0}'", trackedDownload.DownloadItem.Title);
                }
            }
            catch (Exception e)
            {
                _logger.Debug(e, "Failed to find book for " + downloadItem.Title);
                return(null);
            }

            LogItemChange(trackedDownload, existingItem?.DownloadItem, trackedDownload.DownloadItem);

            _cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload);
            return(trackedDownload);
        }
コード例 #10
0
        public void should_not_throw_when_processing_deleted_series()
        {
            GivenDownloadHistory();

            var remoteEpisode = new RemoteEpisode
            {
                Series = new Series()
                {
                    Id = 5
                },
                Episodes = new List <Episode> {
                    new Episode {
                        Id = 4
                    }
                },
                ParsedEpisodeInfo = new ParsedEpisodeInfo()
                {
                    SeriesTitle    = "TV Series",
                    SeasonNumber   = 1,
                    EpisodeNumbers = new[] { 1 }
                },
                MappedSeasonNumber = 0
            };

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.IsAny <ParsedEpisodeInfo>(), It.IsAny <int>(), It.IsAny <int>(), null))
            .Returns(default(RemoteEpisode));

            Mocker.GetMock <IHistoryService>()
            .Setup(s => s.FindByDownloadId(It.IsAny <string>()))
            .Returns(new List <EpisodeHistory>());


            var client = new DownloadClientDefinition()
            {
                Id       = 1,
                Protocol = DownloadProtocol.Torrent
            };

            var item = new DownloadClientItem()
            {
                Title              = "TV Series - S01E01",
                DownloadId         = "12345",
                DownloadClientInfo = new DownloadClientItemClientInfo
                {
                    Id       = 1,
                    Type     = "Blackhole",
                    Name     = "Blackhole Client",
                    Protocol = DownloadProtocol.Torrent
                }
            };

            Subject.TrackDownload(client, item);
            Subject.GetTrackedDownloads().Should().HaveCount(1);

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.IsAny <ParsedEpisodeInfo>(), It.IsAny <int>(), It.IsAny <int>(), null))
            .Returns(default(RemoteEpisode));

            Subject.Handle(new SeriesDeletedEvent(remoteEpisode.Series, true, true));

            var trackedDownloads = Subject.GetTrackedDownloads();

            trackedDownloads.Should().HaveCount(1);
            trackedDownloads.First().RemoteEpisode.Should().BeNull();
        }
コード例 #11
0
        public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem)
        {
            var existingItem = Find(downloadItem.DownloadId);

            if (existingItem != null && existingItem.State != TrackedDownloadState.Downloading)
            {
                LogItemChange(existingItem, existingItem.DownloadItem, downloadItem);

                existingItem.DownloadItem = downloadItem;
                existingItem.IsTrackable  = true;

                return(existingItem);
            }

            var trackedDownload = new TrackedDownload
            {
                DownloadClient = downloadClient.Id,
                DownloadItem   = downloadItem,
                Protocol       = downloadClient.Protocol,
                IsTrackable    = true
            };

            try
            {
                var parsedAlbumInfo = Parser.Parser.ParseAlbumTitle(trackedDownload.DownloadItem.Title);
                var historyItems    = _historyService.FindByDownloadId(downloadItem.DownloadId)
                                      .OrderByDescending(h => h.Date)
                                      .ToList();

                if (parsedAlbumInfo != null)
                {
                    trackedDownload.RemoteAlbum = _parsingService.Map(parsedAlbumInfo);
                }

                if (historyItems.Any())
                {
                    var firstHistoryItem = historyItems.First();
                    var state            = GetStateFromHistory(firstHistoryItem);

                    // One potential issue here is if the latest is imported, but other episodes are ignored or never imported.
                    // It's unlikely that will happen, but could happen if additional episodes are added to season after it's already imported.
                    if (state == TrackedDownloadState.Imported)
                    {
                        var allImported = _trackedDownloadAlreadyImported.IsImported(trackedDownload, historyItems);

                        trackedDownload.State = allImported ? TrackedDownloadState.Imported : TrackedDownloadState.Downloading;
                    }
                    else
                    {
                        trackedDownload.State = state;
                    }

                    if (firstHistoryItem.EventType == HistoryEventType.AlbumImportIncomplete)
                    {
                        var messages = Json.Deserialize <List <TrackedDownloadStatusMessage> >(firstHistoryItem?.Data["statusMessages"]).ToArray();
                        trackedDownload.Warn(messages);
                    }

                    var grabbedEvent = historyItems.FirstOrDefault(v => v.EventType == HistoryEventType.Grabbed);
                    trackedDownload.Indexer = grabbedEvent?.Data["indexer"];

                    if (parsedAlbumInfo == null ||
                        trackedDownload.RemoteAlbum == null ||
                        trackedDownload.RemoteAlbum.Artist == null ||
                        trackedDownload.RemoteAlbum.Albums.Empty())
                    {
                        // Try parsing the original source title and if that fails, try parsing it as a special
                        // TODO: Pass the TVDB ID and TVRage IDs in as well so we have a better chance for finding the item
                        var historyArtist = firstHistoryItem.Artist;
                        var historyAlbums = new List <Album> {
                            firstHistoryItem.Album
                        };

                        parsedAlbumInfo = Parser.Parser.ParseAlbumTitle(firstHistoryItem.SourceTitle);

                        if (parsedAlbumInfo != null)
                        {
                            trackedDownload.RemoteAlbum = _parsingService.Map(parsedAlbumInfo,
                                                                              firstHistoryItem.ArtistId,
                                                                              historyItems.Where(v => v.EventType == HistoryEventType.Grabbed).Select(h => h.AlbumId)
                                                                              .Distinct());
                        }
                        else
                        {
                            parsedAlbumInfo =
                                Parser.Parser.ParseAlbumTitleWithSearchCriteria(firstHistoryItem.SourceTitle,
                                                                                historyArtist,
                                                                                historyAlbums);

                            if (parsedAlbumInfo != null)
                            {
                                trackedDownload.RemoteAlbum = _parsingService.Map(parsedAlbumInfo,
                                                                                  firstHistoryItem.ArtistId,
                                                                                  historyItems.Where(v => v.EventType == HistoryEventType.Grabbed).Select(h => h.AlbumId)
                                                                                  .Distinct());
                            }
                        }
                    }
                }

                // Track it so it can be displayed in the queue even though we can't determine which artist it is for
                if (trackedDownload.RemoteAlbum == null)
                {
                    _logger.Trace("No Album found for download '{0}'", trackedDownload.DownloadItem.Title);
                    trackedDownload.Warn("No Album found for download '{0}'", trackedDownload.DownloadItem.Title);
                }
            }
            catch (Exception e)
            {
                _logger.Debug(e, "Failed to find album for " + downloadItem.Title);
                return(null);
            }

            LogItemChange(trackedDownload, existingItem?.DownloadItem, trackedDownload.DownloadItem);

            _cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload);
            return(trackedDownload);
        }
コード例 #12
0
        public void should_not_throw_when_processing_deleted_series()
        {
            GivenDownloadHistory();

            var remoteEpisode = new RemoteBook
            {
                Author = new Author()
                {
                    Id = 5
                },
                Books = new List <Book> {
                    new Book {
                        Id = 4
                    }
                },
                ParsedBookInfo = new ParsedBookInfo()
                {
                    BookTitle = "TV Series",
                }
            };

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.IsAny <ParsedBookInfo>(), It.IsAny <int>(), It.IsAny <List <int> >()))
            .Returns(default(RemoteBook));

            Mocker.GetMock <IHistoryService>()
            .Setup(s => s.FindByDownloadId(It.IsAny <string>()))
            .Returns(new List <EntityHistory>());

            var client = new DownloadClientDefinition()
            {
                Id       = 1,
                Protocol = DownloadProtocol.Torrent
            };

            var item = new DownloadClientItem()
            {
                Title              = "TV Series - S01E01",
                DownloadId         = "12345",
                DownloadClientInfo = new DownloadClientItemClientInfo
                {
                    Id       = 1,
                    Type     = "Blackhole",
                    Name     = "Blackhole Client",
                    Protocol = DownloadProtocol.Torrent
                }
            };

            Subject.TrackDownload(client, item);
            Subject.GetTrackedDownloads().Should().HaveCount(1);

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.IsAny <ParsedBookInfo>(), It.IsAny <int>(), It.IsAny <List <int> >()))
            .Returns(default(RemoteBook));

            Subject.Handle(new AuthorDeletedEvent(remoteEpisode.Author, true, true));

            var trackedDownloads = Subject.GetTrackedDownloads();

            trackedDownloads.Should().HaveCount(1);
            trackedDownloads.First().RemoteBook.Should().BeNull();
        }
コード例 #13
0
        public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem)
        {
            var existingItem = Find(downloadItem.DownloadId);

            if (existingItem != null && existingItem.State != TrackedDownloadState.Downloading)
            {
                LogItemChange(existingItem, existingItem.DownloadItem, downloadItem);

                existingItem.DownloadItem = downloadItem;
                existingItem.IsTrackable  = true;

                return(existingItem);
            }

            var trackedDownload = new TrackedDownload
            {
                DownloadClient = downloadClient.Id,
                DownloadItem   = downloadItem,
                Protocol       = downloadClient.Protocol,
                IsTrackable    = true
            };

            try
            {
                var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title);
                var historyItems      = _historyService.FindByDownloadId(downloadItem.DownloadId)
                                        .OrderByDescending(h => h.Date)
                                        .ToList();

                if (parsedEpisodeInfo != null)
                {
                    trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0);
                }

                var downloadHistory = _downloadHistoryService.GetLatestDownloadHistoryItem(downloadItem.DownloadId);

                if (downloadHistory != null)
                {
                    var state = GetStateFromHistory(downloadHistory.EventType);
                    trackedDownload.State = state;
                }

                if (historyItems.Any())
                {
                    var firstHistoryItem = historyItems.First();
                    var grabbedEvent     = historyItems.FirstOrDefault(v => v.EventType == EpisodeHistoryEventType.Grabbed);

                    trackedDownload.Indexer = grabbedEvent?.Data["indexer"];

                    if (parsedEpisodeInfo == null ||
                        trackedDownload.RemoteEpisode == null ||
                        trackedDownload.RemoteEpisode.Series == null ||
                        trackedDownload.RemoteEpisode.Episodes.Empty())
                    {
                        // Try parsing the original source title and if that fails, try parsing it as a special
                        // TODO: Pass the TVDB ID and TVRage IDs in as well so we have a better chance for finding the item
                        parsedEpisodeInfo = Parser.Parser.ParseTitle(firstHistoryItem.SourceTitle) ?? _parsingService.ParseSpecialEpisodeTitle(parsedEpisodeInfo, firstHistoryItem.SourceTitle, 0, 0);

                        if (parsedEpisodeInfo != null)
                        {
                            trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, firstHistoryItem.SeriesId, historyItems.Where(v => v.EventType == EpisodeHistoryEventType.Grabbed).Select(h => h.EpisodeId).Distinct());
                        }
                    }
                }

                // Track it so it can be displayed in the queue even though we can't determine which series it is for
                if (trackedDownload.RemoteEpisode == null)
                {
                    _logger.Trace("No Episode found for download '{0}'", trackedDownload.DownloadItem.Title);
                }
            }
            catch (Exception e)
            {
                _logger.Debug(e, "Failed to find episode for " + downloadItem.Title);
                return(null);
            }

            LogItemChange(trackedDownload, existingItem?.DownloadItem, trackedDownload.DownloadItem);

            _cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload);
            return(trackedDownload);
        }
コード例 #14
0
        public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem)
        {
            if (downloadItem.DownloadId.IsNullOrWhiteSpace())
            {
                _logger.Warn("The following download client item ({0}) has no download hash (id), so it cannot be tracked: {1}",
                             downloadClient.Name, downloadItem.Title);
                return(null);
            }

            if (downloadItem.Title.IsNullOrWhiteSpace())
            {
                _logger.Warn("The following download client item ({0}) has no title so it cannot be tracked: {1}",
                             downloadClient.Name, downloadItem.Title);
                return(null);
            }

            var existingItem = Find(downloadItem.DownloadId);

            if (existingItem != null && existingItem.State != TrackedDownloadStage.Downloading)
            {
                existingItem.DownloadItem = downloadItem;
                return(existingItem);
            }

            var trackedDownload = new TrackedDownload
            {
                DownloadClient = downloadClient.Id,
                DownloadItem   = downloadItem,
                Protocol       = downloadClient.Protocol
            };

            try
            {
                var historyItems       = _historyService.FindByDownloadId(downloadItem.DownloadId);
                var grabbedHistoryItem = historyItems.OrderByDescending(h => h.Date).FirstOrDefault(h => h.EventType == HistoryEventType.Grabbed);
                var firstHistoryItem   = historyItems.OrderByDescending(h => h.Date).FirstOrDefault();
                //TODO: Create release info from history and use that here, so we don't loose indexer flags!
                var parsedMovieInfo = _parsingService.ParseMovieInfo(trackedDownload.DownloadItem.Title, new List <object> {
                    grabbedHistoryItem
                });

                if (parsedMovieInfo != null)
                {
                    trackedDownload.RemoteMovie = _parsingService.Map(parsedMovieInfo, "", null).RemoteMovie;
                }

                if (firstHistoryItem != null)
                {
                    trackedDownload.State = GetStateFromHistory(firstHistoryItem.EventType);

                    if (parsedMovieInfo == null ||
                        trackedDownload.RemoteMovie == null ||
                        trackedDownload.RemoteMovie.Movie == null)
                    {
                        parsedMovieInfo = _parsingService.ParseMovieInfo(firstHistoryItem.SourceTitle, new List <object> {
                            grabbedHistoryItem
                        });

                        if (parsedMovieInfo != null)
                        {
                            trackedDownload.RemoteMovie = _parsingService.Map(parsedMovieInfo, "", null).RemoteMovie;
                        }
                    }
                }

                if (trackedDownload.RemoteMovie == null)
                {
                    return(null);
                }
            }
            catch (Exception e)
            {
                _logger.Debug(e, "Failed to find movie for " + downloadItem.Title);
                return(null);
            }

            _cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload);
            return(trackedDownload);
        }
コード例 #15
0
        public void should_unmap_tracked_download_if_album_deleted()
        {
            GivenDownloadHistory();

            var remoteAlbum = new RemoteAlbum
            {
                Artist = new Artist()
                {
                    Id = 5
                },
                Albums = new List <Album> {
                    new Album {
                        Id = 4
                    }
                },
                ParsedAlbumInfo = new ParsedAlbumInfo()
                {
                    AlbumTitle = "Audio Album",
                    ArtistName = "Audio Artist"
                }
            };

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.Is <ParsedAlbumInfo>(i => i.AlbumTitle == "Audio Album" && i.ArtistName == "Audio Artist"), It.IsAny <int>(), It.IsAny <IEnumerable <int> >()))
            .Returns(remoteAlbum);

            var client = new DownloadClientDefinition()
            {
                Id       = 1,
                Protocol = DownloadProtocol.Torrent
            };

            var item = new DownloadClientItem()
            {
                Title              = "Audio Artist - Audio Album [2018 - FLAC]",
                DownloadId         = "35238",
                DownloadClientInfo = new DownloadClientItemClientInfo
                {
                    Protocol = client.Protocol,
                    Id       = client.Id,
                    Name     = client.Name
                }
            };

            // get a tracked download in place
            var trackedDownload = Subject.TrackDownload(client, item);

            Subject.GetTrackedDownloads().Should().HaveCount(1);

            // simulate deletion - album no longer maps
            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.Is <ParsedAlbumInfo>(i => i.AlbumTitle == "Audio Album" && i.ArtistName == "Audio Artist"), It.IsAny <int>(), It.IsAny <IEnumerable <int> >()))
            .Returns(default(RemoteAlbum));

            // handle deletion event
            Subject.Handle(new AlbumDeletedEvent(remoteAlbum.Albums.First(), false, false));

            // verify download has null remote album
            var trackedDownloads = Subject.GetTrackedDownloads();

            trackedDownloads.Should().HaveCount(1);
            trackedDownloads.First().RemoteAlbum.Should().BeNull();
        }
コード例 #16
0
        public void should_unmap_tracked_download_if_movie_deleted()
        {
            GivenDownloadHistory();

            var remoteMovie = new RemoteMovie
            {
                Movie = new Movie()
                {
                    Id = 3
                },

                ParsedMovieInfo = new ParsedMovieInfo()
                {
                    MovieTitles = { "A Movie" },
                    Year        = 1998
                }
            };

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.IsAny <ParsedMovieInfo>(), It.IsAny <string>(), null))
            .Returns(new MappingResult {
                RemoteMovie = remoteMovie
            });

            Mocker.GetMock <IHistoryService>()
            .Setup(s => s.FindByDownloadId(It.IsAny <string>()))
            .Returns(new List <MovieHistory>());

            ParseMovieTitle();

            var client = new DownloadClientDefinition()
            {
                Id       = 1,
                Protocol = DownloadProtocol.Torrent
            };

            var item = new DownloadClientItem()
            {
                Title              = "A Movie 1998",
                DownloadId         = "12345",
                DownloadClientInfo = new DownloadClientItemClientInfo
                {
                    Id       = 1,
                    Type     = "Blackhole",
                    Name     = "Blackhole Client",
                    Protocol = DownloadProtocol.Torrent
                }
            };

            Subject.TrackDownload(client, item);
            Subject.GetTrackedDownloads().Should().HaveCount(1);

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.IsAny <ParsedMovieInfo>(), It.IsAny <string>(), null))
            .Returns(new MappingResult {
                MappingResultType = MappingResultType.Unknown
            });

            Subject.Handle(new MoviesDeletedEvent(new List <Movie> {
                remoteMovie.Movie
            }, false, false));

            var trackedDownloads = Subject.GetTrackedDownloads();

            trackedDownloads.Should().HaveCount(1);
            trackedDownloads.First().RemoteMovie.Should().BeNull();
        }
コード例 #17
0
        public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem)
        {
            var existingItem = Find(downloadItem.DownloadId);

            if (existingItem != null && existingItem.State != TrackedDownloadStage.Downloading)
            {
                LogItemChange(existingItem, existingItem.DownloadItem, downloadItem);

                existingItem.DownloadItem = downloadItem;
                return(existingItem);
            }

            var trackedDownload = new TrackedDownload
            {
                DownloadClient = downloadClient.Id,
                DownloadItem   = downloadItem,
                Protocol       = downloadClient.Protocol
            };

            try
            {
                var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title);
                var historyItems      = _historyService.FindByDownloadId(downloadItem.DownloadId);

                if (parsedEpisodeInfo != null)
                {
                    trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0);
                }

                if (historyItems.Any())
                {
                    var firstHistoryItem = historyItems.OrderByDescending(h => h.Date).First();
                    trackedDownload.State = GetStateFromHistory(firstHistoryItem.EventType);

                    if (parsedEpisodeInfo == null ||
                        trackedDownload.RemoteEpisode == null ||
                        trackedDownload.RemoteEpisode.Series == null ||
                        trackedDownload.RemoteEpisode.Episodes.Empty())
                    {
                        // Try parsing the original source title and if that fails, try parsing it as a special
                        // TODO: Pass the TVDB ID and TVRage IDs in as well so we have a better chance for finding the item
                        parsedEpisodeInfo = Parser.Parser.ParseTitle(firstHistoryItem.SourceTitle) ?? _parsingService.ParseSpecialEpisodeTitle(parsedEpisodeInfo, firstHistoryItem.SourceTitle, 0, 0);

                        if (parsedEpisodeInfo != null)
                        {
                            trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, firstHistoryItem.SeriesId, historyItems.Where(v => v.EventType == HistoryEventType.Grabbed).Select(h => h.EpisodeId).Distinct());
                        }
                    }
                }

                if (trackedDownload.RemoteEpisode == null)
                {
                    _logger.Trace("No Episode found for download '{0}', not tracking.", trackedDownload.DownloadItem.Title);

                    return(null);
                }
            }
            catch (Exception e)
            {
                _logger.Debug(e, "Failed to find episode for " + downloadItem.Title);
                return(null);
            }

            LogItemChange(trackedDownload, existingItem?.DownloadItem, trackedDownload.DownloadItem);

            _cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload);
            return(trackedDownload);
        }
 public void Setup()
 {
     _downloadClient = Builder <DownloadClientDefinition> .CreateNew()
                       .With(c => c.Settings = new FloodSettings())
                       .BuildNew();
 }
コード例 #19
0
        public void should_parse_as_special_when_source_title_parsing_fails()
        {
            var remoteEpisode = new RemoteEpisode
            {
                Series = new Series()
                {
                    Id = 5
                },
                Episodes = new List <Episode> {
                    new Episode {
                        Id = 4
                    }
                },
                ParsedEpisodeInfo = new ParsedEpisodeInfo()
                {
                    SeriesTitle    = "TV Series",
                    SeasonNumber   = 0,
                    EpisodeNumbers = new [] { 1 }
                }
            };

            Mocker.GetMock <IHistoryService>()
            .Setup(s => s.FindByDownloadId(It.Is <string>(sr => sr == "35238")))
            .Returns(new List <History.History>()
            {
                new History.History()
                {
                    DownloadId  = "35238",
                    SourceTitle = "TV Series Special",
                    SeriesId    = 5,
                    EpisodeId   = 4
                }
            });

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.Map(It.Is <ParsedEpisodeInfo>(i => i.SeasonNumber == 0 && i.SeriesTitle == "TV Series"), It.IsAny <int>(), It.IsAny <IEnumerable <int> >()))
            .Returns(remoteEpisode);

            Mocker.GetMock <IParsingService>()
            .Setup(s => s.ParseSpecialEpisodeTitle(It.IsAny <ParsedEpisodeInfo>(), It.IsAny <string>(), It.IsAny <int>(), It.IsAny <int>(), null))
            .Returns(remoteEpisode.ParsedEpisodeInfo);

            var client = new DownloadClientDefinition()
            {
                Id       = 1,
                Protocol = DownloadProtocol.Torrent
            };

            var item = new DownloadClientItem()
            {
                Title      = "The torrent release folder",
                DownloadId = "35238",
            };

            var trackedDownload = Subject.TrackDownload(client, item);

            trackedDownload.Should().NotBeNull();
            trackedDownload.RemoteEpisode.Should().NotBeNull();
            trackedDownload.RemoteEpisode.Series.Should().NotBeNull();
            trackedDownload.RemoteEpisode.Series.Id.Should().Be(5);
            trackedDownload.RemoteEpisode.Episodes.First().Id.Should().Be(4);
            trackedDownload.RemoteEpisode.ParsedEpisodeInfo.SeasonNumber.Should().Be(0);
        }
コード例 #20
0
        public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem)
        {
            var existingItem = Find(downloadItem.DownloadId);

            if (existingItem != null && existingItem.State != TrackedDownloadState.Downloading)
            {
                LogItemChange(existingItem, existingItem.DownloadItem, downloadItem);

                existingItem.DownloadItem = downloadItem;
                existingItem.IsTrackable  = true;

                return(existingItem);
            }

            var trackedDownload = new TrackedDownload
            {
                DownloadClient = downloadClient.Id,
                DownloadItem   = downloadItem,
                Protocol       = downloadClient.Protocol,
                IsTrackable    = true
            };

            try
            {
                var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title);
                var historyItems      = _historyService.FindByDownloadId(downloadItem.DownloadId)
                                        .OrderByDescending(h => h.Date)
                                        .ToList();

                if (parsedEpisodeInfo != null)
                {
                    trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0);
                }

                if (historyItems.Any())
                {
                    var firstHistoryItem = historyItems.First();
                    var state            = GetStateFromHistory(firstHistoryItem.EventType);

                    trackedDownload.State = state;

                    // TODO: Restore check to confirm all files were imported
                    // This will treat partially imported downloads as imported (as it was before), which means a partially imported download after a
                    // restart will get marked as imported without importing the restart of the files.

                    // One potential issue here is if the latest is imported, but other episodes are ignored or never imported.
                    // It's unlikely that will happen, but could happen if additional episodes are added to season after it's already imported.

//                    if (state == TrackedDownloadState.Imported)
//                    {
//                        trackedDownload.State = TrackedDownloadState.Imported;
//
//                        var allImported = _trackedDownloadAlreadyImported.IsImported(trackedDownload, historyItems);
//
//                        trackedDownload.State = allImported ? TrackedDownloadState.Imported : TrackedDownloadState.Downloading;
//                    }
//                    else
//                    {
//                        trackedDownload.State = state;
//                    }

                    var grabbedEvent = historyItems.FirstOrDefault(v => v.EventType == HistoryEventType.Grabbed);
                    trackedDownload.Indexer = grabbedEvent?.Data["indexer"];

                    if (parsedEpisodeInfo == null ||
                        trackedDownload.RemoteEpisode == null ||
                        trackedDownload.RemoteEpisode.Series == null ||
                        trackedDownload.RemoteEpisode.Episodes.Empty())
                    {
                        // Try parsing the original source title and if that fails, try parsing it as a special
                        // TODO: Pass the TVDB ID and TVRage IDs in as well so we have a better chance for finding the item
                        parsedEpisodeInfo = Parser.Parser.ParseTitle(firstHistoryItem.SourceTitle) ?? _parsingService.ParseSpecialEpisodeTitle(parsedEpisodeInfo, firstHistoryItem.SourceTitle, 0, 0);

                        if (parsedEpisodeInfo != null)
                        {
                            trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, firstHistoryItem.SeriesId, historyItems.Where(v => v.EventType == HistoryEventType.Grabbed).Select(h => h.EpisodeId).Distinct());
                        }
                    }
                }

                // Track it so it can be displayed in the queue even though we can't determine which serires it is for
                if (trackedDownload.RemoteEpisode == null)
                {
                    _logger.Trace("No Episode found for download '{0}'", trackedDownload.DownloadItem.Title);
                }
            }
            catch (Exception e)
            {
                _logger.Debug(e, "Failed to find episode for " + downloadItem.Title);
                return(null);
            }

            LogItemChange(trackedDownload, existingItem?.DownloadItem, trackedDownload.DownloadItem);

            _cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload);
            return(trackedDownload);
        }