private void AuthenticateClient(HttpRequestBuilder requestBuilder, QBittorrentSettings settings, bool reauthenticate = false)
        {
            if (settings.Username.IsNullOrWhiteSpace() || settings.Password.IsNullOrWhiteSpace())
            {
                if (reauthenticate)
                {
                    throw new DownloadClientAuthenticationException("Failed to authenticate with qBittorrent.");
                }

                return;
            }

            var authKey = string.Format("{0}:{1}", requestBuilder.BaseUrl, settings.Password);

            var cookies = _authCookieCache.Find(authKey);

            if (cookies == null || reauthenticate)
            {
                _authCookieCache.Remove(authKey);

                var authLoginRequest = BuildRequest(settings).Resource("/api/v2/auth/login")
                                       .Post()
                                       .AddFormParameter("username", settings.Username ?? string.Empty)
                                       .AddFormParameter("password", settings.Password ?? string.Empty)
                                       .Build();

                HttpResponse response;
                try
                {
                    response = _httpClient.Execute(authLoginRequest);
                }
                catch (HttpException ex)
                {
                    _logger.Debug("qbitTorrent authentication failed.");
                    if (ex.Response.StatusCode == HttpStatusCode.Forbidden)
                    {
                        throw new DownloadClientAuthenticationException("Failed to authenticate with qBittorrent.", ex);
                    }

                    throw new DownloadClientException("Failed to connect to qBittorrent, please check your settings.", ex);
                }
                catch (WebException ex)
                {
                    throw new DownloadClientUnavailableException("Failed to connect to qBittorrent, please check your settings.", ex);
                }

                // returns "Fails." on bad login
                if (response.Content != "Ok.")
                {
                    _logger.Debug("qbitTorrent authentication failed.");
                    throw new DownloadClientAuthenticationException("Failed to authenticate with qBittorrent.");
                }

                _logger.Debug("qBittorrent authentication succeeded.");

                cookies = response.GetCookies();

                _authCookieCache.Set(authKey, cookies);
            }

            requestBuilder.SetCookies(cookies);
        }
Beispiel #2
0
 public TrackedDownload Find(string downloadId)
 {
     return(_cache.Find(downloadId));
 }
Beispiel #3
0
        protected bool HasReachedSeedingTimeLimit(QBittorrentTorrent torrent, QBittorrentPreferences config)
        {
            long seedingTimeLimit;

            if (torrent.SeedingTimeLimit >= 0)
            {
                seedingTimeLimit = torrent.SeedingTimeLimit;
            }
            else if (torrent.SeedingTimeLimit == -2 && config.MaxSeedingTimeEnabled)
            {
                seedingTimeLimit = config.MaxSeedingTime;
            }
            else
            {
                return(false);
            }

            if (torrent.SeedingTime.HasValue)
            {
                // SeedingTime can't be available here, but use it if the api starts to provide it.
                return(torrent.SeedingTime.Value >= seedingTimeLimit);
            }

            var cacheKey         = Settings.Host + Settings.Port + torrent.Hash;
            var cacheSeedingTime = _seedingTimeCache.Find(cacheKey);

            if (cacheSeedingTime != null)
            {
                var togo    = seedingTimeLimit - cacheSeedingTime.SeedingTime;
                var elapsed = (DateTime.UtcNow - cacheSeedingTime.LastFetched).TotalSeconds;

                if (togo <= 0)
                {
                    // Already reached the limit, keep the cache alive
                    _seedingTimeCache.Set(cacheKey, cacheSeedingTime, TimeSpan.FromMinutes(5));
                    return(true);
                }
                else if (togo > elapsed)
                {
                    // SeedingTime cannot have reached the required value since the last check, preserve the cache
                    _seedingTimeCache.Set(cacheKey, cacheSeedingTime, TimeSpan.FromMinutes(5));
                    return(false);
                }
            }

            FetchTorrentDetails(torrent);

            cacheSeedingTime = new SeedingTimeCacheEntry
            {
                LastFetched = DateTime.UtcNow,
                SeedingTime = torrent.SeedingTime.Value
            };

            _seedingTimeCache.Set(cacheKey, cacheSeedingTime, TimeSpan.FromMinutes(5));

            if (cacheSeedingTime.SeedingTime >= seedingTimeLimit)
            {
                // Reached the limit, keep the cache alive
                return(true);
            }

            return(false);
        }
Beispiel #4
0
 public Command GetById(int id)
 {
     return(_cache.Find(id.ToString()));
 }
        private Response Search()
        {
            if (Request.Query.Id == 0)
            {
                //Todo error handling
            }

            RootFolder rootFolder = _rootFolderService.Get(Request.Query.Id);

            int page     = Request.Query.page;
            int per_page = Request.Query.per_page;

            int min = (page - 1) * per_page;

            int max = page * per_page;

            var unmapped = rootFolder.UnmappedFolders.OrderBy(f => f.Name).ToList();

            int total_count = unmapped.Count;

            if (Request.Query.total_entries.HasValue)
            {
                total_count = Request.Query.total_entries;
            }

            max = total_count >= max ? max : total_count;

            var paged = unmapped.GetRange(min, max - min);

            var mapped = paged.Select(f =>
            {
                Core.Movies.Movie m = null;

                var mappedMovie = _mappedMovies.Find(f.Name);

                if (mappedMovie != null)
                {
                    return(mappedMovie);
                }

                var parsedTitle    = _parsingService.ParseMinimalPathMovieInfo(f.Name);
                parsedTitle.ImdbId = Parser.ParseImdbId(parsedTitle.SimpleReleaseTitle);
                if (parsedTitle == null)
                {
                    m = new Core.Movies.Movie
                    {
                        Title = f.Name.Replace(".", " ").Replace("-", " "),
                        Path  = f.Path,
                    };
                }
                else
                {
                    m = new Core.Movies.Movie
                    {
                        Title  = parsedTitle.MovieTitle,
                        Year   = parsedTitle.Year,
                        ImdbId = parsedTitle.ImdbId,
                        Path   = f.Path
                    };
                }

                var files = _diskScanService.GetVideoFiles(f.Path);

                var decisions = _importDecisionMaker.GetImportDecisions(files.ToList(), m, true);

                var decision = decisions.Where(d => d.Approved && !d.Rejections.Any()).FirstOrDefault();

                if (decision != null)
                {
                    var local = decision.LocalMovie;

                    m.MovieFile = new MovieFile
                    {
                        Path         = local.Path,
                        Edition      = local.ParsedMovieInfo.Edition,
                        Quality      = local.Quality,
                        MediaInfo    = local.MediaInfo,
                        ReleaseGroup = local.ParsedMovieInfo.ReleaseGroup,
                        RelativePath = f.Path.GetRelativePath(local.Path)
                    };
                }

                mappedMovie = _searchProxy.MapMovieToTmdbMovie(m);

                if (mappedMovie != null)
                {
                    mappedMovie.Monitored = true;

                    _mappedMovies.Set(f.Name, mappedMovie, TimeSpan.FromDays(2));

                    return(mappedMovie);
                }

                return(null);
            });

            return(new PagingResource <MovieResource>
            {
                Page = page,
                PageSize = per_page,
                SortDirection = SortDirection.Ascending,
                SortKey = Request.Query.sort_by,
                TotalRecords = total_count - mapped.Where(m => m == null).Count(),
                Records = MapToResource(mapped.Where(m => m != null)).ToList()
            }.AsResponse());
        }
        private ImportDecision GetDecision(string file, Movie movie, DownloadClientItem downloadClientItem, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName, bool shouldCheckQuality = false)
        {
            ImportDecision decision = null;

            try
            {
                ParsedMovieInfo modifiedFolderInfo = null;
                if (folderInfo != null)
                {
                    modifiedFolderInfo = folderInfo.JsonClone();
                    // We want the filename to be used for parsing quality, etc. even if we didn't get any movie info from there.
                    modifiedFolderInfo.SimpleReleaseTitle = Path.GetFileName(file);
                }

                var minimalInfo = _parsingService.ParseMinimalPathMovieInfo(file) ?? modifiedFolderInfo;

                LocalMovie localMovie = null;

                if (minimalInfo != null)
                {
                    //TODO: make it so media info doesn't ruin the import process of a new movie
                    var mediaInfo        = (_config.EnableMediaInfo || !movie.Path?.IsParentPath(file) == true) ? _videoFileInfoReader.GetMediaInfo(file) : null;
                    var size             = _diskProvider.GetFileSize(file);
                    var historyItems     = _historyService.FindByDownloadId(downloadClientItem?.DownloadId ?? "");
                    var firstHistoryItem = historyItems?.OrderByDescending(h => h.Date)?.FirstOrDefault();
                    var sizeMovie        = new LocalMovie();
                    sizeMovie.Size = size;
                    localMovie     = _parsingService.GetLocalMovie(file, minimalInfo, movie, new List <object> {
                        mediaInfo, firstHistoryItem, sizeMovie, folderInfo
                    }, sceneSource);
                    localMovie.Quality = GetQuality(folderInfo, localMovie.Quality, movie);
                    localMovie.Size    = size;

                    _logger.Debug("Size: {0}", localMovie.Size);

                    decision = GetDecision(localMovie, downloadClientItem);
                }
                else
                {
                    localMovie      = new LocalMovie();
                    localMovie.Path = file;

                    if (MediaFileExtensions.Extensions.Contains(Path.GetExtension(file)))
                    {
                        if (_warnedFiles.Find(file) == null)
                        {
                            _warnedFiles.Set(file, "warned");
                            _logger.Warn("Unable to parse movie info from path {0}", file);
                        }
                        else
                        {
                            _logger.Trace("Already warned user that we are unable to parse movie info from path: {0}", file);
                        }
                    }

                    decision = new ImportDecision(localMovie, new Rejection("Unable to parse file"));
                }
            }
            catch (Exception e)
            {
                _logger.Error(e, "Couldn't import file. {0}", file);

                var localMovie = new LocalMovie {
                    Path = file
                };
                decision = new ImportDecision(localMovie, new Rejection("Unexpected error processing file"));
            }

            //LocalMovie nullMovie = null;

            //decision = new ImportDecision(nullMovie, new Rejection("IMPLEMENTATION MISSING!!!"));

            return(decision);
        }
Beispiel #7
0
        public override IEnumerable <DownloadClientItem> GetItems()
        {
            List <UTorrentTorrent> torrents;

            try
            {
                var cacheKey = string.Format("{0}:{1}:{2}", Settings.Host, Settings.Port, Settings.TvCategory);
                var cache    = _torrentCache.Find(cacheKey);

                var response = _proxy.GetTorrents(cache == null ? null : cache.CacheID, Settings);

                if (cache != null && response.Torrents == null)
                {
                    var removedAndUpdated = new HashSet <string>(response.TorrentsChanged.Select(v => v.Hash).Concat(response.TorrentsRemoved));

                    torrents = cache.Torrents
                               .Where(v => !removedAndUpdated.Contains(v.Hash))
                               .Concat(response.TorrentsChanged)
                               .ToList();
                }
                else
                {
                    torrents = response.Torrents;
                }

                cache = new UTorrentTorrentCache
                {
                    CacheID  = response.CacheNumber,
                    Torrents = torrents
                };

                _torrentCache.Set(cacheKey, cache, TimeSpan.FromMinutes(15));
            }
            catch (DownloadClientException ex)
            {
                _logger.Error(ex, ex.Message);
                return(Enumerable.Empty <DownloadClientItem>());
            }

            var queueItems = new List <DownloadClientItem>();

            foreach (var torrent in torrents)
            {
                if (torrent.Label != Settings.TvCategory)
                {
                    continue;
                }

                var item = new DownloadClientItem();
                item.DownloadId     = torrent.Hash;
                item.Title          = torrent.Name;
                item.TotalSize      = torrent.Size;
                item.Category       = torrent.Label;
                item.DownloadClient = Definition.Name;
                item.RemainingSize  = torrent.Remaining;
                if (torrent.Eta != -1)
                {
                    item.RemainingTime = TimeSpan.FromSeconds(torrent.Eta);
                }

                var outputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(torrent.RootDownloadPath));

                if (outputPath == null || outputPath.FileName == torrent.Name)
                {
                    item.OutputPath = outputPath;
                }
                else
                {
                    item.OutputPath = outputPath + torrent.Name;
                }

                if (torrent.Status.HasFlag(UTorrentTorrentStatus.Error))
                {
                    item.Status  = DownloadItemStatus.Warning;
                    item.Message = "uTorrent is reporting an error";
                }
                else if (torrent.Status.HasFlag(UTorrentTorrentStatus.Loaded) &&
                         torrent.Status.HasFlag(UTorrentTorrentStatus.Checked) && torrent.Remaining == 0 && torrent.Progress == 1.0)
                {
                    item.Status = DownloadItemStatus.Completed;
                }
                else if (torrent.Status.HasFlag(UTorrentTorrentStatus.Paused))
                {
                    item.Status = DownloadItemStatus.Paused;
                }
                else if (torrent.Status.HasFlag(UTorrentTorrentStatus.Started))
                {
                    item.Status = DownloadItemStatus.Downloading;
                }
                else
                {
                    item.Status = DownloadItemStatus.Queued;
                }

                // 'Started' without 'Queued' is when the torrent is 'forced seeding'
                item.IsReadOnly = torrent.Status.HasFlag(UTorrentTorrentStatus.Queued) || torrent.Status.HasFlag(UTorrentTorrentStatus.Started);

                queueItems.Add(item);
            }

            return(queueItems);
        }
Beispiel #8
0
        private object DownloadRelease(ReleaseResource release)
        {
            var remoteBook = _remoteBookCache.Find(GetCacheKey(release));

            if (remoteBook == null)
            {
                _logger.Debug("Couldn't find requested release in cache, cache timeout probably expired.");

                throw new NzbDroneClientException(HttpStatusCode.NotFound, "Couldn't find requested release in cache, try searching again");
            }

            try
            {
                if (remoteBook.Author == null)
                {
                    if (release.BookId.HasValue)
                    {
                        var book = _bookService.GetBook(release.BookId.Value);

                        remoteBook.Author = _authorService.GetAuthor(book.AuthorId);
                        remoteBook.Books  = new List <Book> {
                            book
                        };
                    }
                    else if (release.AuthorId.HasValue)
                    {
                        var author = _authorService.GetAuthor(release.AuthorId.Value);
                        var books  = _parsingService.GetBooks(remoteBook.ParsedBookInfo, author);

                        if (books.Empty())
                        {
                            throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to parse books in the release");
                        }

                        remoteBook.Author = author;
                        remoteBook.Books  = books;
                    }
                    else
                    {
                        throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to find matching author and books");
                    }
                }
                else if (remoteBook.Books.Empty())
                {
                    var books = _parsingService.GetBooks(remoteBook.ParsedBookInfo, remoteBook.Author);

                    if (books.Empty() && release.BookId.HasValue)
                    {
                        var book = _bookService.GetBook(release.BookId.Value);

                        books = new List <Book> {
                            book
                        };
                    }

                    remoteBook.Books = books;
                }

                if (remoteBook.Books.Empty())
                {
                    throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to parse books in the release");
                }

                _downloadService.DownloadReport(remoteBook);
            }
            catch (ReleaseDownloadException ex)
            {
                _logger.Error(ex, "Getting release from indexer failed");
                throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed");
            }

            return(release);
        }
Beispiel #9
0
        public DateTime GetNextExecution(Type type)
        {
            var scheduledTask = _cache.Find(type.FullName);

            return(scheduledTask.LastExecution.AddMinutes(scheduledTask.Interval));
        }
 public List <SceneMapping> FindByTvdbid(int tvdbId)
 {
     return(_findbytvdbIdCache.Find(tvdbId.ToString()));
 }
Beispiel #11
0
        private object DownloadRelease(ReleaseResource release)
        {
            var remoteEpisode = _remoteEpisodeCache.Find(GetCacheKey(release));

            if (remoteEpisode == null)
            {
                _logger.Debug("Couldn't find requested release in cache, cache timeout probably expired.");

                throw new NzbDroneClientException(HttpStatusCode.NotFound, "Couldn't find requested release in cache, try searching again");
            }

            try
            {
                if (remoteEpisode.Series == null)
                {
                    if (release.EpisodeId.HasValue)
                    {
                        var episode = _episodeService.GetEpisode(release.EpisodeId.Value);

                        remoteEpisode.Series   = _seriesService.GetSeries(episode.SeriesId);
                        remoteEpisode.Episodes = new List <Episode> {
                            episode
                        };
                    }
                    else if (release.SeriesId.HasValue)
                    {
                        var series   = _seriesService.GetSeries(release.SeriesId.Value);
                        var episodes = _parsingService.GetEpisodes(remoteEpisode.ParsedEpisodeInfo, series, true);

                        if (episodes.Empty())
                        {
                            throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to parse episodes in the release");
                        }

                        remoteEpisode.Series   = series;
                        remoteEpisode.Episodes = episodes;
                    }
                    else
                    {
                        throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to find matching series and episodes");
                    }
                }
                else if (remoteEpisode.Episodes.Empty())
                {
                    var episodes = _parsingService.GetEpisodes(remoteEpisode.ParsedEpisodeInfo, remoteEpisode.Series, true);

                    if (episodes.Empty() && release.EpisodeId.HasValue)
                    {
                        var episode = _episodeService.GetEpisode(release.EpisodeId.Value);

                        episodes = new List <Episode> {
                            episode
                        };
                    }

                    remoteEpisode.Episodes = episodes;
                }

                if (remoteEpisode.Episodes.Empty())
                {
                    throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to parse episodes in the release");
                }

                _downloadService.DownloadReport(remoteEpisode);
            }
            catch (ReleaseDownloadException ex)
            {
                _logger.Error(ex, ex.Message);
                throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed");
            }

            return(release);
        }
Beispiel #12
0
        private object DownloadRelease(ReleaseResource release)
        {
            var remoteAlbum = _remoteAlbumCache.Find(GetCacheKey(release));

            if (remoteAlbum == null)
            {
                _logger.Debug("Couldn't find requested release in cache, cache timeout probably expired.");

                throw new NzbDroneClientException(HttpStatusCode.NotFound, "Couldn't find requested release in cache, try searching again");
            }

            try
            {
                if (remoteAlbum.Artist == null)
                {
                    if (release.AlbumId.HasValue)
                    {
                        var album = _albumService.GetAlbum(release.AlbumId.Value);

                        remoteAlbum.Artist = _artistService.GetArtist(album.ArtistId);
                        remoteAlbum.Albums = new List <Album> {
                            album
                        };
                    }
                    else if (release.ArtistId.HasValue)
                    {
                        var artist = _artistService.GetArtist(release.ArtistId.Value);
                        var albums = _parsingService.GetAlbums(remoteAlbum.ParsedAlbumInfo, artist);

                        if (albums.Empty())
                        {
                            throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to parse albums in the release");
                        }

                        remoteAlbum.Artist = artist;
                        remoteAlbum.Albums = albums;
                    }
                    else
                    {
                        throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to find matching artist and albums");
                    }
                }
                else if (remoteAlbum.Albums.Empty())
                {
                    var albums = _parsingService.GetAlbums(remoteAlbum.ParsedAlbumInfo, remoteAlbum.Artist);

                    if (albums.Empty() && release.AlbumId.HasValue)
                    {
                        var album = _albumService.GetAlbum(release.AlbumId.Value);

                        albums = new List <Album> {
                            album
                        };
                    }

                    remoteAlbum.Albums = albums;
                }

                if (remoteAlbum.Albums.Empty())
                {
                    throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to parse albums in the release");
                }

                _downloadService.DownloadReport(remoteAlbum);
            }
            catch (ReleaseDownloadException ex)
            {
                _logger.Error(ex, ex.Message);
                throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed");
            }

            return(release);
        }