mirror of https://github.com/lidarr/Lidarr
New: Option to Import via Script
(cherry picked from commit 9f1e2151206a077334a9c34a12a373b465752d87)
This commit is contained in:
parent
f38f00c64e
commit
c8a950eb40
|
@ -68,29 +68,29 @@ class MediaManagement extends Component {
|
||||||
<NamingConnector />
|
<NamingConnector />
|
||||||
|
|
||||||
{
|
{
|
||||||
isFetching &&
|
isFetching ?
|
||||||
<FieldSet legend={translate('NamingSettings')}>
|
<FieldSet legend={translate('NamingSettings')}>
|
||||||
<LoadingIndicator />
|
<LoadingIndicator />
|
||||||
</FieldSet>
|
</FieldSet> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
!isFetching && error &&
|
!isFetching && error ?
|
||||||
<FieldSet legend={translate('NamingSettings')}>
|
<FieldSet legend={translate('NamingSettings')}>
|
||||||
<div>
|
<div>
|
||||||
{translate('UnableToLoadMediaManagementSettings')}
|
{translate('UnableToLoadMediaManagementSettings')}
|
||||||
</div>
|
</div>
|
||||||
</FieldSet>
|
</FieldSet> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
hasSettings && !isFetching && !error &&
|
hasSettings && !isFetching && !error ?
|
||||||
<Form
|
<Form
|
||||||
id="mediaManagementSettings"
|
id="mediaManagementSettings"
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
advancedSettings &&
|
advancedSettings ?
|
||||||
<FieldSet legend={translate('Folders')}>
|
<FieldSet legend={translate('Folders')}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
advancedSettings={advancedSettings}
|
advancedSettings={advancedSettings}
|
||||||
|
@ -127,11 +127,11 @@ class MediaManagement extends Component {
|
||||||
{...settings.deleteEmptyFolders}
|
{...settings.deleteEmptyFolders}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</FieldSet>
|
</FieldSet> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
advancedSettings &&
|
advancedSettings ?
|
||||||
<FieldSet
|
<FieldSet
|
||||||
legend={translate('Importing')}
|
legend={translate('Importing')}
|
||||||
>
|
>
|
||||||
|
@ -194,6 +194,41 @@ class MediaManagement extends Component {
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup
|
||||||
|
advancedSettings={advancedSettings}
|
||||||
|
isAdvanced={true}
|
||||||
|
size={sizes.MEDIUM}
|
||||||
|
>
|
||||||
|
<FormLabel>{translate('ImportUsingScript')}</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.CHECK}
|
||||||
|
name="useScriptImport"
|
||||||
|
helpText={translate('UseScriptImportHelpText')}
|
||||||
|
onChange={onInputChange}
|
||||||
|
{...settings.useScriptImport}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
{
|
||||||
|
settings.useScriptImport.value ?
|
||||||
|
<FormGroup
|
||||||
|
advancedSettings={advancedSettings}
|
||||||
|
isAdvanced={true}
|
||||||
|
>
|
||||||
|
<FormLabel>{translate('ImportScriptPath')}</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.PATH}
|
||||||
|
includeFiles={true}
|
||||||
|
name="scriptImportPath"
|
||||||
|
helpText={translate('ScriptImportPathHelpText')}
|
||||||
|
onChange={onInputChange}
|
||||||
|
{...settings.scriptImportPath}
|
||||||
|
/>
|
||||||
|
</FormGroup> : null
|
||||||
|
}
|
||||||
|
|
||||||
<FormGroup size={sizes.MEDIUM}>
|
<FormGroup size={sizes.MEDIUM}>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
{translate('ImportExtraFiles')}
|
{translate('ImportExtraFiles')}
|
||||||
|
@ -209,7 +244,7 @@ class MediaManagement extends Component {
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
{
|
{
|
||||||
settings.importExtraFiles.value &&
|
settings.importExtraFiles.value ?
|
||||||
<FormGroup
|
<FormGroup
|
||||||
advancedSettings={advancedSettings}
|
advancedSettings={advancedSettings}
|
||||||
isAdvanced={true}
|
isAdvanced={true}
|
||||||
|
@ -228,9 +263,9 @@ class MediaManagement extends Component {
|
||||||
onChange={onInputChange}
|
onChange={onInputChange}
|
||||||
{...settings.extraFileExtensions}
|
{...settings.extraFileExtensions}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup> : null
|
||||||
}
|
}
|
||||||
</FieldSet>
|
</FieldSet> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
<FieldSet
|
<FieldSet
|
||||||
|
@ -375,7 +410,7 @@ class MediaManagement extends Component {
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
|
|
||||||
{
|
{
|
||||||
advancedSettings && !isWindows &&
|
advancedSettings && !isWindows ?
|
||||||
<FieldSet
|
<FieldSet
|
||||||
legend={translate('Permissions')}
|
legend={translate('Permissions')}
|
||||||
>
|
>
|
||||||
|
@ -434,9 +469,9 @@ class MediaManagement extends Component {
|
||||||
{...settings.chownGroup}
|
{...settings.chownGroup}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</FieldSet>
|
</FieldSet> : null
|
||||||
}
|
}
|
||||||
</Form>
|
</Form> : null
|
||||||
}
|
}
|
||||||
</PageContentBody>
|
</PageContentBody>
|
||||||
</PageContent>
|
</PageContent>
|
||||||
|
|
|
@ -32,6 +32,9 @@ namespace Lidarr.Api.V1.Config
|
||||||
.When(c => !string.IsNullOrWhiteSpace(c.RecycleBin));
|
.When(c => !string.IsNullOrWhiteSpace(c.RecycleBin));
|
||||||
SharedValidator.RuleFor(c => c.RecycleBinCleanupDays).GreaterThanOrEqualTo(0);
|
SharedValidator.RuleFor(c => c.RecycleBinCleanupDays).GreaterThanOrEqualTo(0);
|
||||||
SharedValidator.RuleFor(c => c.ChmodFolder).SetValidator(folderChmodValidator).When(c => !string.IsNullOrEmpty(c.ChmodFolder) && (OsInfo.IsLinux || OsInfo.IsOsx));
|
SharedValidator.RuleFor(c => c.ChmodFolder).SetValidator(folderChmodValidator).When(c => !string.IsNullOrEmpty(c.ChmodFolder) && (OsInfo.IsLinux || OsInfo.IsOsx));
|
||||||
|
|
||||||
|
SharedValidator.RuleFor(c => c.ScriptImportPath).IsValidPath().When(c => c.UseScriptImport);
|
||||||
|
|
||||||
SharedValidator.RuleFor(c => c.MinimumFreeSpaceWhenImporting).GreaterThanOrEqualTo(100);
|
SharedValidator.RuleFor(c => c.MinimumFreeSpaceWhenImporting).GreaterThanOrEqualTo(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@ namespace Lidarr.Api.V1.Config
|
||||||
public bool SkipFreeSpaceCheckWhenImporting { get; set; }
|
public bool SkipFreeSpaceCheckWhenImporting { get; set; }
|
||||||
public int MinimumFreeSpaceWhenImporting { get; set; }
|
public int MinimumFreeSpaceWhenImporting { get; set; }
|
||||||
public bool CopyUsingHardlinks { get; set; }
|
public bool CopyUsingHardlinks { get; set; }
|
||||||
|
public bool UseScriptImport { get; set; }
|
||||||
|
public string ScriptImportPath { get; set; }
|
||||||
public bool ImportExtraFiles { get; set; }
|
public bool ImportExtraFiles { get; set; }
|
||||||
public string ExtraFileExtensions { get; set; }
|
public string ExtraFileExtensions { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -53,6 +55,8 @@ namespace Lidarr.Api.V1.Config
|
||||||
SkipFreeSpaceCheckWhenImporting = model.SkipFreeSpaceCheckWhenImporting,
|
SkipFreeSpaceCheckWhenImporting = model.SkipFreeSpaceCheckWhenImporting,
|
||||||
MinimumFreeSpaceWhenImporting = model.MinimumFreeSpaceWhenImporting,
|
MinimumFreeSpaceWhenImporting = model.MinimumFreeSpaceWhenImporting,
|
||||||
CopyUsingHardlinks = model.CopyUsingHardlinks,
|
CopyUsingHardlinks = model.CopyUsingHardlinks,
|
||||||
|
UseScriptImport = model.UseScriptImport,
|
||||||
|
ScriptImportPath = model.ScriptImportPath,
|
||||||
ImportExtraFiles = model.ImportExtraFiles,
|
ImportExtraFiles = model.ImportExtraFiles,
|
||||||
ExtraFileExtensions = model.ExtraFileExtensions,
|
ExtraFileExtensions = model.ExtraFileExtensions,
|
||||||
};
|
};
|
||||||
|
|
|
@ -200,6 +200,20 @@ namespace NzbDrone.Core.Configuration
|
||||||
set { SetValue("CopyUsingHardlinks", value); }
|
set { SetValue("CopyUsingHardlinks", value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool UseScriptImport
|
||||||
|
{
|
||||||
|
get { return GetValueBoolean("UseScriptImport", false); }
|
||||||
|
|
||||||
|
set { SetValue("UseScriptImport", value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ScriptImportPath
|
||||||
|
{
|
||||||
|
get { return GetValue("ScriptImportPath"); }
|
||||||
|
|
||||||
|
set { SetValue("ScriptImportPath", value); }
|
||||||
|
}
|
||||||
|
|
||||||
public bool ImportExtraFiles
|
public bool ImportExtraFiles
|
||||||
{
|
{
|
||||||
get { return GetValueBoolean("ImportExtraFiles", false); }
|
get { return GetValueBoolean("ImportExtraFiles", false); }
|
||||||
|
|
|
@ -32,6 +32,8 @@ namespace NzbDrone.Core.Configuration
|
||||||
bool SkipFreeSpaceCheckWhenImporting { get; set; }
|
bool SkipFreeSpaceCheckWhenImporting { get; set; }
|
||||||
int MinimumFreeSpaceWhenImporting { get; set; }
|
int MinimumFreeSpaceWhenImporting { get; set; }
|
||||||
bool CopyUsingHardlinks { get; set; }
|
bool CopyUsingHardlinks { get; set; }
|
||||||
|
bool UseScriptImport { get; set; }
|
||||||
|
string ScriptImportPath { get; set; }
|
||||||
bool ImportExtraFiles { get; set; }
|
bool ImportExtraFiles { get; set; }
|
||||||
string ExtraFileExtensions { get; set; }
|
string ExtraFileExtensions { get; set; }
|
||||||
bool WatchLibraryForChanges { get; set; }
|
bool WatchLibraryForChanges { get; set; }
|
||||||
|
|
|
@ -392,6 +392,8 @@
|
||||||
"ImportListStatusCheckSingleClientMessage": "Lists unavailable due to failures: {0}",
|
"ImportListStatusCheckSingleClientMessage": "Lists unavailable due to failures: {0}",
|
||||||
"ImportLists": "Import Lists",
|
"ImportLists": "Import Lists",
|
||||||
"ImportMechanismHealthCheckMessage": "Enable Completed Download Handling",
|
"ImportMechanismHealthCheckMessage": "Enable Completed Download Handling",
|
||||||
|
"ImportScriptPath": "Import Script Path",
|
||||||
|
"ImportUsingScript": "Import Using Script",
|
||||||
"ImportedTo": "Imported To",
|
"ImportedTo": "Imported To",
|
||||||
"Importing": "Importing",
|
"Importing": "Importing",
|
||||||
"Inactive": "Inactive",
|
"Inactive": "Inactive",
|
||||||
|
@ -754,6 +756,7 @@
|
||||||
"SceneInformation": "Scene Information",
|
"SceneInformation": "Scene Information",
|
||||||
"SceneNumberHasntBeenVerifiedYet": "Scene number hasn't been verified yet",
|
"SceneNumberHasntBeenVerifiedYet": "Scene number hasn't been verified yet",
|
||||||
"Scheduled": "Scheduled",
|
"Scheduled": "Scheduled",
|
||||||
|
"ScriptImportPathHelpText": "The path to the script to use for importing",
|
||||||
"ScriptPath": "Script Path",
|
"ScriptPath": "Script Path",
|
||||||
"ScrubAudioTagsHelpText": "Remove existing tags from files, leaving only those added by Lidarr.",
|
"ScrubAudioTagsHelpText": "Remove existing tags from files, leaving only those added by Lidarr.",
|
||||||
"ScrubExistingTags": "Scrub Existing Tags",
|
"ScrubExistingTags": "Scrub Existing Tags",
|
||||||
|
@ -963,6 +966,7 @@
|
||||||
"UrlBaseHelpTextWarning": "Requires restart to take effect",
|
"UrlBaseHelpTextWarning": "Requires restart to take effect",
|
||||||
"UseHardlinksInsteadOfCopy": "Use Hardlinks instead of Copy",
|
"UseHardlinksInsteadOfCopy": "Use Hardlinks instead of Copy",
|
||||||
"UseProxy": "Use Proxy",
|
"UseProxy": "Use Proxy",
|
||||||
|
"UseScriptImportHelpText": "Copy files for importing using a script (ex. for transcoding)",
|
||||||
"Usenet": "Usenet",
|
"Usenet": "Usenet",
|
||||||
"UsenetDelay": "Usenet Delay",
|
"UsenetDelay": "Usenet Delay",
|
||||||
"UsenetDelayHelpText": "Delay in minutes to wait before grabbing a release from Usenet",
|
"UsenetDelayHelpText": "Delay in minutes to wait before grabbing a release from Usenet",
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Common.Processes;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles
|
||||||
|
{
|
||||||
|
public interface IImportScript
|
||||||
|
{
|
||||||
|
public ScriptImportDecision TryImport(string sourcePath, string destinationFilePath, LocalTrack localTrack, TrackFile trackFile, TransferMode mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportScriptService : IImportScript
|
||||||
|
{
|
||||||
|
private readonly IConfigFileProvider _configFileProvider;
|
||||||
|
private readonly IProcessProvider _processProvider;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public ImportScriptService(IProcessProvider processProvider,
|
||||||
|
IConfigService configService,
|
||||||
|
IConfigFileProvider configFileProvider,
|
||||||
|
Logger logger)
|
||||||
|
{
|
||||||
|
_processProvider = processProvider;
|
||||||
|
_configService = configService;
|
||||||
|
_configFileProvider = configFileProvider;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScriptImportDecision TryImport(string sourcePath, string destinationFilePath, LocalTrack localTrack, TrackFile trackFile, TransferMode mode)
|
||||||
|
{
|
||||||
|
var artist = localTrack.Artist;
|
||||||
|
var oldFiles = localTrack.OldFiles;
|
||||||
|
var downloadClientInfo = localTrack.DownloadItem?.DownloadClientInfo;
|
||||||
|
var downloadId = localTrack.DownloadItem?.DownloadId;
|
||||||
|
|
||||||
|
if (!_configService.UseScriptImport)
|
||||||
|
{
|
||||||
|
return ScriptImportDecision.DeferMove;
|
||||||
|
}
|
||||||
|
|
||||||
|
var environmentVariables = new StringDictionary();
|
||||||
|
|
||||||
|
environmentVariables.Add("Lidarr_SourcePath", sourcePath);
|
||||||
|
environmentVariables.Add("Lidarr_DestinationPath", destinationFilePath);
|
||||||
|
|
||||||
|
environmentVariables.Add("Lidarr_InstanceName", _configFileProvider.InstanceName);
|
||||||
|
environmentVariables.Add("Lidarr_ApplicationUrl", _configService.ApplicationUrl);
|
||||||
|
environmentVariables.Add("Lidarr_TransferMode", mode.ToString());
|
||||||
|
|
||||||
|
environmentVariables.Add("Lidarr_Artist_Id", artist.Id.ToString());
|
||||||
|
environmentVariables.Add("Lidarr_Artist_Name", artist.Metadata.Value.Name);
|
||||||
|
environmentVariables.Add("Lidarr_Artist_Path", artist.Path);
|
||||||
|
environmentVariables.Add("Lidarr_Artist_MBId", artist.Metadata.Value.ForeignArtistId);
|
||||||
|
environmentVariables.Add("Lidarr_Artist_Type", artist.Metadata.Value.Type);
|
||||||
|
|
||||||
|
environmentVariables.Add("Lidarr_Album_Id", localTrack.Album.Id.ToString());
|
||||||
|
environmentVariables.Add("Lidarr_Album_Title", localTrack.Album.Title);
|
||||||
|
environmentVariables.Add("Lidarr_Album_Overview", localTrack.Album.Overview);
|
||||||
|
environmentVariables.Add("Lidarr_Album_MBId", localTrack.Album.ForeignAlbumId);
|
||||||
|
environmentVariables.Add("Lidarr_AlbumRelease_MBId", localTrack.Release.ForeignReleaseId);
|
||||||
|
environmentVariables.Add("Lidarr_Album_ReleaseDate", localTrack.Release.ReleaseDate.ToString());
|
||||||
|
|
||||||
|
environmentVariables.Add("Lidarr_Download_Client", downloadClientInfo?.Name ?? string.Empty);
|
||||||
|
environmentVariables.Add("Lidarr_Download_Client_Type", downloadClientInfo?.Type ?? string.Empty);
|
||||||
|
environmentVariables.Add("Lidarr_Download_Id", downloadId ?? string.Empty);
|
||||||
|
|
||||||
|
if (oldFiles.Any())
|
||||||
|
{
|
||||||
|
environmentVariables.Add("Lidarr_DeletedPaths", string.Join("|", oldFiles.Select(e => e.Path)));
|
||||||
|
environmentVariables.Add("Lidarr_DeletedDateAdded", string.Join("|", oldFiles.Select(e => e.DateAdded)));
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Debug("Executing external script: {0}", _configService.ScriptImportPath);
|
||||||
|
|
||||||
|
var processOutput = _processProvider.StartAndCapture(_configService.ScriptImportPath, $"\"{sourcePath}\" \"{destinationFilePath}\"", environmentVariables);
|
||||||
|
|
||||||
|
_logger.Debug("Executed external script: {0} - Status: {1}", _configService.ScriptImportPath, processOutput.ExitCode);
|
||||||
|
_logger.Debug("Script Output: \r\n{0}", string.Join("\r\n", processOutput.Lines));
|
||||||
|
|
||||||
|
switch (processOutput.ExitCode)
|
||||||
|
{
|
||||||
|
case 0: // Copy complete
|
||||||
|
return ScriptImportDecision.MoveComplete;
|
||||||
|
case 2: // Copy complete, file potentially changed, should try renaming again
|
||||||
|
// trackFile.MediaInfo = _videoFileInfoReader.GetMediaInfo(destinationFilePath);
|
||||||
|
trackFile.Path = null;
|
||||||
|
return ScriptImportDecision.RenameRequested;
|
||||||
|
case 3: // Let Lidarr handle it
|
||||||
|
return ScriptImportDecision.DeferMove;
|
||||||
|
default: // Error, fail to import
|
||||||
|
throw new ScriptImportException("Moving with script failed! Exit code {0}", processOutput.ExitCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace NzbDrone.Core.MediaFiles
|
||||||
|
{
|
||||||
|
public enum ScriptImportDecision
|
||||||
|
{
|
||||||
|
MoveComplete,
|
||||||
|
RenameRequested,
|
||||||
|
RejectExtra,
|
||||||
|
DeferMove
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Common.Exceptions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles
|
||||||
|
{
|
||||||
|
public class ScriptImportException : NzbDroneException
|
||||||
|
{
|
||||||
|
public ScriptImportException(string message)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScriptImportException(string message, params object[] args)
|
||||||
|
: base(message, args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScriptImportException(string message, Exception innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
private readonly IDiskProvider _diskProvider;
|
private readonly IDiskProvider _diskProvider;
|
||||||
private readonly IRootFolderWatchingService _rootFolderWatchingService;
|
private readonly IRootFolderWatchingService _rootFolderWatchingService;
|
||||||
private readonly IMediaFileAttributeService _mediaFileAttributeService;
|
private readonly IMediaFileAttributeService _mediaFileAttributeService;
|
||||||
|
private readonly IImportScript _scriptImportDecider;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IConfigService _configService;
|
private readonly IConfigService _configService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
@ -43,6 +44,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
IRootFolderWatchingService rootFolderWatchingService,
|
IRootFolderWatchingService rootFolderWatchingService,
|
||||||
IMediaFileAttributeService mediaFileAttributeService,
|
IMediaFileAttributeService mediaFileAttributeService,
|
||||||
|
IImportScript scriptImportDecider,
|
||||||
IEventAggregator eventAggregator,
|
IEventAggregator eventAggregator,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
|
@ -55,6 +57,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
_rootFolderWatchingService = rootFolderWatchingService;
|
_rootFolderWatchingService = rootFolderWatchingService;
|
||||||
_mediaFileAttributeService = mediaFileAttributeService;
|
_mediaFileAttributeService = mediaFileAttributeService;
|
||||||
|
_scriptImportDecider = scriptImportDecider;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -63,6 +66,11 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
public TrackFile MoveTrackFile(TrackFile trackFile, Artist artist)
|
public TrackFile MoveTrackFile(TrackFile trackFile, Artist artist)
|
||||||
{
|
{
|
||||||
var tracks = _trackService.GetTracksByFileId(trackFile.Id);
|
var tracks = _trackService.GetTracksByFileId(trackFile.Id);
|
||||||
|
return MoveTrackFile(trackFile, artist, tracks);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TrackFile MoveTrackFile(TrackFile trackFile, Artist artist, List<Track> tracks)
|
||||||
|
{
|
||||||
var album = _albumService.GetAlbum(trackFile.AlbumId);
|
var album = _albumService.GetAlbum(trackFile.AlbumId);
|
||||||
var newFileName = _buildFileNames.BuildTrackFileName(tracks, artist, album, trackFile);
|
var newFileName = _buildFileNames.BuildTrackFileName(tracks, artist, album, trackFile);
|
||||||
var filePath = _buildFileNames.BuildTrackFilePath(artist, newFileName, Path.GetExtension(trackFile.Path));
|
var filePath = _buildFileNames.BuildTrackFilePath(artist, newFileName, Path.GetExtension(trackFile.Path));
|
||||||
|
@ -83,7 +91,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
|
|
||||||
_logger.Debug("Moving track file: {0} to {1}", trackFile.Path, filePath);
|
_logger.Debug("Moving track file: {0} to {1}", trackFile.Path, filePath);
|
||||||
|
|
||||||
return TransferFile(trackFile, localTrack.Artist, localTrack.Tracks, filePath, TransferMode.Move);
|
return TransferFile(trackFile, localTrack.Artist, localTrack.Tracks, filePath, TransferMode.Move, localTrack);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrackFile CopyTrackFile(TrackFile trackFile, LocalTrack localTrack)
|
public TrackFile CopyTrackFile(TrackFile trackFile, LocalTrack localTrack)
|
||||||
|
@ -96,14 +104,14 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
if (_configService.CopyUsingHardlinks)
|
if (_configService.CopyUsingHardlinks)
|
||||||
{
|
{
|
||||||
_logger.Debug("Hardlinking track file: {0} to {1}", trackFile.Path, filePath);
|
_logger.Debug("Hardlinking track file: {0} to {1}", trackFile.Path, filePath);
|
||||||
return TransferFile(trackFile, localTrack.Artist, localTrack.Tracks, filePath, TransferMode.HardLinkOrCopy);
|
return TransferFile(trackFile, localTrack.Artist, localTrack.Tracks, filePath, TransferMode.HardLinkOrCopy, localTrack);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug("Copying track file: {0} to {1}", trackFile.Path, filePath);
|
_logger.Debug("Copying track file: {0} to {1}", trackFile.Path, filePath);
|
||||||
return TransferFile(trackFile, localTrack.Artist, localTrack.Tracks, filePath, TransferMode.Copy);
|
return TransferFile(trackFile, localTrack.Artist, localTrack.Tracks, filePath, TransferMode.Copy, localTrack);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TrackFile TransferFile(TrackFile trackFile, Artist artist, List<Track> tracks, string destinationFilePath, TransferMode mode)
|
private TrackFile TransferFile(TrackFile trackFile, Artist artist, List<Track> tracks, string destinationFilePath, TransferMode mode, LocalTrack localTrack = null)
|
||||||
{
|
{
|
||||||
Ensure.That(trackFile, () => trackFile).IsNotNull();
|
Ensure.That(trackFile, () => trackFile).IsNotNull();
|
||||||
Ensure.That(artist, () => artist).IsNotNull();
|
Ensure.That(artist, () => artist).IsNotNull();
|
||||||
|
@ -122,10 +130,34 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
_rootFolderWatchingService.ReportFileSystemChangeBeginning(trackFilePath, destinationFilePath);
|
_rootFolderWatchingService.ReportFileSystemChangeBeginning(trackFilePath, destinationFilePath);
|
||||||
_diskTransferService.TransferFile(trackFilePath, destinationFilePath, mode);
|
|
||||||
|
var transfer = true;
|
||||||
|
|
||||||
trackFile.Path = destinationFilePath;
|
trackFile.Path = destinationFilePath;
|
||||||
|
|
||||||
|
if (localTrack is not null)
|
||||||
|
{
|
||||||
|
var scriptImportDecision = _scriptImportDecider.TryImport(trackFilePath, destinationFilePath, localTrack, trackFile, mode);
|
||||||
|
|
||||||
|
switch (scriptImportDecision)
|
||||||
|
{
|
||||||
|
case ScriptImportDecision.DeferMove:
|
||||||
|
break;
|
||||||
|
case ScriptImportDecision.RenameRequested:
|
||||||
|
MoveTrackFile(trackFile, artist, trackFile.Tracks);
|
||||||
|
transfer = false;
|
||||||
|
break;
|
||||||
|
case ScriptImportDecision.MoveComplete:
|
||||||
|
transfer = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transfer)
|
||||||
|
{
|
||||||
|
_diskTransferService.TransferFile(trackFilePath, destinationFilePath, mode);
|
||||||
|
}
|
||||||
|
|
||||||
_updateTrackFileService.ChangeFileDateForFile(trackFile, artist, tracks);
|
_updateTrackFileService.ChangeFileDateForFile(trackFile, artist, tracks);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
|
@ -216,8 +216,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
||||||
trackFile.SceneName = localTrack.SceneName;
|
trackFile.SceneName = localTrack.SceneName;
|
||||||
trackFile.OriginalFilePath = GetOriginalFilePath(downloadClientItem, localTrack);
|
trackFile.OriginalFilePath = GetOriginalFilePath(downloadClientItem, localTrack);
|
||||||
|
|
||||||
var moveResult = _trackFileUpgrader.UpgradeTrackFile(trackFile, localTrack, copyOnly);
|
oldFiles = _trackFileUpgrader.UpgradeTrackFile(trackFile, localTrack, copyOnly).OldFiles;
|
||||||
oldFiles = moveResult.OldFiles;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -108,6 +108,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
||||||
var localTrack = new LocalTrack
|
var localTrack = new LocalTrack
|
||||||
{
|
{
|
||||||
DownloadClientAlbumInfo = downloadClientItemInfo,
|
DownloadClientAlbumInfo = downloadClientItemInfo,
|
||||||
|
DownloadItem = downloadClientItem,
|
||||||
FolderAlbumInfo = folderInfo,
|
FolderAlbumInfo = folderInfo,
|
||||||
Path = file.FullName,
|
Path = file.FullName,
|
||||||
Size = file.Length,
|
Size = file.Length,
|
||||||
|
|
|
@ -70,6 +70,8 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
_mediaFileService.Delete(file, DeleteMediaFileReason.Upgrade);
|
_mediaFileService.Delete(file, DeleteMediaFileReason.Upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
localTrack.OldFiles = moveFileResult.OldFiles;
|
||||||
|
|
||||||
if (copyOnly)
|
if (copyOnly)
|
||||||
{
|
{
|
||||||
moveFileResult.TrackFile = _trackFileMover.CopyTrackFile(trackFile, localTrack);
|
moveFileResult.TrackFile = _trackFileMover.CopyTrackFile(trackFile, localTrack);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.TrackImport.Identification;
|
using NzbDrone.Core.MediaFiles.TrackImport.Identification;
|
||||||
using NzbDrone.Core.Music;
|
using NzbDrone.Core.Music;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
@ -19,11 +21,13 @@ namespace NzbDrone.Core.Parser.Model
|
||||||
public ParsedTrackInfo FileTrackInfo { get; set; }
|
public ParsedTrackInfo FileTrackInfo { get; set; }
|
||||||
public ParsedAlbumInfo FolderAlbumInfo { get; set; }
|
public ParsedAlbumInfo FolderAlbumInfo { get; set; }
|
||||||
public ParsedAlbumInfo DownloadClientAlbumInfo { get; set; }
|
public ParsedAlbumInfo DownloadClientAlbumInfo { get; set; }
|
||||||
|
public DownloadClientItem DownloadItem { get; set; }
|
||||||
public List<string> AcoustIdResults { get; set; }
|
public List<string> AcoustIdResults { get; set; }
|
||||||
public Artist Artist { get; set; }
|
public Artist Artist { get; set; }
|
||||||
public Album Album { get; set; }
|
public Album Album { get; set; }
|
||||||
public AlbumRelease Release { get; set; }
|
public AlbumRelease Release { get; set; }
|
||||||
public List<Track> Tracks { get; set; }
|
public List<Track> Tracks { get; set; }
|
||||||
|
public List<TrackFile> OldFiles { get; set; }
|
||||||
public Distance Distance { get; set; }
|
public Distance Distance { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public bool ExistingFile { get; set; }
|
public bool ExistingFile { get; set; }
|
||||||
|
|
Loading…
Reference in New Issue