2022-03-08 02:03:00 +00:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
2022-06-25 21:01:01 +00:00
|
|
|
using NzbDrone.Common.Extensions;
|
2022-03-08 02:03:00 +00:00
|
|
|
using NzbDrone.Core.Datastore.Events;
|
2023-09-10 17:24:42 +00:00
|
|
|
using NzbDrone.Core.MediaCover;
|
2022-06-25 20:23:39 +00:00
|
|
|
using NzbDrone.Core.Messaging.Commands;
|
2022-03-08 02:03:00 +00:00
|
|
|
using NzbDrone.Core.Messaging.Events;
|
|
|
|
using NzbDrone.Core.Movies;
|
|
|
|
using NzbDrone.Core.Movies.Collections;
|
2022-06-25 20:23:39 +00:00
|
|
|
using NzbDrone.Core.Movies.Commands;
|
2022-03-08 02:03:00 +00:00
|
|
|
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;
|
2022-06-03 00:31:42 +00:00
|
|
|
private readonly INamingConfigService _namingService;
|
2023-09-10 17:24:42 +00:00
|
|
|
private readonly IMapCoversToLocal _coverMapper;
|
2022-06-25 20:23:39 +00:00
|
|
|
private readonly IManageCommandQueue _commandQueueManager;
|
2022-03-08 02:03:00 +00:00
|
|
|
|
|
|
|
public CollectionController(IBroadcastSignalRMessage signalRBroadcaster,
|
|
|
|
IMovieCollectionService collectionService,
|
|
|
|
IMovieService movieService,
|
|
|
|
IMovieMetadataService movieMetadataService,
|
2022-06-03 00:31:42 +00:00
|
|
|
IBuildFileNames fileNameBuilder,
|
2022-06-25 20:23:39 +00:00
|
|
|
INamingConfigService namingService,
|
2023-09-10 17:24:42 +00:00
|
|
|
IMapCoversToLocal coverMapper,
|
2022-06-25 20:23:39 +00:00
|
|
|
IManageCommandQueue commandQueueManager)
|
2022-03-08 02:03:00 +00:00
|
|
|
: base(signalRBroadcaster)
|
|
|
|
{
|
|
|
|
_collectionService = collectionService;
|
|
|
|
_movieService = movieService;
|
|
|
|
_movieMetadataService = movieMetadataService;
|
|
|
|
_fileNameBuilder = fileNameBuilder;
|
2022-06-03 00:31:42 +00:00
|
|
|
_namingService = namingService;
|
2023-09-10 17:24:42 +00:00
|
|
|
_coverMapper = coverMapper;
|
2022-06-25 20:23:39 +00:00
|
|
|
_commandQueueManager = commandQueueManager;
|
2022-03-08 02:03:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override CollectionResource GetResourceById(int id)
|
|
|
|
{
|
|
|
|
return MapToResource(_collectionService.GetCollection(id));
|
|
|
|
}
|
|
|
|
|
|
|
|
[HttpGet]
|
2022-08-19 03:37:15 +00:00
|
|
|
public List<CollectionResource> GetCollections(int? tmdbId)
|
2022-03-08 02:03:00 +00:00
|
|
|
{
|
2022-08-19 03:37:15 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
return collectionResources;
|
2022-03-08 02:03:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
[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]
|
2022-06-25 20:23:39 +00:00
|
|
|
public ActionResult UpdateCollections(CollectionUpdateResource resource)
|
2022-03-08 02:03:00 +00:00
|
|
|
{
|
2022-06-25 20:23:39 +00:00
|
|
|
var collectionsToUpdate = _collectionService.GetCollections(resource.CollectionIds);
|
2022-03-08 02:03:00 +00:00
|
|
|
|
2022-06-25 20:23:39 +00:00
|
|
|
foreach (var collection in collectionsToUpdate)
|
2022-03-08 02:03:00 +00:00
|
|
|
{
|
2022-06-25 20:23:39 +00:00
|
|
|
if (resource.Monitored.HasValue)
|
2022-03-08 02:03:00 +00:00
|
|
|
{
|
2022-06-25 20:23:39 +00:00
|
|
|
collection.Monitored = resource.Monitored.Value;
|
2022-03-08 02:03:00 +00:00
|
|
|
}
|
|
|
|
|
2022-06-25 21:01:01 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-06-25 20:23:39 +00:00
|
|
|
if (resource.MonitorMovies.HasValue)
|
2022-03-08 02:03:00 +00:00
|
|
|
{
|
|
|
|
var movies = _movieService.GetMoviesByCollectionTmdbId(collection.TmdbId);
|
|
|
|
|
2022-06-25 20:23:39 +00:00
|
|
|
movies.ForEach(c => c.Monitored = resource.MonitorMovies.Value);
|
2022-03-08 02:03:00 +00:00
|
|
|
|
|
|
|
_movieService.UpdateMovie(movies, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-25 20:23:39 +00:00
|
|
|
var updated = _collectionService.UpdateCollections(collectionsToUpdate.ToList()).ToResource();
|
|
|
|
|
|
|
|
_commandQueueManager.Push(new RefreshCollectionsCommand());
|
|
|
|
|
|
|
|
return Accepted(updated);
|
2022-03-08 02:03:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-16 02:47:21 +00:00
|
|
|
private IEnumerable<CollectionResource> MapToResource(List<MovieCollection> collections)
|
2022-06-03 00:31:42 +00:00
|
|
|
{
|
|
|
|
// Avoid calling for naming spec on every movie in filenamebuilder
|
|
|
|
var namingConfig = _namingService.GetConfig();
|
2022-07-16 02:47:21 +00:00
|
|
|
var collectionMovies = _movieMetadataService.GetMoviesWithCollections();
|
2023-06-25 14:04:57 +00:00
|
|
|
var existingMoviesTmdbIds = _movieService.AllMovieWithCollectionsTmdbIds();
|
2022-06-03 00:31:42 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2023-09-10 17:24:42 +00:00
|
|
|
_coverMapper.ConvertToLocalUrls(0, movieResource.Images);
|
|
|
|
|
2023-06-25 14:04:57 +00:00
|
|
|
if (!existingMoviesTmdbIds.Contains(movie.TmdbId))
|
|
|
|
{
|
|
|
|
resource.MissingMovies++;
|
|
|
|
}
|
|
|
|
|
2022-06-03 00:31:42 +00:00
|
|
|
resource.Movies.Add(movieResource);
|
|
|
|
}
|
|
|
|
|
|
|
|
yield return resource;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-08 02:03:00 +00:00
|
|
|
private CollectionResource MapToResource(MovieCollection collection)
|
|
|
|
{
|
|
|
|
var resource = collection.ToResource();
|
2023-06-25 14:04:57 +00:00
|
|
|
var existingMoviesTmdbIds = _movieService.AllMovieWithCollectionsTmdbIds();
|
2023-07-10 04:05:59 +00:00
|
|
|
var namingConfig = _namingService.GetConfig();
|
2022-03-08 02:03:00 +00:00
|
|
|
|
|
|
|
foreach (var movie in _movieMetadataService.GetMoviesByCollectionTmdbId(collection.TmdbId))
|
|
|
|
{
|
|
|
|
var movieResource = movie.ToResource();
|
2023-07-10 04:05:59 +00:00
|
|
|
movieResource.Folder = _fileNameBuilder.GetMovieFolder(new Movie { MovieMetadata = movie }, namingConfig);
|
2022-03-08 02:03:00 +00:00
|
|
|
|
2023-09-10 17:24:42 +00:00
|
|
|
_coverMapper.ConvertToLocalUrls(0, movieResource.Images);
|
|
|
|
|
2023-06-25 14:04:57 +00:00
|
|
|
if (!existingMoviesTmdbIds.Contains(movie.TmdbId))
|
|
|
|
{
|
|
|
|
resource.MissingMovies++;
|
|
|
|
}
|
|
|
|
|
2022-03-08 02:03:00 +00:00
|
|
|
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)
|
|
|
|
{
|
2022-07-13 00:20:46 +00:00
|
|
|
BroadcastResourceChange(ModelAction.Deleted, message.Collection.Id);
|
2022-03-08 02:03:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|