You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Radarr/src/Radarr.Api.V3/Collections/CollectionController.cs

208 lines
7.5 KiB

using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Collections;
using NzbDrone.Core.Movies.Commands;
using NzbDrone.Core.Movies.Events;
using NzbDrone.Core.Organizer;
using NzbDrone.SignalR;
using Radarr.Http;
using Radarr.Http.REST;
using Radarr.Http.REST.Attributes;
namespace Radarr.Api.V3.Collections
{
[V3ApiController]
public class CollectionController : RestControllerWithSignalR<CollectionResource, MovieCollection>,
IHandle<CollectionAddedEvent>,
IHandle<CollectionEditedEvent>,
IHandle<CollectionDeletedEvent>
{
private readonly IMovieCollectionService _collectionService;
private readonly IMovieService _movieService;
private readonly IMovieMetadataService _movieMetadataService;
private readonly IBuildFileNames _fileNameBuilder;
private readonly INamingConfigService _namingService;
private readonly IManageCommandQueue _commandQueueManager;
private readonly Logger _logger;
public CollectionController(IBroadcastSignalRMessage signalRBroadcaster,
IMovieCollectionService collectionService,
IMovieService movieService,
IMovieMetadataService movieMetadataService,
IBuildFileNames fileNameBuilder,
INamingConfigService namingService,
IManageCommandQueue commandQueueManager,
Logger logger)
: base(signalRBroadcaster)
{
_collectionService = collectionService;
_movieService = movieService;
_movieMetadataService = movieMetadataService;
_fileNameBuilder = fileNameBuilder;
_namingService = namingService;
_commandQueueManager = commandQueueManager;
_logger = logger;
}
protected override CollectionResource GetResourceById(int id)
{
return MapToResource(_collectionService.GetCollection(id));
}
[HttpGet]
public List<CollectionResource> GetCollections(int? tmdbId)
{
var collectionResources = new List<CollectionResource>();
if (tmdbId.HasValue)
{
var collection = _collectionService.FindByTmdbId(tmdbId.Value);
if (collection != null)
{
collectionResources.AddIfNotNull(MapToResource(collection));
}
}
else
{
collectionResources = MapToResource(_collectionService.GetAllCollections()).ToList();
}
_logger.Trace("Returning Collections");
return collectionResources;
}
[RestPutById]
public ActionResult<CollectionResource> UpdateCollection(CollectionResource collectionResource)
{
var collection = _collectionService.GetCollection(collectionResource.Id);
var model = collectionResource.ToModel(collection);
var updatedMovie = _collectionService.UpdateCollection(model);
return Accepted(updatedMovie.Id);
}
[HttpPut]
public ActionResult UpdateCollections(CollectionUpdateResource resource)
{
var collectionsToUpdate = _collectionService.GetCollections(resource.CollectionIds);
foreach (var collection in collectionsToUpdate)
{
if (resource.Monitored.HasValue)
{
collection.Monitored = resource.Monitored.Value;
}
if (resource.QualityProfileId.HasValue)
{
collection.QualityProfileId = resource.QualityProfileId.Value;
}
if (resource.MinimumAvailability.HasValue)
{
collection.MinimumAvailability = resource.MinimumAvailability.Value;
}
if (resource.RootFolderPath.IsNotNullOrWhiteSpace())
{
collection.RootFolderPath = resource.RootFolderPath;
}
if (resource.MonitorMovies.HasValue)
{
var movies = _movieService.GetMoviesByCollectionTmdbId(collection.TmdbId);
movies.ForEach(c => c.Monitored = resource.MonitorMovies.Value);
_movieService.UpdateMovie(movies, true);
}
}
var updated = _collectionService.UpdateCollections(collectionsToUpdate.ToList()).ToResource();
_commandQueueManager.Push(new RefreshCollectionsCommand());
return Accepted(updated);
}
private IEnumerable<CollectionResource> MapToResource(List<MovieCollection> collections)
{
// Avoid calling for naming spec on every movie in filenamebuilder
var namingConfig = _namingService.GetConfig();
var collectionMovies = _movieMetadataService.GetMoviesWithCollections();
var existingMoviesTmdbIds = _movieService.AllMovieWithCollectionsTmdbIds();
foreach (var collection in collections)
{
var resource = collection.ToResource();
foreach (var movie in collectionMovies.Where(m => m.CollectionTmdbId == collection.TmdbId))
{
var movieResource = movie.ToResource();
movieResource.Folder = _fileNameBuilder.GetMovieFolder(new Movie { MovieMetadata = movie }, namingConfig);
if (!existingMoviesTmdbIds.Contains(movie.TmdbId))
{
resource.MissingMovies++;
}
resource.Movies.Add(movieResource);
}
yield return resource;
}
}
private CollectionResource MapToResource(MovieCollection collection)
{
var resource = collection.ToResource();
var existingMoviesTmdbIds = _movieService.AllMovieWithCollectionsTmdbIds();
var namingConfig = _namingService.GetConfig();
foreach (var movie in _movieMetadataService.GetMoviesByCollectionTmdbId(collection.TmdbId))
{
var movieResource = movie.ToResource();
movieResource.Folder = _fileNameBuilder.GetMovieFolder(new Movie { MovieMetadata = movie }, namingConfig);
if (!existingMoviesTmdbIds.Contains(movie.TmdbId))
{
resource.MissingMovies++;
}
resource.Movies.Add(movieResource);
}
return resource;
}
[NonAction]
public void Handle(CollectionAddedEvent message)
{
BroadcastResourceChange(ModelAction.Created, MapToResource(message.Collection));
}
[NonAction]
public void Handle(CollectionEditedEvent message)
{
BroadcastResourceChange(ModelAction.Updated, MapToResource(message.Collection));
}
[NonAction]
public void Handle(CollectionDeletedEvent message)
{
BroadcastResourceChange(ModelAction.Deleted, message.Collection.Id);
}
}
}