2020-01-19 23:43:26 +00:00
using System ;
2017-01-03 19:24:55 +00:00
using System.IO ;
using System.Linq ;
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 ;
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 IMovieService _movieService ;
private readonly IUpdateMovieFileService _updateMovieFileService ;
private readonly IBuildFileNames _buildFileNames ;
private readonly IDiskTransferService _diskTransferService ;
private readonly IDiskProvider _diskProvider ;
private readonly IMediaFileAttributeService _mediaFileAttributeService ;
2017-04-26 11:31:55 +00:00
private readonly IRecycleBinProvider _recycleBinProvider ;
2017-01-03 19:24:55 +00:00
private readonly IEventAggregator _eventAggregator ;
private readonly IConfigService _configService ;
private readonly Logger _logger ;
public MovieFileMovingService ( IMovieService movieService ,
IUpdateMovieFileService updateMovieFileService ,
IBuildFileNames buildFileNames ,
IDiskTransferService diskTransferService ,
IDiskProvider diskProvider ,
IMediaFileAttributeService mediaFileAttributeService ,
2017-04-26 11:31:55 +00:00
IRecycleBinProvider recycleBinProvider ,
2017-01-03 19:24:55 +00:00
IEventAggregator eventAggregator ,
IConfigService configService ,
Logger logger )
{
_movieService = movieService ;
_updateMovieFileService = updateMovieFileService ;
_buildFileNames = buildFileNames ;
_diskTransferService = diskTransferService ;
_diskProvider = diskProvider ;
_mediaFileAttributeService = mediaFileAttributeService ;
2017-04-26 11:31:55 +00:00
_recycleBinProvider = recycleBinProvider ;
2017-01-03 19:24:55 +00:00
_eventAggregator = eventAggregator ;
_configService = configService ;
_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
2017-01-03 19:24:55 +00:00
return TransferFile ( movieFile , localMovie . Movie , filePath , TransferMode . Move ) ;
}
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 ) ;
return TransferFile ( movieFile , localMovie . Movie , filePath , TransferMode . HardLinkOrCopy ) ;
}
_logger . Debug ( "Copying movie file: {0} to {1}" , movieFile . Path , filePath ) ;
return TransferFile ( movieFile , localMovie . Movie , filePath , TransferMode . Copy ) ;
}
2018-02-02 12:23:29 +00:00
2017-01-03 19:24:55 +00:00
private MovieFile TransferFile ( MovieFile movieFile , Movie movie , string destinationFilePath , TransferMode mode )
{
Ensure . That ( movieFile , ( ) = > movieFile ) . IsNotNull ( ) ;
2019-12-22 22:08:53 +00:00
Ensure . That ( movie , ( ) = > movie ) . IsNotNull ( ) ;
2017-01-03 19:24:55 +00:00
Ensure . That ( destinationFilePath , ( ) = > destinationFilePath ) . IsValidPath ( ) ;
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 ) ;
}
_diskTransferService . TransferFile ( movieFilePath , destinationFilePath , mode ) ;
2017-04-26 11:31:55 +00:00
var oldMoviePath = movie . Path ;
var newMoviePath = new OsPath ( destinationFilePath ) . Directory . FullPath . TrimEnd ( Path . DirectorySeparatorChar ) ;
2018-02-02 12:23:29 +00:00
movie . Path = newMoviePath ; //We update it when everything went well!
2017-04-26 11:31:55 +00:00
2017-01-26 22:58:19 +00:00
movieFile . RelativePath = movie . Path . GetRelativePath ( destinationFilePath ) ;
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 ) ;
2019-12-22 22:08:53 +00:00
if ( oldMoviePath ! = newMoviePath & & _diskProvider . FolderExists ( oldMoviePath ) )
2017-04-26 11:31:55 +00:00
{
2018-02-02 12:23:29 +00:00
//Let's move the old files before deleting the old folder. We could just do move folder, but the main file (movie file) is already moved, so eh.
var files = _diskProvider . GetFiles ( oldMoviePath , SearchOption . AllDirectories ) ;
foreach ( var file in files )
{
try
{
var destFile = Path . Combine ( newMoviePath , oldMoviePath . GetRelativePath ( file ) ) ;
_diskProvider . EnsureFolder ( Path . GetDirectoryName ( destFile ) ) ;
_diskProvider . MoveFile ( file , destFile ) ;
}
catch ( Exception e )
{
_logger . Warn ( e , "Error while trying to move extra file {0} to new folder. Maybe it already exists? (Manual cleanup necessary!)." , oldMoviePath . GetRelativePath ( file ) ) ;
}
}
2017-04-26 11:31:55 +00:00
if ( _diskProvider . GetFiles ( oldMoviePath , SearchOption . AllDirectories ) . Count ( ) = = 0 )
{
_recycleBinProvider . DeleteFolder ( oldMoviePath ) ;
}
}
2018-02-02 12:23:29 +00:00
//Only update the movie path if we were successfull!
if ( oldMoviePath ! = newMoviePath )
{
_movieService . UpdateMovie ( movie ) ;
}
2017-01-03 19:24:55 +00:00
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
{
var movieFolder = Path . GetDirectoryName ( filePath ) ;
2019-12-22 22:08:53 +00:00
//movie.Path = movieFolder;
2017-01-03 19:24:55 +00:00
var rootFolder = new OsPath ( movieFolder ) . Directory . FullPath ;
2017-04-26 11:31:55 +00:00
var fileName = Path . GetFileName ( filePath ) ;
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 ;
}
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 ) ;
}
}
}