1
+ using System . Collections . Generic ;
1
2
using System . Collections . Specialized ;
2
3
using System . IO ;
3
4
using System . Linq ;
5
+ using System . Text . RegularExpressions ;
4
6
using NLog ;
5
7
using NzbDrone . Common . Disk ;
6
8
using NzbDrone . Common . Extensions ;
@@ -25,23 +27,89 @@ public class ImportScriptService : IImportScript
25
27
private readonly IProcessProvider _processProvider ;
26
28
private readonly IConfigService _configService ;
27
29
private readonly ITagRepository _tagRepository ;
30
+ private readonly IDiskProvider _diskProvider ;
28
31
private readonly Logger _logger ;
29
32
30
33
public ImportScriptService ( IProcessProvider processProvider ,
31
34
IVideoFileInfoReader videoFileInfoReader ,
32
35
IConfigService configService ,
33
36
IConfigFileProvider configFileProvider ,
34
37
ITagRepository tagRepository ,
38
+ IDiskProvider diskProvider ,
35
39
Logger logger )
36
40
{
37
41
_processProvider = processProvider ;
38
42
_videoFileInfoReader = videoFileInfoReader ;
39
43
_configService = configService ;
40
44
_configFileProvider = configFileProvider ;
41
45
_tagRepository = tagRepository ;
46
+ _diskProvider = diskProvider ;
42
47
_logger = logger ;
43
48
}
44
49
50
+ private static readonly Regex OutputRegex = new Regex ( @"^(?:\[(?:(?<mediaFile>MediaFile)|(?<extraFile>ExtraFile))\]\s?(?<fileName>.+)|(?<preventExtraImport>\[PreventExtraImport\])|\[MoveStatus\]\s?(?:(?<deferMove>DeferMove)|(?<moveComplete>MoveComplete)|(?<renameRequested>RenameRequested)))$" , RegexOptions . Compiled ) ;
51
+
52
+ private ScriptImportInfo ProcessOutput ( List < ProcessOutputLine > processOutputLines )
53
+ {
54
+ var possibleExtraFiles = new List < string > ( ) ;
55
+ string mediaFile = null ;
56
+ var decision = ScriptImportDecision . MoveComplete ;
57
+ var importExtraFiles = true ;
58
+
59
+ foreach ( var line in processOutputLines )
60
+ {
61
+ var match = OutputRegex . Match ( line . Content ) ;
62
+
63
+ if ( match . Groups [ "mediaFile" ] . Success )
64
+ {
65
+ if ( mediaFile is not null )
66
+ {
67
+ throw new ScriptImportException ( "Script output contains multiple media files. Only one media file can be returned." ) ;
68
+ }
69
+
70
+ mediaFile = match . Groups [ "fileName" ] . Value ;
71
+
72
+ if ( ! MediaFileExtensions . Extensions . Contains ( Path . GetExtension ( mediaFile ) ) )
73
+ {
74
+ throw new ScriptImportException ( "Script output contains invalid media file: {0}" , mediaFile ) ;
75
+ }
76
+ else if ( ! _diskProvider . FileExists ( mediaFile ) )
77
+ {
78
+ throw new ScriptImportException ( "Script output contains non-existent media file: {0}" , mediaFile ) ;
79
+ }
80
+ }
81
+ else if ( match . Groups [ "extraFile" ] . Success )
82
+ {
83
+ var fileName = match . Groups [ "fileName" ] . Value ;
84
+
85
+ if ( ! _diskProvider . FileExists ( fileName ) )
86
+ {
87
+ _logger . Warn ( "Script output contains non-existent possible extra file: {0}" , fileName ) ;
88
+ }
89
+
90
+ possibleExtraFiles . Add ( fileName ) ;
91
+ }
92
+ else if ( match . Groups [ "moveComplete" ] . Success )
93
+ {
94
+ decision = ScriptImportDecision . MoveComplete ;
95
+ }
96
+ else if ( match . Groups [ "renameRequested" ] . Success )
97
+ {
98
+ decision = ScriptImportDecision . RenameRequested ;
99
+ }
100
+ else if ( match . Groups [ "deferMove" ] . Success )
101
+ {
102
+ decision = ScriptImportDecision . DeferMove ;
103
+ }
104
+ else if ( match . Groups [ "preventExtraImport" ] . Success )
105
+ {
106
+ importExtraFiles = false ;
107
+ }
108
+ }
109
+
110
+ return new ScriptImportInfo ( possibleExtraFiles , mediaFile , decision , importExtraFiles ) ;
111
+ }
112
+
45
113
public ScriptImportDecision TryImport ( string sourcePath , string destinationFilePath , LocalMovie localMovie , MovieFile movieFile , TransferMode mode )
46
114
{
47
115
var movie = localMovie . Movie ;
@@ -111,22 +179,37 @@ public ScriptImportDecision TryImport(string sourcePath, string destinationFileP
111
179
112
180
var processOutput = _processProvider . StartAndCapture ( _configService . ScriptImportPath , $ "\" { sourcePath } \" \" { destinationFilePath } \" ", environmentVariables ) ;
113
181
114
- _logger . Debug ( "Executed external script: {0} - Status: {1}" , _configService . ScriptImportPath , processOutput . ExitCode ) ;
115
182
_logger . Debug ( "Script Output: \r \n {0}" , string . Join ( "\r \n " , processOutput . Lines ) ) ;
116
183
117
- switch ( processOutput . ExitCode )
184
+ if ( processOutput . ExitCode != 0 )
185
+ {
186
+ throw new ScriptImportException ( "Script exited with non-zero exit code: {0}" , processOutput . ExitCode ) ;
187
+ }
188
+
189
+ var scriptImportInfo = ProcessOutput ( processOutput . Lines ) ;
190
+
191
+ var mediaFile = scriptImportInfo . MediaFile ?? destinationFilePath ;
192
+ localMovie . PossibleExtraFiles = scriptImportInfo . PossibleExtraFiles ;
193
+
194
+ movieFile . RelativePath = movie . Path . GetRelativePath ( mediaFile ) ;
195
+ movieFile . Path = mediaFile ;
196
+
197
+ var exitCode = processOutput . ExitCode ;
198
+
199
+ localMovie . ShouldImportExtras = scriptImportInfo . ImportExtraFiles ;
200
+
201
+ if ( scriptImportInfo . Decision != ScriptImportDecision . DeferMove )
118
202
{
119
- case 0 : // Copy complete
120
- return ScriptImportDecision . MoveComplete ;
121
- case 2 : // Copy complete, file potentially changed, should try renaming again
122
- movieFile . MediaInfo = _videoFileInfoReader . GetMediaInfo ( destinationFilePath ) ;
123
- movieFile . Path = null ;
124
- return ScriptImportDecision . RenameRequested ;
125
- case 3 : // Let Radarr handle it
126
- return ScriptImportDecision . DeferMove ;
127
- default : // Error, fail to import
128
- throw new ScriptImportException ( "Moving with script failed! Exit code {0}" , processOutput . ExitCode ) ;
203
+ localMovie . ScriptImported = true ;
129
204
}
205
+
206
+ if ( scriptImportInfo . Decision == ScriptImportDecision . RenameRequested )
207
+ {
208
+ movieFile . MediaInfo = _videoFileInfoReader . GetMediaInfo ( mediaFile ) ;
209
+ movieFile . Path = null ;
210
+ }
211
+
212
+ return scriptImportInfo . Decision ;
130
213
}
131
214
}
132
215
}
0 commit comments