2020-01-19 23:43:26 +00:00
|
|
|
using System;
|
2017-01-03 19:24:55 +00:00
|
|
|
using System.IO;
|
|
|
|
using NLog;
|
|
|
|
using NzbDrone.Common.Disk;
|
|
|
|
using NzbDrone.Common.EnsureThat;
|
|
|
|
using NzbDrone.Common.Extensions;
|
|
|
|
using NzbDrone.Core.Configuration;
|
|
|
|
using NzbDrone.Core.MediaFiles.Events;
|
2020-01-16 02:52:45 +00:00
|
|
|
using NzbDrone.Core.MediaFiles.MovieImport;
|
2017-01-03 19:24:55 +00:00
|
|
|
using NzbDrone.Core.Messaging.Events;
|
2019-12-22 22:08:53 +00:00
|
|
|
using NzbDrone.Core.Movies;
|
2017-01-03 19:24:55 +00:00
|
|
|
using NzbDrone.Core.Organizer;
|
|
|
|
using NzbDrone.Core.Parser.Model;
|
2020-11-13 03:55:16 +00:00
|
|
|
using NzbDrone.Core.RootFolders;
|
2017-01-03 19:24:55 +00:00
|
|
|
|
|
|
|
namespace NzbDrone.Core.MediaFiles
|
|
|
|
{
|
|
|
|
public interface IMoveMovieFiles
|
|
|
|
{
|
|
|
|
MovieFile MoveMovieFile(MovieFile movieFile, Movie movie);
|
|
|
|
MovieFile MoveMovieFile(MovieFile movieFile, LocalMovie localMovie);
|
|
|
|
MovieFile CopyMovieFile(MovieFile movieFile, LocalMovie localMovie);
|
|
|
|
}
|
|
|
|
|
|
|
|
public class MovieFileMovingService : IMoveMovieFiles
|
|
|
|
{
|
|
|
|
private readonly IUpdateMovieFileService _updateMovieFileService;
|
|
|
|
private readonly IBuildFileNames _buildFileNames;
|
|
|
|
private readonly IDiskTransferService _diskTransferService;
|
|
|
|
private readonly IDiskProvider _diskProvider;
|
|
|
|
private readonly IMediaFileAttributeService _mediaFileAttributeService;
|
2023-05-23 03:36:17 +00:00
|
|
|
private readonly IImportScript _scriptImportDecider;
|
2017-01-03 19:24:55 +00:00
|
|
|
private readonly IEventAggregator _eventAggregator;
|
|
|
|
private readonly IConfigService _configService;
|
2020-11-13 03:55:16 +00:00
|
|
|
private readonly IRootFolderService _rootFolderService;
|
2017-01-03 19:24:55 +00:00
|
|
|
private readonly Logger _logger;
|
|
|
|
|
2020-02-27 03:11:53 +00:00
|
|
|
public MovieFileMovingService(IUpdateMovieFileService updateMovieFileService,
|
2017-01-03 19:24:55 +00:00
|
|
|
IBuildFileNames buildFileNames,
|
|
|
|
IDiskTransferService diskTransferService,
|
|
|
|
IDiskProvider diskProvider,
|
|
|
|
IMediaFileAttributeService mediaFileAttributeService,
|
2023-05-23 03:36:17 +00:00
|
|
|
IImportScript scriptImportDecider,
|
2017-01-03 19:24:55 +00:00
|
|
|
IEventAggregator eventAggregator,
|
|
|
|
IConfigService configService,
|
2020-11-13 03:55:16 +00:00
|
|
|
IRootFolderService rootFolderService,
|
2017-01-03 19:24:55 +00:00
|
|
|
Logger logger)
|
|
|
|
{
|
|
|
|
_updateMovieFileService = updateMovieFileService;
|
|
|
|
_buildFileNames = buildFileNames;
|
|
|
|
_diskTransferService = diskTransferService;
|
|
|
|
_diskProvider = diskProvider;
|
|
|
|
_mediaFileAttributeService = mediaFileAttributeService;
|
2023-05-23 03:36:17 +00:00
|
|
|
_scriptImportDecider = scriptImportDecider;
|
2017-01-03 19:24:55 +00:00
|
|
|
_eventAggregator = eventAggregator;
|
|
|
|
_configService = configService;
|
2020-11-13 03:55:16 +00:00
|
|
|
_rootFolderService = rootFolderService;
|
2017-01-03 19:24:55 +00:00
|
|
|
_logger = logger;
|
|
|
|
}
|
|
|
|
|
|
|
|
public MovieFile MoveMovieFile(MovieFile movieFile, Movie movie)
|
|
|
|
{
|
|
|
|
var newFileName = _buildFileNames.BuildFileName(movie, movieFile);
|
|
|
|
var filePath = _buildFileNames.BuildFilePath(movie, newFileName, Path.GetExtension(movieFile.RelativePath));
|
|
|
|
|
2017-01-26 01:11:02 +00:00
|
|
|
EnsureMovieFolder(movieFile, movie, filePath);
|
2017-01-03 19:24:55 +00:00
|
|
|
|
|
|
|
_logger.Debug("Renaming movie file: {0} to {1}", movieFile, filePath);
|
2018-02-02 12:23:29 +00:00
|
|
|
|
2017-01-03 19:24:55 +00:00
|
|
|
return TransferFile(movieFile, movie, filePath, TransferMode.Move);
|
|
|
|
}
|
|
|
|
|
|
|
|
public MovieFile MoveMovieFile(MovieFile movieFile, LocalMovie localMovie)
|
|
|
|
{
|
|
|
|
var newFileName = _buildFileNames.BuildFileName(localMovie.Movie, movieFile);
|
|
|
|
var filePath = _buildFileNames.BuildFilePath(localMovie.Movie, newFileName, Path.GetExtension(localMovie.Path));
|
|
|
|
|
2017-01-26 01:11:02 +00:00
|
|
|
EnsureMovieFolder(movieFile, localMovie, filePath);
|
2017-01-03 19:24:55 +00:00
|
|
|
|
|
|
|
_logger.Debug("Moving movie file: {0} to {1}", movieFile.Path, filePath);
|
2018-02-02 12:23:29 +00:00
|
|
|
|
2023-05-23 03:36:17 +00:00
|
|
|
return TransferFile(movieFile, localMovie.Movie, filePath, TransferMode.Move, localMovie);
|
2017-01-03 19:24:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public MovieFile CopyMovieFile(MovieFile movieFile, LocalMovie localMovie)
|
|
|
|
{
|
|
|
|
var newFileName = _buildFileNames.BuildFileName(localMovie.Movie, movieFile);
|
|
|
|
var filePath = _buildFileNames.BuildFilePath(localMovie.Movie, newFileName, Path.GetExtension(localMovie.Path));
|
|
|
|
|
2017-01-26 01:11:02 +00:00
|
|
|
EnsureMovieFolder(movieFile, localMovie, filePath);
|
2017-01-03 19:24:55 +00:00
|
|
|
|
|
|
|
if (_configService.CopyUsingHardlinks)
|
|
|
|
{
|
|
|
|
_logger.Debug("Hardlinking movie file: {0} to {1}", movieFile.Path, filePath);
|
2023-05-23 03:36:17 +00:00
|
|
|
return TransferFile(movieFile, localMovie.Movie, filePath, TransferMode.HardLinkOrCopy, localMovie);
|
2017-01-03 19:24:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_logger.Debug("Copying movie file: {0} to {1}", movieFile.Path, filePath);
|
2023-05-23 03:36:17 +00:00
|
|
|
return TransferFile(movieFile, localMovie.Movie, filePath, TransferMode.Copy, localMovie);
|
2017-01-03 19:24:55 +00:00
|
|
|
}
|
2018-02-02 12:23:29 +00:00
|
|
|
|
2023-05-23 03:36:17 +00:00
|
|
|
private MovieFile TransferFile(MovieFile movieFile, Movie movie, string destinationFilePath, TransferMode mode, LocalMovie localMovie = null)
|
2017-01-03 19:24:55 +00:00
|
|
|
{
|
|
|
|
Ensure.That(movieFile, () => movieFile).IsNotNull();
|
2019-12-22 22:08:53 +00:00
|
|
|
Ensure.That(movie, () => movie).IsNotNull();
|
2023-03-24 00:34:19 +00:00
|
|
|
Ensure.That(destinationFilePath, () => destinationFilePath).IsValidPath(PathValidationType.CurrentOs);
|
2017-01-03 19:24:55 +00:00
|
|
|
|
|
|
|
var movieFilePath = movieFile.Path ?? Path.Combine(movie.Path, movieFile.RelativePath);
|
|
|
|
|
|
|
|
if (!_diskProvider.FileExists(movieFilePath))
|
|
|
|
{
|
|
|
|
throw new FileNotFoundException("Movie file path does not exist", movieFilePath);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (movieFilePath == destinationFilePath)
|
|
|
|
{
|
|
|
|
throw new SameFilenameException("File not moved, source and destination are the same", movieFilePath);
|
|
|
|
}
|
|
|
|
|
2017-01-26 22:58:19 +00:00
|
|
|
movieFile.RelativePath = movie.Path.GetRelativePath(destinationFilePath);
|
2017-01-03 19:24:55 +00:00
|
|
|
|
2023-08-16 19:56:44 +00:00
|
|
|
if (localMovie is not null && _scriptImportDecider.TryImport(movieFilePath, destinationFilePath, localMovie, movieFile, mode) is var scriptImportDecision && scriptImportDecision != ScriptImportDecision.DeferMove)
|
2023-05-23 03:36:17 +00:00
|
|
|
{
|
2023-08-16 19:56:44 +00:00
|
|
|
if (scriptImportDecision == ScriptImportDecision.RenameRequested)
|
2023-05-23 03:36:17 +00:00
|
|
|
{
|
2023-08-16 19:56:44 +00:00
|
|
|
try
|
|
|
|
{
|
2023-05-23 03:36:17 +00:00
|
|
|
MoveMovieFile(movieFile, movie);
|
2023-08-16 19:56:44 +00:00
|
|
|
}
|
|
|
|
catch (SameFilenameException)
|
|
|
|
{
|
|
|
|
_logger.Debug("No rename was required. File already exists at destination.");
|
|
|
|
}
|
2023-05-23 03:36:17 +00:00
|
|
|
}
|
|
|
|
}
|
2023-08-16 19:56:44 +00:00
|
|
|
else
|
2023-05-23 03:36:17 +00:00
|
|
|
{
|
|
|
|
_diskTransferService.TransferFile(movieFilePath, destinationFilePath, mode);
|
|
|
|
}
|
|
|
|
|
2017-01-03 19:24:55 +00:00
|
|
|
_updateMovieFileService.ChangeFileDateForFile(movieFile, movie);
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
_mediaFileAttributeService.SetFolderLastWriteTime(movie.Path, movieFile.DateAdded);
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
_logger.Warn(ex, "Unable to set last write time");
|
|
|
|
}
|
|
|
|
|
|
|
|
_mediaFileAttributeService.SetFilePermissions(destinationFilePath);
|
|
|
|
|
|
|
|
return movieFile;
|
|
|
|
}
|
|
|
|
|
2017-01-26 01:11:02 +00:00
|
|
|
private void EnsureMovieFolder(MovieFile movieFile, LocalMovie localMovie, string filePath)
|
2017-01-03 19:24:55 +00:00
|
|
|
{
|
2017-01-26 01:11:02 +00:00
|
|
|
EnsureMovieFolder(movieFile, localMovie.Movie, filePath);
|
2017-01-03 19:24:55 +00:00
|
|
|
}
|
|
|
|
|
2017-01-26 01:11:02 +00:00
|
|
|
private void EnsureMovieFolder(MovieFile movieFile, Movie movie, string filePath)
|
2017-01-03 19:24:55 +00:00
|
|
|
{
|
2020-02-27 03:11:53 +00:00
|
|
|
var movieFileFolder = Path.GetDirectoryName(filePath);
|
2019-12-22 22:08:53 +00:00
|
|
|
|
2020-02-27 03:11:53 +00:00
|
|
|
var movieFolder = movie.Path;
|
2020-11-13 03:55:16 +00:00
|
|
|
var rootFolder = _rootFolderService.GetBestRootFolderPath(movieFolder);
|
2017-01-03 19:24:55 +00:00
|
|
|
|
|
|
|
if (!_diskProvider.FolderExists(rootFolder))
|
|
|
|
{
|
2020-01-16 02:52:45 +00:00
|
|
|
throw new RootFolderNotFoundException(string.Format("Root folder '{0}' was not found.", rootFolder));
|
2017-01-03 19:24:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var changed = false;
|
|
|
|
var newEvent = new MovieFolderCreatedEvent(movie, movieFile);
|
|
|
|
|
|
|
|
if (!_diskProvider.FolderExists(movieFolder))
|
|
|
|
{
|
|
|
|
CreateFolder(movieFolder);
|
2017-04-26 11:31:55 +00:00
|
|
|
newEvent.MovieFolder = movieFolder;
|
2017-01-03 19:24:55 +00:00
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
|
2020-02-27 03:11:53 +00:00
|
|
|
if (movieFolder != movieFileFolder && !_diskProvider.FolderExists(movieFileFolder))
|
|
|
|
{
|
|
|
|
CreateFolder(movieFileFolder);
|
|
|
|
newEvent.MovieFileFolder = movieFileFolder;
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
|
2017-01-03 19:24:55 +00:00
|
|
|
if (changed)
|
|
|
|
{
|
|
|
|
_eventAggregator.PublishEvent(newEvent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void CreateFolder(string directoryName)
|
|
|
|
{
|
|
|
|
Ensure.That(directoryName, () => directoryName).IsNotNullOrWhiteSpace();
|
|
|
|
|
|
|
|
var parentFolder = new OsPath(directoryName).Directory.FullPath;
|
|
|
|
if (!_diskProvider.FolderExists(parentFolder))
|
|
|
|
{
|
|
|
|
CreateFolder(parentFolder);
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
_diskProvider.CreateFolder(directoryName);
|
|
|
|
}
|
|
|
|
catch (IOException ex)
|
|
|
|
{
|
2020-01-19 23:43:26 +00:00
|
|
|
_logger.Error(ex, "Unable to create directory: {0}", directoryName);
|
2017-01-03 19:24:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_mediaFileAttributeService.SetFolderPermissions(directoryName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|