using System; using System.Collections.Generic; using FluentValidation; using Nancy; using NLog; using NzbDrone.Api.Mapping; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Download; using NzbDrone.Core.IndexerSearch; using NzbDrone.Core.Indexers; using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; using Omu.ValueInjecter; using System.Linq; using Nancy.ModelBinding; using NzbDrone.Api.Extensions; using NzbDrone.Common.Cache; using System.Threading; namespace NzbDrone.Api.Indexers { public class ReleaseModule : NzbDroneRestModule { private readonly IFetchAndParseRss _rssFetcherAndParser; private readonly ISearchForNzb _nzbSearchService; private readonly IMakeDownloadDecision _downloadDecisionMaker; private readonly IPrioritizeDownloadDecision _prioritizeDownloadDecision; private readonly IDownloadService _downloadService; private readonly IParsingService _parsingService; private readonly Logger _logger; private readonly ICached _remoteEpisodeCache; public ReleaseModule(IFetchAndParseRss rssFetcherAndParser, ISearchForNzb nzbSearchService, IMakeDownloadDecision downloadDecisionMaker, IPrioritizeDownloadDecision prioritizeDownloadDecision, IDownloadService downloadService, IParsingService parsingService, ICacheManager cacheManager, Logger logger) { _rssFetcherAndParser = rssFetcherAndParser; _nzbSearchService = nzbSearchService; _downloadDecisionMaker = downloadDecisionMaker; _prioritizeDownloadDecision = prioritizeDownloadDecision; _downloadService = downloadService; _parsingService = parsingService; _logger = logger; GetResourceAll = GetReleases; Post["/"] = x => DownloadRelease(this.Bind()); PostValidator.RuleFor(s => s.DownloadAllowed).Equal(true); _remoteEpisodeCache = cacheManager.GetCache(GetType(), "remoteEpisodes"); } private Response DownloadRelease(ReleaseResource release) { var remoteEpisode = _remoteEpisodeCache.Find(release.Guid); if (remoteEpisode == null) { _logger.Debug("Couldn't find requested release in cache, cache timeout probably expired."); return new NotFoundResponse(); } _downloadService.DownloadReport(remoteEpisode); return release.AsResponse(); } private List GetReleases() { if (Request.Query.episodeId != null) { return GetEpisodeReleases(Request.Query.episodeId); } return GetRss(); } private List GetEpisodeReleases(int episodeId) { try { var decisions = _nzbSearchService.EpisodeSearch(episodeId); var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(decisions); return MapDecisions(prioritizedDecisions); } catch (Exception ex) { _logger.ErrorException("Episode search failed: " + ex.Message, ex); } return new List(); } private List GetRss() { var reports = _rssFetcherAndParser.Fetch(); var decisions = _downloadDecisionMaker.GetRssDecision(reports); var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(decisions); return MapDecisions(prioritizedDecisions); } private List MapDecisions(IEnumerable decisions) { var result = new List(); foreach (var downloadDecision in decisions) { _remoteEpisodeCache.Set(downloadDecision.RemoteEpisode.Release.Guid, downloadDecision.RemoteEpisode, TimeSpan.FromMinutes(30)); var release = new ReleaseResource(); release.InjectFrom(downloadDecision.RemoteEpisode.Release); release.InjectFrom(downloadDecision.RemoteEpisode.ParsedEpisodeInfo); release.InjectFrom(downloadDecision); release.Rejections = downloadDecision.Rejections.Select(r => r.Reason).ToList(); release.DownloadAllowed = downloadDecision.RemoteEpisode.DownloadAllowed; release.ReleaseWeight = result.Count; if (downloadDecision.RemoteEpisode.Series != null) { release.QualityWeight = downloadDecision.RemoteEpisode.Series.Profile.Value.Items.FindIndex(v => v.Quality == release.Quality.Quality) * 2; } if (!release.Quality.Proper) { release.QualityWeight++; } result.Add(release); } return result; } } }