mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-17 17:14:18 +02:00
Fixed: Remove Static/Dynamic Settings, Allow Folder Move from Editor
This commit is contained in:
@@ -49,6 +49,13 @@ function MoveMovieModal(props) {
|
|||||||
`Would you like to move the movie folders to '${destinationRootFolder}'?` :
|
`Would you like to move the movie folders to '${destinationRootFolder}'?` :
|
||||||
`Would you like to move the movie files from '${originalPath}' to '${destinationPath}'?`
|
`Would you like to move the movie files from '${originalPath}' to '${destinationPath}'?`
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
destinationRootFolder ?
|
||||||
|
<div>
|
||||||
|
This will also rename the movie folder per the movie folder format in settings.
|
||||||
|
</div> :
|
||||||
|
null
|
||||||
|
}
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
|
@@ -39,7 +39,6 @@ namespace NzbDrone.Api.Config
|
|||||||
CreateEmptySeriesFolders = model.CreateEmptyMovieFolders,
|
CreateEmptySeriesFolders = model.CreateEmptyMovieFolders,
|
||||||
FileDate = model.FileDate,
|
FileDate = model.FileDate,
|
||||||
AutoRenameFolders = model.AutoRenameFolders,
|
AutoRenameFolders = model.AutoRenameFolders,
|
||||||
PathsDefaultStatic = model.PathsDefaultStatic,
|
|
||||||
|
|
||||||
SetPermissionsLinux = model.SetPermissionsLinux,
|
SetPermissionsLinux = model.SetPermissionsLinux,
|
||||||
FileChmod = model.FileChmod,
|
FileChmod = model.FileChmod,
|
||||||
|
@@ -25,7 +25,7 @@ namespace NzbDrone.Api.Movies
|
|||||||
|
|
||||||
var movie = resources.Select(movieResource => movieResource.ToModel(_movieService.GetMovie(movieResource.Id))).ToList();
|
var movie = resources.Select(movieResource => movieResource.ToModel(_movieService.GetMovie(movieResource.Id))).ToList();
|
||||||
|
|
||||||
return ResponseWithCode(_movieService.UpdateMovie(movie)
|
return ResponseWithCode(_movieService.UpdateMovie(movie, true)
|
||||||
.ToResource(),
|
.ToResource(),
|
||||||
HttpStatusCode.Accepted);
|
HttpStatusCode.Accepted);
|
||||||
}
|
}
|
||||||
|
@@ -43,7 +43,6 @@ namespace NzbDrone.Api.Movies
|
|||||||
//View & Edit
|
//View & Edit
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
public int ProfileId { get; set; }
|
public int ProfileId { get; set; }
|
||||||
public MoviePathState PathState { get; set; }
|
|
||||||
|
|
||||||
//Editing Only
|
//Editing Only
|
||||||
public bool Monitored { get; set; }
|
public bool Monitored { get; set; }
|
||||||
@@ -144,7 +143,6 @@ namespace NzbDrone.Api.Movies
|
|||||||
|
|
||||||
Path = model.Path,
|
Path = model.Path,
|
||||||
ProfileId = model.ProfileId,
|
ProfileId = model.ProfileId,
|
||||||
PathState = model.PathState,
|
|
||||||
|
|
||||||
Monitored = model.Monitored,
|
Monitored = model.Monitored,
|
||||||
MinimumAvailability = model.MinimumAvailability,
|
MinimumAvailability = model.MinimumAvailability,
|
||||||
@@ -209,7 +207,6 @@ namespace NzbDrone.Api.Movies
|
|||||||
|
|
||||||
Path = resource.Path,
|
Path = resource.Path,
|
||||||
ProfileId = resource.ProfileId,
|
ProfileId = resource.ProfileId,
|
||||||
PathState = resource.PathState,
|
|
||||||
|
|
||||||
Monitored = resource.Monitored,
|
Monitored = resource.Monitored,
|
||||||
MinimumAvailability = resource.MinimumAvailability,
|
MinimumAvailability = resource.MinimumAvailability,
|
||||||
|
@@ -153,30 +153,30 @@ namespace NzbDrone.Core.Test.Datastore
|
|||||||
[Test]
|
[Test]
|
||||||
public void enum_as_int()
|
public void enum_as_int()
|
||||||
{
|
{
|
||||||
_subject = Where(x => x.PathState == MoviePathState.Static);
|
_subject = Where(x => x.Status == MovieStatusType.Released);
|
||||||
|
|
||||||
var name = _subject.Parameters.ParameterNames.First();
|
var name = _subject.Parameters.ParameterNames.First();
|
||||||
_subject.ToString().Should().Be($"(\"Movies\".\"PathState\" = @{name})");
|
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = @{name})");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void enum_in_list()
|
public void enum_in_list()
|
||||||
{
|
{
|
||||||
var allowed = new List<MoviePathState> { MoviePathState.Dynamic, MoviePathState.Static };
|
var allowed = new List<MovieStatusType> { MovieStatusType.InCinemas, MovieStatusType.Released };
|
||||||
_subject = Where(x => allowed.Contains(x.PathState));
|
_subject = Where(x => allowed.Contains(x.Status));
|
||||||
|
|
||||||
var name = _subject.Parameters.ParameterNames.First();
|
var name = _subject.Parameters.ParameterNames.First();
|
||||||
_subject.ToString().Should().Be($"(\"Movies\".\"PathState\" IN @{name})");
|
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @{name})");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void enum_in_array()
|
public void enum_in_array()
|
||||||
{
|
{
|
||||||
var allowed = new MoviePathState[] { MoviePathState.Dynamic, MoviePathState.Static };
|
var allowed = new MovieStatusType[] { MovieStatusType.InCinemas, MovieStatusType.Released };
|
||||||
_subject = Where(x => allowed.Contains(x.PathState));
|
_subject = Where(x => allowed.Contains(x.Status));
|
||||||
|
|
||||||
var name = _subject.Parameters.ParameterNames.First();
|
var name = _subject.Parameters.ParameterNames.First();
|
||||||
_subject.ToString().Should().Be($"(\"Movies\".\"PathState\" IN @{name})");
|
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @{name})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,94 @@
|
|||||||
|
using System.IO;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Movies;
|
||||||
|
using NzbDrone.Core.Organizer;
|
||||||
|
using NzbDrone.Core.RootFolders;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.MovieTests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class MovieFolderPathBuilderFixture : CoreTest<MoviePathBuilder>
|
||||||
|
{
|
||||||
|
private Movie _movie;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_movie = Builder<Movie>.CreateNew()
|
||||||
|
.With(s => s.Title = "Movie Title")
|
||||||
|
.With(s => s.Path = @"C:\Test\Movies\Movie.Title".AsOsAgnostic())
|
||||||
|
.With(s => s.RootFolderPath = null)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenMovieFolderName(string name)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IBuildFileNames>()
|
||||||
|
.Setup(s => s.GetMovieFolder(_movie, null))
|
||||||
|
.Returns(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenExistingRootFolder(string rootFolder)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IRootFolderService>()
|
||||||
|
.Setup(s => s.GetBestRootFolderPath(It.IsAny<string>()))
|
||||||
|
.Returns(rootFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_create_new_movie_path()
|
||||||
|
{
|
||||||
|
var rootFolder = @"C:\Test\Movies2".AsOsAgnostic();
|
||||||
|
|
||||||
|
GivenMovieFolderName(_movie.Title);
|
||||||
|
_movie.RootFolderPath = rootFolder;
|
||||||
|
|
||||||
|
Subject.BuildPath(_movie, false).Should().Be(Path.Combine(rootFolder, _movie.Title));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_reuse_existing_relative_folder_name()
|
||||||
|
{
|
||||||
|
var folderName = Path.GetFileName(_movie.Path);
|
||||||
|
var rootFolder = @"C:\Test\Movies2".AsOsAgnostic();
|
||||||
|
|
||||||
|
GivenExistingRootFolder(Path.GetDirectoryName(_movie.Path));
|
||||||
|
GivenMovieFolderName(_movie.Title);
|
||||||
|
_movie.RootFolderPath = rootFolder;
|
||||||
|
|
||||||
|
Subject.BuildPath(_movie, true).Should().Be(Path.Combine(rootFolder, folderName));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_reuse_existing_relative_folder_structure()
|
||||||
|
{
|
||||||
|
var existingRootFolder = @"C:\Test\Movies".AsOsAgnostic();
|
||||||
|
var existingRelativePath = @"M\Movie.Title";
|
||||||
|
var rootFolder = @"C:\Test\Movies2".AsOsAgnostic();
|
||||||
|
|
||||||
|
GivenExistingRootFolder(existingRootFolder);
|
||||||
|
GivenMovieFolderName(_movie.Title);
|
||||||
|
_movie.RootFolderPath = rootFolder;
|
||||||
|
_movie.Path = Path.Combine(existingRootFolder, existingRelativePath);
|
||||||
|
|
||||||
|
Subject.BuildPath(_movie, true).Should().Be(Path.Combine(rootFolder, existingRelativePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_use_built_path_for_new_movie()
|
||||||
|
{
|
||||||
|
var rootFolder = @"C:\Test\Movies2".AsOsAgnostic();
|
||||||
|
|
||||||
|
GivenMovieFolderName(_movie.Title);
|
||||||
|
_movie.RootFolderPath = rootFolder;
|
||||||
|
_movie.Path = null;
|
||||||
|
|
||||||
|
Subject.BuildPath(_movie, true).Should().Be(Path.Combine(rootFolder, _movie.Title));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,10 +1,12 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
|
using NzbDrone.Core.Organizer;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
@@ -30,7 +32,7 @@ namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests
|
|||||||
[Test]
|
[Test]
|
||||||
public void should_call_repo_updateMany()
|
public void should_call_repo_updateMany()
|
||||||
{
|
{
|
||||||
Subject.UpdateMovie(_movies);
|
Subject.UpdateMovie(_movies, false);
|
||||||
|
|
||||||
Mocker.GetMock<IMovieRepository>().Verify(v => v.UpdateMany(_movies), Times.Once());
|
Mocker.GetMock<IMovieRepository>().Verify(v => v.UpdateMany(_movies), Times.Once());
|
||||||
}
|
}
|
||||||
@@ -41,13 +43,17 @@ namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests
|
|||||||
var newRoot = @"C:\Test\TV2".AsOsAgnostic();
|
var newRoot = @"C:\Test\TV2".AsOsAgnostic();
|
||||||
_movies.ForEach(s => s.RootFolderPath = newRoot);
|
_movies.ForEach(s => s.RootFolderPath = newRoot);
|
||||||
|
|
||||||
Subject.UpdateMovie(_movies).ForEach(s => s.Path.Should().StartWith(newRoot));
|
Mocker.GetMock<IBuildMoviePaths>()
|
||||||
|
.Setup(s => s.BuildPath(It.IsAny<Movie>(), false))
|
||||||
|
.Returns<Movie, bool>((s, u) => Path.Combine(s.RootFolderPath, s.Title));
|
||||||
|
|
||||||
|
Subject.UpdateMovie(_movies, false).ForEach(s => s.Path.Should().StartWith(newRoot));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_not_update_path_when_rootFolderPath_is_empty()
|
public void should_not_update_path_when_rootFolderPath_is_empty()
|
||||||
{
|
{
|
||||||
Subject.UpdateMovie(_movies).ForEach(s =>
|
Subject.UpdateMovie(_movies, false).ForEach(s =>
|
||||||
{
|
{
|
||||||
var expectedPath = _movies.Single(ser => ser.Id == s.Id).Path;
|
var expectedPath = _movies.Single(ser => ser.Id == s.Id).Path;
|
||||||
s.Path.Should().Be(expectedPath);
|
s.Path.Should().Be(expectedPath);
|
||||||
@@ -66,7 +72,11 @@ namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests
|
|||||||
var newRoot = @"C:\Test\Movies2".AsOsAgnostic();
|
var newRoot = @"C:\Test\Movies2".AsOsAgnostic();
|
||||||
movies.ForEach(s => s.RootFolderPath = newRoot);
|
movies.ForEach(s => s.RootFolderPath = newRoot);
|
||||||
|
|
||||||
Subject.UpdateMovie(movies);
|
Mocker.GetMock<IBuildFileNames>()
|
||||||
|
.Setup(s => s.GetMovieFolder(It.IsAny<Movie>(), (NamingConfig)null))
|
||||||
|
.Returns<Movie, NamingConfig>((s, n) => s.Title);
|
||||||
|
|
||||||
|
Subject.UpdateMovie(movies, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -116,7 +116,7 @@ namespace NzbDrone.Core.Test.NetImport
|
|||||||
.Verify(v => v.GetAllMovies(), Times.Never());
|
.Verify(v => v.GetAllMovies(), Times.Never());
|
||||||
|
|
||||||
Mocker.GetMock<IMovieService>()
|
Mocker.GetMock<IMovieService>()
|
||||||
.Verify(v => v.UpdateMovie(new List<Movie>()), Times.Once());
|
.Verify(v => v.UpdateMovie(new List<Movie>(), true), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -139,7 +139,7 @@ namespace NzbDrone.Core.Test.NetImport
|
|||||||
.Verify(v => v.DeleteMovie(It.IsAny<int>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never());
|
.Verify(v => v.DeleteMovie(It.IsAny<int>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never());
|
||||||
|
|
||||||
Mocker.GetMock<IMovieService>()
|
Mocker.GetMock<IMovieService>()
|
||||||
.Verify(v => v.UpdateMovie(new List<Movie>()), Times.Once());
|
.Verify(v => v.UpdateMovie(new List<Movie>(), true), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -162,7 +162,7 @@ namespace NzbDrone.Core.Test.NetImport
|
|||||||
.Verify(v => v.DeleteMovie(It.IsAny<int>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never());
|
.Verify(v => v.DeleteMovie(It.IsAny<int>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never());
|
||||||
|
|
||||||
Mocker.GetMock<IMovieService>()
|
Mocker.GetMock<IMovieService>()
|
||||||
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.Count == 3 && s.All(m => !m.Monitored))), Times.Once());
|
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.Count == 3 && s.All(m => !m.Monitored)), true), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -181,7 +181,7 @@ namespace NzbDrone.Core.Test.NetImport
|
|||||||
Subject.Execute(_command);
|
Subject.Execute(_command);
|
||||||
|
|
||||||
Mocker.GetMock<IMovieService>()
|
Mocker.GetMock<IMovieService>()
|
||||||
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.Count == 2 && s.All(m => !m.Monitored))), Times.Once());
|
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.Count == 2 && s.All(m => !m.Monitored)), true), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -201,7 +201,7 @@ namespace NzbDrone.Core.Test.NetImport
|
|||||||
Subject.Execute(_command);
|
Subject.Execute(_command);
|
||||||
|
|
||||||
Mocker.GetMock<IMovieService>()
|
Mocker.GetMock<IMovieService>()
|
||||||
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.Count == 2 && s.All(m => !m.Monitored))), Times.Once());
|
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.Count == 2 && s.All(m => !m.Monitored)), true), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -227,7 +227,7 @@ namespace NzbDrone.Core.Test.NetImport
|
|||||||
.Verify(v => v.DeleteMovie(It.IsAny<int>(), true, It.IsAny<bool>()), Times.Never());
|
.Verify(v => v.DeleteMovie(It.IsAny<int>(), true, It.IsAny<bool>()), Times.Never());
|
||||||
|
|
||||||
Mocker.GetMock<IMovieService>()
|
Mocker.GetMock<IMovieService>()
|
||||||
.Verify(v => v.UpdateMovie(new List<Movie>()), Times.Once());
|
.Verify(v => v.UpdateMovie(new List<Movie>(), true), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -253,7 +253,7 @@ namespace NzbDrone.Core.Test.NetImport
|
|||||||
.Verify(v => v.DeleteMovie(It.IsAny<int>(), true, It.IsAny<bool>()), Times.Exactly(3));
|
.Verify(v => v.DeleteMovie(It.IsAny<int>(), true, It.IsAny<bool>()), Times.Exactly(3));
|
||||||
|
|
||||||
Mocker.GetMock<IMovieService>()
|
Mocker.GetMock<IMovieService>()
|
||||||
.Verify(v => v.UpdateMovie(new List<Movie>()), Times.Once());
|
.Verify(v => v.UpdateMovie(new List<Movie>(), true), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -267,7 +267,7 @@ namespace NzbDrone.Core.Test.NetImport
|
|||||||
Subject.Execute(_command);
|
Subject.Execute(_command);
|
||||||
|
|
||||||
Mocker.GetMock<IMovieService>()
|
Mocker.GetMock<IMovieService>()
|
||||||
.Verify(v => v.UpdateMovie(new List<Movie>()), Times.Never());
|
.Verify(v => v.UpdateMovie(new List<Movie>(), true), Times.Never());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@@ -299,13 +299,6 @@ namespace NzbDrone.Core.Configuration
|
|||||||
set { SetValue("AutoRenameFolders", value); }
|
set { SetValue("AutoRenameFolders", value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PathsDefaultStatic
|
|
||||||
{
|
|
||||||
get { return GetValueBoolean("PathsDefaultStatic", true); }
|
|
||||||
|
|
||||||
set { SetValue("PathsDefaultStatic", value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public RescanAfterRefreshType RescanAfterRefresh
|
public RescanAfterRefreshType RescanAfterRefresh
|
||||||
{
|
{
|
||||||
get { return GetValueEnum("RescanAfterRefresh", RescanAfterRefreshType.Always); }
|
get { return GetValueEnum("RescanAfterRefresh", RescanAfterRefreshType.Always); }
|
||||||
|
@@ -40,7 +40,6 @@ namespace NzbDrone.Core.Configuration
|
|||||||
string ExtraFileExtensions { get; set; }
|
string ExtraFileExtensions { get; set; }
|
||||||
RescanAfterRefreshType RescanAfterRefresh { get; set; }
|
RescanAfterRefreshType RescanAfterRefresh { get; set; }
|
||||||
bool AutoRenameFolders { get; set; }
|
bool AutoRenameFolders { get; set; }
|
||||||
bool PathsDefaultStatic { get; set; }
|
|
||||||
|
|
||||||
//Permissions (Media Management)
|
//Permissions (Media Management)
|
||||||
bool SetPermissionsLinux { get; set; }
|
bool SetPermissionsLinux { get; set; }
|
||||||
|
@@ -0,0 +1,21 @@
|
|||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(167)]
|
||||||
|
public class remove_movie_pathstate : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Delete.Column("PathState").FromTable("Movies");
|
||||||
|
|
||||||
|
Execute.Sql("DELETE FROM Config WHERE [KEY] IN ('pathsdefaultstatic')");
|
||||||
|
|
||||||
|
Alter.Table("MovieFiles").AddColumn("OriginalFilePath").AsString().Nullable();
|
||||||
|
|
||||||
|
//This is Ignored in mapping, should not be in DB
|
||||||
|
Delete.Column("Path").FromTable("MovieFiles");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,13 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.SQLite;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Instrumentation.Extensions;
|
using NzbDrone.Common.Instrumentation.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
|
||||||
using NzbDrone.Core.MediaFiles.Commands;
|
using NzbDrone.Core.MediaFiles.Commands;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.Messaging.Commands;
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
@@ -20,22 +18,18 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
public interface IRenameMovieFileService
|
public interface IRenameMovieFileService
|
||||||
{
|
{
|
||||||
List<RenameMovieFilePreview> GetRenamePreviews(int movieId);
|
List<RenameMovieFilePreview> GetRenamePreviews(int movieId);
|
||||||
void RenameMoviePath(Movie movie, bool shouldRenameFiles);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RenameMovieFileService : IRenameMovieFileService,
|
public class RenameMovieFileService : IRenameMovieFileService,
|
||||||
IExecute<RenameFilesCommand>,
|
IExecute<RenameFilesCommand>,
|
||||||
IExecute<RenameMovieCommand>,
|
IExecute<RenameMovieCommand>
|
||||||
IExecute<RenameMovieFolderCommand>
|
|
||||||
{
|
{
|
||||||
private readonly IMovieService _movieService;
|
private readonly IMovieService _movieService;
|
||||||
private readonly IMediaFileService _mediaFileService;
|
private readonly IMediaFileService _mediaFileService;
|
||||||
private readonly IMoveMovieFiles _movieFileMover;
|
private readonly IMoveMovieFiles _movieFileMover;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IBuildFileNames _filenameBuilder;
|
private readonly IBuildFileNames _filenameBuilder;
|
||||||
private readonly IConfigService _configService;
|
|
||||||
private readonly IDiskProvider _diskProvider;
|
private readonly IDiskProvider _diskProvider;
|
||||||
private readonly IRecycleBinProvider _recycleBinProvider;
|
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public RenameMovieFileService(IMovieService movieService,
|
public RenameMovieFileService(IMovieService movieService,
|
||||||
@@ -43,8 +37,6 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
IMoveMovieFiles movieFileMover,
|
IMoveMovieFiles movieFileMover,
|
||||||
IEventAggregator eventAggregator,
|
IEventAggregator eventAggregator,
|
||||||
IBuildFileNames filenameBuilder,
|
IBuildFileNames filenameBuilder,
|
||||||
IConfigService configService,
|
|
||||||
IRecycleBinProvider recycleBinProvider,
|
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
@@ -53,8 +45,6 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
_movieFileMover = movieFileMover;
|
_movieFileMover = movieFileMover;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_filenameBuilder = filenameBuilder;
|
_filenameBuilder = filenameBuilder;
|
||||||
_configService = configService;
|
|
||||||
_recycleBinProvider = recycleBinProvider;
|
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
@@ -82,28 +72,21 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
{
|
{
|
||||||
MovieId = movie.Id,
|
MovieId = movie.Id,
|
||||||
MovieFileId = file.Id,
|
MovieFileId = file.Id,
|
||||||
ExistingPath = movieFilePath,
|
ExistingPath = file.RelativePath,
|
||||||
|
|
||||||
//NewPath = movie.Path.GetRelativePath(newPath)
|
NewPath = movie.Path.GetRelativePath(newPath)
|
||||||
NewPath = newPath
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenameFiles(List<MovieFile> movieFiles, Movie movie, string oldMoviePath = null)
|
private void RenameFiles(List<MovieFile> movieFiles, Movie movie)
|
||||||
{
|
{
|
||||||
var renamed = new List<MovieFile>();
|
var renamed = new List<MovieFile>();
|
||||||
|
|
||||||
if (oldMoviePath == null)
|
|
||||||
{
|
|
||||||
oldMoviePath = movie.Path;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var movieFile in movieFiles)
|
foreach (var movieFile in movieFiles)
|
||||||
{
|
{
|
||||||
var oldMovieFilePath = Path.Combine(oldMoviePath, movieFile.RelativePath);
|
var movieFilePath = Path.Combine(movie.Path, movieFile.RelativePath);
|
||||||
movieFile.Path = oldMovieFilePath;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -116,7 +99,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
|
|
||||||
_logger.Debug("Renamed movie file: {0}", movieFile);
|
_logger.Debug("Renamed movie file: {0}", movieFile);
|
||||||
|
|
||||||
_eventAggregator.PublishEvent(new MovieFileRenamedEvent(movie, movieFile, oldMovieFilePath));
|
_eventAggregator.PublishEvent(new MovieFileRenamedEvent(movie, movieFile, movieFilePath));
|
||||||
}
|
}
|
||||||
catch (SameFilenameException ex)
|
catch (SameFilenameException ex)
|
||||||
{
|
{
|
||||||
@@ -124,55 +107,18 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Error(ex, "Failed to rename file: {0}", oldMovieFilePath);
|
_logger.Error(ex, "Failed to rename file: {0}", movieFilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renamed.Any())
|
if (renamed.Any())
|
||||||
{
|
{
|
||||||
|
_diskProvider.RemoveEmptySubfolders(movie.Path);
|
||||||
|
|
||||||
_eventAggregator.PublishEvent(new MovieRenamedEvent(movie));
|
_eventAggregator.PublishEvent(new MovieRenamedEvent(movie));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RenameMoviePath(Movie movie, bool shouldRenameFiles = true)
|
|
||||||
{
|
|
||||||
var newFolder = _filenameBuilder.BuildMoviePath(movie);
|
|
||||||
if (newFolder != movie.Path && movie.PathState == MoviePathState.Dynamic)
|
|
||||||
{
|
|
||||||
if (!_configService.AutoRenameFolders)
|
|
||||||
{
|
|
||||||
_logger.Info("{0}'s movie should be {1} according to your naming config.", movie, newFolder);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.Info("{0}'s movie folder changed to: {1}", movie, newFolder);
|
|
||||||
var oldFolder = movie.Path;
|
|
||||||
movie.Path = newFolder;
|
|
||||||
|
|
||||||
_diskProvider.MoveFolder(oldFolder, movie.Path);
|
|
||||||
|
|
||||||
// if (false)
|
|
||||||
// {
|
|
||||||
// var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id);
|
|
||||||
// _logger.ProgressInfo("Renaming movie files for {0}", movie.Title);
|
|
||||||
// RenameFiles(movieFiles, movie, oldFolder);
|
|
||||||
// _logger.ProgressInfo("All movie files renamed for {0}", movie.Title);
|
|
||||||
// }
|
|
||||||
_movieService.UpdateMovie(movie);
|
|
||||||
|
|
||||||
if (_diskProvider.GetFiles(oldFolder, SearchOption.AllDirectories).Count() == 0)
|
|
||||||
{
|
|
||||||
_recycleBinProvider.DeleteFolder(oldFolder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (movie.PathState == MoviePathState.StaticOnce)
|
|
||||||
{
|
|
||||||
movie.PathState = MoviePathState.Dynamic;
|
|
||||||
_movieService.UpdateMovie(movie);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Execute(RenameFilesCommand message)
|
public void Execute(RenameFilesCommand message)
|
||||||
{
|
{
|
||||||
var movie = _movieService.GetMovie(message.MovieId);
|
var movie = _movieService.GetMovie(message.MovieId);
|
||||||
@@ -196,25 +142,5 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
_logger.ProgressInfo("All movie files renamed for {0}", movie.Title);
|
_logger.ProgressInfo("All movie files renamed for {0}", movie.Title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Execute(RenameMovieFolderCommand message)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_logger.Debug("Renaming movie folder for selected movie if necessary");
|
|
||||||
var moviesToRename = _movieService.GetMovies(message.MovieIds);
|
|
||||||
foreach (var movie in moviesToRename)
|
|
||||||
{
|
|
||||||
var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id);
|
|
||||||
|
|
||||||
//_logger.ProgressInfo("Renaming movie folder for {0}", movie.Title);
|
|
||||||
RenameMoviePath(movie);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (SQLiteException ex)
|
|
||||||
{
|
|
||||||
_logger.Warn(ex, "wtf: {0}, {1}", ex.ResultCode, ex.Data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ namespace NzbDrone.Core.Movies.Commands
|
|||||||
public string DestinationPath { get; set; }
|
public string DestinationPath { get; set; }
|
||||||
public string DestinationRootFolder { get; set; }
|
public string DestinationRootFolder { get; set; }
|
||||||
|
|
||||||
|
public override bool SendUpdatesToClient => true;
|
||||||
public override bool RequiresDiskAccess => true;
|
public override bool RequiresDiskAccess => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -42,7 +42,6 @@ namespace NzbDrone.Core.Movies
|
|||||||
|
|
||||||
public string Certification { get; set; }
|
public string Certification { get; set; }
|
||||||
public string RootFolderPath { get; set; }
|
public string RootFolderPath { get; set; }
|
||||||
public MoviePathState PathState { get; set; }
|
|
||||||
public DateTime Added { get; set; }
|
public DateTime Added { get; set; }
|
||||||
public DateTime? InCinemas { get; set; }
|
public DateTime? InCinemas { get; set; }
|
||||||
public DateTime? PhysicalRelease { get; set; }
|
public DateTime? PhysicalRelease { get; set; }
|
||||||
@@ -154,7 +153,6 @@ namespace NzbDrone.Core.Movies
|
|||||||
|
|
||||||
Path = otherMovie.Path;
|
Path = otherMovie.Path;
|
||||||
ProfileId = otherMovie.ProfileId;
|
ProfileId = otherMovie.ProfileId;
|
||||||
PathState = otherMovie.PathState;
|
|
||||||
|
|
||||||
Monitored = otherMovie.Monitored;
|
Monitored = otherMovie.Monitored;
|
||||||
MinimumAvailability = otherMovie.MinimumAvailability;
|
MinimumAvailability = otherMovie.MinimumAvailability;
|
||||||
@@ -164,11 +162,4 @@ namespace NzbDrone.Core.Movies
|
|||||||
AddOptions = otherMovie.AddOptions;
|
AddOptions = otherMovie.AddOptions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum MoviePathState
|
|
||||||
{
|
|
||||||
Dynamic,
|
|
||||||
StaticOnce,
|
|
||||||
Static,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
48
src/NzbDrone.Core/Movies/MoviePathBuilder.cs
Normal file
48
src/NzbDrone.Core/Movies/MoviePathBuilder.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Organizer;
|
||||||
|
using NzbDrone.Core.RootFolders;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Movies
|
||||||
|
{
|
||||||
|
public interface IBuildMoviePaths
|
||||||
|
{
|
||||||
|
string BuildPath(Movie movie, bool useExistingRelativeFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MoviePathBuilder : IBuildMoviePaths
|
||||||
|
{
|
||||||
|
private readonly IBuildFileNames _fileNameBuilder;
|
||||||
|
private readonly IRootFolderService _rootFolderService;
|
||||||
|
|
||||||
|
public MoviePathBuilder(IBuildFileNames fileNameBuilder, IRootFolderService rootFolderService)
|
||||||
|
{
|
||||||
|
_fileNameBuilder = fileNameBuilder;
|
||||||
|
_rootFolderService = rootFolderService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BuildPath(Movie movie, bool useExistingRelativeFolder)
|
||||||
|
{
|
||||||
|
if (movie.RootFolderPath.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Root folder was not provided", nameof(movie));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useExistingRelativeFolder && movie.Path.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
var relativePath = GetExistingRelativePath(movie);
|
||||||
|
return Path.Combine(movie.RootFolderPath, relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Path.Combine(movie.RootFolderPath, _fileNameBuilder.GetMovieFolder(movie));
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetExistingRelativePath(Movie movie)
|
||||||
|
{
|
||||||
|
var rootFolderPath = _rootFolderService.GetBestRootFolderPath(movie.Path);
|
||||||
|
|
||||||
|
return rootFolderPath.GetRelativePath(movie.Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -43,7 +43,7 @@ namespace NzbDrone.Core.Movies
|
|||||||
List<Movie> GetAllMovies();
|
List<Movie> GetAllMovies();
|
||||||
List<Movie> AllForTag(int tagId);
|
List<Movie> AllForTag(int tagId);
|
||||||
Movie UpdateMovie(Movie movie);
|
Movie UpdateMovie(Movie movie);
|
||||||
List<Movie> UpdateMovie(List<Movie> movie);
|
List<Movie> UpdateMovie(List<Movie> movie, bool useExistingRelativeFolder);
|
||||||
List<Movie> FilterExistingMovies(List<Movie> movies);
|
List<Movie> FilterExistingMovies(List<Movie> movies);
|
||||||
bool MoviePathExists(string folder);
|
bool MoviePathExists(string folder);
|
||||||
void RemoveAddOptions(Movie movie);
|
void RemoveAddOptions(Movie movie);
|
||||||
@@ -57,6 +57,7 @@ namespace NzbDrone.Core.Movies
|
|||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IBuildFileNames _fileNameBuilder;
|
private readonly IBuildFileNames _fileNameBuilder;
|
||||||
private readonly IImportExclusionsService _exclusionService;
|
private readonly IImportExclusionsService _exclusionService;
|
||||||
|
private readonly IBuildMoviePaths _moviePathBuilder;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public MovieService(IMovieRepository movieRepository,
|
public MovieService(IMovieRepository movieRepository,
|
||||||
@@ -64,6 +65,7 @@ namespace NzbDrone.Core.Movies
|
|||||||
IBuildFileNames fileNameBuilder,
|
IBuildFileNames fileNameBuilder,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IImportExclusionsService exclusionService,
|
IImportExclusionsService exclusionService,
|
||||||
|
IBuildMoviePaths moviePathBuilder,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_movieRepository = movieRepository;
|
_movieRepository = movieRepository;
|
||||||
@@ -71,6 +73,7 @@ namespace NzbDrone.Core.Movies
|
|||||||
_fileNameBuilder = fileNameBuilder;
|
_fileNameBuilder = fileNameBuilder;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_exclusionService = exclusionService;
|
_exclusionService = exclusionService;
|
||||||
|
_moviePathBuilder = moviePathBuilder;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,21 +96,10 @@ namespace NzbDrone.Core.Movies
|
|||||||
{
|
{
|
||||||
Ensure.That(newMovie, () => newMovie).IsNotNull();
|
Ensure.That(newMovie, () => newMovie).IsNotNull();
|
||||||
|
|
||||||
MoviePathState defaultState = MoviePathState.Static;
|
|
||||||
if (!_configService.PathsDefaultStatic)
|
|
||||||
{
|
|
||||||
defaultState = MoviePathState.Dynamic;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(newMovie.Path))
|
if (string.IsNullOrWhiteSpace(newMovie.Path))
|
||||||
{
|
{
|
||||||
var folderName = _fileNameBuilder.GetMovieFolder(newMovie);
|
var folderName = _fileNameBuilder.GetMovieFolder(newMovie);
|
||||||
newMovie.Path = Path.Combine(newMovie.RootFolderPath, folderName);
|
newMovie.Path = Path.Combine(newMovie.RootFolderPath, folderName);
|
||||||
newMovie.PathState = defaultState;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newMovie.PathState = defaultState == MoviePathState.Dynamic ? MoviePathState.StaticOnce : MoviePathState.Static;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Info("Adding Movie {0} Path: [{1}]", newMovie, newMovie.Path);
|
_logger.Info("Adding Movie {0} Path: [{1}]", newMovie, newMovie.Path);
|
||||||
@@ -128,21 +120,10 @@ namespace NzbDrone.Core.Movies
|
|||||||
|
|
||||||
newMovies.ForEach(m =>
|
newMovies.ForEach(m =>
|
||||||
{
|
{
|
||||||
MoviePathState defaultState = MoviePathState.Static;
|
|
||||||
if (!_configService.PathsDefaultStatic)
|
|
||||||
{
|
|
||||||
defaultState = MoviePathState.Dynamic;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(m.Path))
|
if (string.IsNullOrWhiteSpace(m.Path))
|
||||||
{
|
{
|
||||||
var folderName = _fileNameBuilder.GetMovieFolder(m);
|
var folderName = _fileNameBuilder.GetMovieFolder(m);
|
||||||
m.Path = Path.Combine(m.RootFolderPath, folderName);
|
m.Path = Path.Combine(m.RootFolderPath, folderName);
|
||||||
m.PathState = defaultState;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m.PathState = defaultState == MoviePathState.Dynamic ? MoviePathState.StaticOnce : MoviePathState.Static;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m.CleanTitle = m.Title.CleanSeriesTitle();
|
m.CleanTitle = m.Title.CleanSeriesTitle();
|
||||||
@@ -324,21 +305,22 @@ namespace NzbDrone.Core.Movies
|
|||||||
return updatedMovie;
|
return updatedMovie;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Movie> UpdateMovie(List<Movie> movie)
|
public List<Movie> UpdateMovie(List<Movie> movie, bool useExistingRelativeFolder)
|
||||||
{
|
{
|
||||||
_logger.Debug("Updating {0} movie", movie.Count);
|
_logger.Debug("Updating {0} movie", movie.Count);
|
||||||
foreach (var s in movie)
|
foreach (var m in movie)
|
||||||
{
|
{
|
||||||
_logger.Trace("Updating: {0}", s.Title);
|
_logger.Trace("Updating: {0}", m.Title);
|
||||||
if (!s.RootFolderPath.IsNullOrWhiteSpace())
|
|
||||||
|
if (!m.RootFolderPath.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
var folderName = new DirectoryInfo(s.Path).Name;
|
m.Path = _moviePathBuilder.BuildPath(m, useExistingRelativeFolder);
|
||||||
s.Path = Path.Combine(s.RootFolderPath, folderName);
|
|
||||||
_logger.Trace("Changing path for {0} to {1}", s.Title, s.Path);
|
_logger.Trace("Changing path for {0} to {1}", m.Title, m.Path);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Trace("Not changing path for: {0}", s.Title);
|
_logger.Trace("Not changing path for: {0}", m.Title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -138,7 +138,7 @@ namespace NzbDrone.Core.Movies
|
|||||||
_logger.Info(ex, "Unable to communicate with Mappings Server.");
|
_logger.Info(ex, "Unable to communicate with Mappings Server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
_movieService.UpdateMovie(new List<Movie> { movie });
|
_movieService.UpdateMovie(new List<Movie> { movie }, true);
|
||||||
_creditService.UpdateCredits(tuple.Item2, movie);
|
_creditService.UpdateCredits(tuple.Item2, movie);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@@ -194,7 +194,7 @@ namespace NzbDrone.Core.NetImport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_movieService.UpdateMovie(moviesToUpdate);
|
_movieService.UpdateMovie(moviesToUpdate, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ namespace NzbDrone.Core.Organizer
|
|||||||
{
|
{
|
||||||
string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null);
|
string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null);
|
||||||
string BuildFilePath(Movie movie, string fileName, string extension);
|
string BuildFilePath(Movie movie, string fileName, string extension);
|
||||||
string BuildMoviePath(Movie movie, NamingConfig namingConfig = null);
|
|
||||||
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
|
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
|
||||||
string GetMovieFolder(Movie movie, NamingConfig namingConfig = null);
|
string GetMovieFolder(Movie movie, NamingConfig namingConfig = null);
|
||||||
}
|
}
|
||||||
@@ -110,59 +109,11 @@ namespace NzbDrone.Core.Organizer
|
|||||||
{
|
{
|
||||||
Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace();
|
Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace();
|
||||||
|
|
||||||
var path = "";
|
var path = movie.Path;
|
||||||
|
|
||||||
if (movie.PathState > 0)
|
|
||||||
{
|
|
||||||
path = movie.Path;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = BuildMoviePath(movie);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Path.Combine(path, fileName + extension);
|
return Path.Combine(path, fileName + extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string BuildMoviePath(Movie movie, NamingConfig namingConfig = null)
|
|
||||||
{
|
|
||||||
if (namingConfig == null)
|
|
||||||
{
|
|
||||||
namingConfig = _namingConfigService.GetConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
var path = movie.Path;
|
|
||||||
var directory = new DirectoryInfo(path).Name;
|
|
||||||
var parentDirectoryPath = new DirectoryInfo(path).Parent.FullName;
|
|
||||||
|
|
||||||
var movieFile = movie.MovieFile;
|
|
||||||
|
|
||||||
var pattern = namingConfig.MovieFolderFormat;
|
|
||||||
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
|
|
||||||
|
|
||||||
AddMovieTokens(tokenHandlers, movie);
|
|
||||||
AddReleaseDateTokens(tokenHandlers, movie.Year);
|
|
||||||
AddIdTokens(tokenHandlers, movie);
|
|
||||||
|
|
||||||
if (movie.MovieFile != null)
|
|
||||||
{
|
|
||||||
AddQualityTokens(tokenHandlers, movie, movieFile);
|
|
||||||
AddMediaInfoTokens(tokenHandlers, movieFile);
|
|
||||||
AddMovieFileTokens(tokenHandlers, movieFile);
|
|
||||||
AddTagsTokens(tokenHandlers, movieFile);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AddMovieFileTokens(tokenHandlers, new MovieFile { SceneName = $"{movie.Title} {movie.Year}", RelativePath = $"{movie.Title} {movie.Year}" });
|
|
||||||
}
|
|
||||||
|
|
||||||
var directoryName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim();
|
|
||||||
directoryName = FileNameCleanupRegex.Replace(directoryName, match => match.Captures[0].Value[0].ToString());
|
|
||||||
directoryName = TrimSeparatorsRegex.Replace(directoryName, string.Empty);
|
|
||||||
|
|
||||||
return Path.Combine(parentDirectoryPath, directoryName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec)
|
public BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec)
|
||||||
{
|
{
|
||||||
return new BasicNamingConfig(); //For now let's be lazy
|
return new BasicNamingConfig(); //For now let's be lazy
|
||||||
|
@@ -46,7 +46,6 @@ namespace Radarr.Api.V3.Config
|
|||||||
FileDate = model.FileDate,
|
FileDate = model.FileDate,
|
||||||
RescanAfterRefresh = model.RescanAfterRefresh,
|
RescanAfterRefresh = model.RescanAfterRefresh,
|
||||||
AutoRenameFolders = model.AutoRenameFolders,
|
AutoRenameFolders = model.AutoRenameFolders,
|
||||||
PathsDefaultStatic = model.PathsDefaultStatic,
|
|
||||||
|
|
||||||
SetPermissionsLinux = model.SetPermissionsLinux,
|
SetPermissionsLinux = model.SetPermissionsLinux,
|
||||||
FileChmod = model.FileChmod,
|
FileChmod = model.FileChmod,
|
||||||
|
@@ -85,7 +85,7 @@ namespace Radarr.Api.V3.Movies
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseWithCode(_movieService.UpdateMovie(moviesToUpdate)
|
return ResponseWithCode(_movieService.UpdateMovie(moviesToUpdate, !resource.MoveFiles)
|
||||||
.ToResource(),
|
.ToResource(),
|
||||||
HttpStatusCode.Accepted);
|
HttpStatusCode.Accepted);
|
||||||
}
|
}
|
||||||
|
@@ -7,8 +7,10 @@ using NzbDrone.Core.DecisionEngine.Specifications;
|
|||||||
using NzbDrone.Core.MediaCover;
|
using NzbDrone.Core.MediaCover;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
|
using NzbDrone.Core.Movies.Commands;
|
||||||
using NzbDrone.Core.Movies.Events;
|
using NzbDrone.Core.Movies.Events;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
using NzbDrone.Core.Validation.Paths;
|
using NzbDrone.Core.Validation.Paths;
|
||||||
@@ -29,11 +31,13 @@ namespace Radarr.Api.V3.Movies
|
|||||||
{
|
{
|
||||||
protected readonly IMovieService _moviesService;
|
protected readonly IMovieService _moviesService;
|
||||||
private readonly IMapCoversToLocal _coverMapper;
|
private readonly IMapCoversToLocal _coverMapper;
|
||||||
|
private readonly IManageCommandQueue _commandQueueManager;
|
||||||
private readonly IUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly IUpgradableSpecification _qualityUpgradableSpecification;
|
||||||
|
|
||||||
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||||
IMovieService moviesService,
|
IMovieService moviesService,
|
||||||
IMapCoversToLocal coverMapper,
|
IMapCoversToLocal coverMapper,
|
||||||
|
IManageCommandQueue commandQueueManager,
|
||||||
IUpgradableSpecification qualityUpgradableSpecification,
|
IUpgradableSpecification qualityUpgradableSpecification,
|
||||||
RootFolderValidator rootFolderValidator,
|
RootFolderValidator rootFolderValidator,
|
||||||
MoviePathValidator moviesPathValidator,
|
MoviePathValidator moviesPathValidator,
|
||||||
@@ -46,6 +50,7 @@ namespace Radarr.Api.V3.Movies
|
|||||||
_moviesService = moviesService;
|
_moviesService = moviesService;
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||||
_coverMapper = coverMapper;
|
_coverMapper = coverMapper;
|
||||||
|
_commandQueueManager = commandQueueManager;
|
||||||
|
|
||||||
GetResourceAll = AllMovie;
|
GetResourceAll = AllMovie;
|
||||||
GetResourceById = GetMovie;
|
GetResourceById = GetMovie;
|
||||||
@@ -114,7 +119,24 @@ namespace Radarr.Api.V3.Movies
|
|||||||
|
|
||||||
private void UpdateMovie(MovieResource moviesResource)
|
private void UpdateMovie(MovieResource moviesResource)
|
||||||
{
|
{
|
||||||
var model = moviesResource.ToModel(_moviesService.GetMovie(moviesResource.Id));
|
var moveFiles = Request.GetBooleanQueryParameter("moveFiles");
|
||||||
|
var movie = _moviesService.GetMovie(moviesResource.Id);
|
||||||
|
|
||||||
|
if (moveFiles)
|
||||||
|
{
|
||||||
|
var sourcePath = movie.Path;
|
||||||
|
var destinationPath = moviesResource.Path;
|
||||||
|
|
||||||
|
_commandQueueManager.Push(new MoveMovieCommand
|
||||||
|
{
|
||||||
|
MovieId = movie.Id,
|
||||||
|
SourcePath = sourcePath,
|
||||||
|
DestinationPath = destinationPath,
|
||||||
|
Trigger = CommandTrigger.Manual
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var model = moviesResource.ToModel(movie);
|
||||||
|
|
||||||
_moviesService.UpdateMovie(model);
|
_moviesService.UpdateMovie(model);
|
||||||
|
|
||||||
|
@@ -45,7 +45,6 @@ namespace Radarr.Api.V3.Movies
|
|||||||
//View & Edit
|
//View & Edit
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
public int QualityProfileId { get; set; }
|
public int QualityProfileId { get; set; }
|
||||||
public MoviePathState PathState { get; set; }
|
|
||||||
|
|
||||||
//Editing Only
|
//Editing Only
|
||||||
public bool Monitored { get; set; }
|
public bool Monitored { get; set; }
|
||||||
@@ -105,7 +104,6 @@ namespace Radarr.Api.V3.Movies
|
|||||||
|
|
||||||
Path = model.Path,
|
Path = model.Path,
|
||||||
QualityProfileId = model.ProfileId,
|
QualityProfileId = model.ProfileId,
|
||||||
PathState = model.PathState,
|
|
||||||
|
|
||||||
Monitored = model.Monitored,
|
Monitored = model.Monitored,
|
||||||
MinimumAvailability = model.MinimumAvailability,
|
MinimumAvailability = model.MinimumAvailability,
|
||||||
@@ -166,7 +164,6 @@ namespace Radarr.Api.V3.Movies
|
|||||||
|
|
||||||
Path = model.Path,
|
Path = model.Path,
|
||||||
QualityProfileId = model.ProfileId,
|
QualityProfileId = model.ProfileId,
|
||||||
PathState = model.PathState,
|
|
||||||
|
|
||||||
Monitored = model.Monitored,
|
Monitored = model.Monitored,
|
||||||
MinimumAvailability = model.MinimumAvailability,
|
MinimumAvailability = model.MinimumAvailability,
|
||||||
@@ -221,7 +218,6 @@ namespace Radarr.Api.V3.Movies
|
|||||||
|
|
||||||
Path = resource.Path,
|
Path = resource.Path,
|
||||||
ProfileId = resource.QualityProfileId,
|
ProfileId = resource.QualityProfileId,
|
||||||
PathState = resource.PathState,
|
|
||||||
|
|
||||||
Monitored = resource.Monitored,
|
Monitored = resource.Monitored,
|
||||||
MinimumAvailability = resource.MinimumAvailability,
|
MinimumAvailability = resource.MinimumAvailability,
|
||||||
|
Reference in New Issue
Block a user