using System.Collections.Generic; using System.Linq; using FluentValidation; using FluentValidation.Results; using Microsoft.AspNetCore.Mvc; using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Core.Datastore; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Download; using NzbDrone.Core.Indexers; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Profiles.Languages; using NzbDrone.Core.Profiles.Qualities; using Sonarr.Http; namespace Sonarr.Api.V3.Indexers { [V3ApiController("release/push")] public class ReleasePushController : ReleaseControllerBase { private readonly IMakeDownloadDecision _downloadDecisionMaker; private readonly IProcessDownloadDecisions _downloadDecisionProcessor; private readonly IIndexerFactory _indexerFactory; private readonly Logger _logger; public ReleasePushController(IMakeDownloadDecision downloadDecisionMaker, IProcessDownloadDecisions downloadDecisionProcessor, IIndexerFactory indexerFactory, ILanguageProfileService languageProfileService, IQualityProfileService qualityProfileService, Logger logger) : base(languageProfileService, qualityProfileService) { _downloadDecisionMaker = downloadDecisionMaker; _downloadDecisionProcessor = downloadDecisionProcessor; _indexerFactory = indexerFactory; _logger = logger; PostValidator.RuleFor(s => s.Title).NotEmpty(); PostValidator.RuleFor(s => s.DownloadUrl).NotEmpty(); PostValidator.RuleFor(s => s.Protocol).NotEmpty(); PostValidator.RuleFor(s => s.PublishDate).NotEmpty(); } [HttpPost] [Consumes("application/json")] public ActionResult> Create(ReleaseResource release) { _logger.Info("Release pushed: {0} - {1}", release.Title, release.DownloadUrl); ValidateResource(release); var info = release.ToModel(); info.Guid = "PUSH-" + info.DownloadUrl; ResolveIndexer(info); var decisions = _downloadDecisionMaker.GetRssDecision(new List { info }); _downloadDecisionProcessor.ProcessDecisions(decisions); var firstDecision = decisions.FirstOrDefault(); if (firstDecision?.RemoteEpisode.ParsedEpisodeInfo == null) { throw new ValidationException(new List { new ValidationFailure("Title", "Unable to parse", release.Title) }); } return MapDecisions(new[] { firstDecision }); } private void ResolveIndexer(ReleaseInfo release) { if (release.IndexerId == 0 && release.Indexer.IsNotNullOrWhiteSpace()) { var indexer = _indexerFactory.All().FirstOrDefault(v => v.Name == release.Indexer); if (indexer != null) { release.IndexerId = indexer.Id; _logger.Debug("Push Release {0} associated with indexer {1} - {2}.", release.Title, release.IndexerId, release.Indexer); } else { _logger.Debug("Push Release {0} not associated with known indexer {1}.", release.Title, release.Indexer); } } else if (release.IndexerId != 0 && release.Indexer.IsNullOrWhiteSpace()) { try { var indexer = _indexerFactory.Get(release.IndexerId); release.Indexer = indexer.Name; _logger.Debug("Push Release {0} associated with indexer {1} - {2}.", release.Title, release.IndexerId, release.Indexer); } catch (ModelNotFoundException) { _logger.Debug("Push Release {0} not associated with known indexer {1}.", release.Title, release.IndexerId); release.IndexerId = 0; } } else { _logger.Debug("Push Release {0} not associated with an indexer.", release.Title); } } } }