diff --git a/BasicNodes/BasicNodes.csproj b/BasicNodes/BasicNodes.csproj index 9d018d1d..e9f7bed4 100644 --- a/BasicNodes/BasicNodes.csproj +++ b/BasicNodes/BasicNodes.csproj @@ -29,6 +29,10 @@ + + + + Always diff --git a/BasicNodes/BasicNodes.en.json b/BasicNodes/BasicNodes.en.json index 351f3ca0..2bd59318 100644 --- a/BasicNodes/BasicNodes.en.json +++ b/BasicNodes/BasicNodes.en.json @@ -323,6 +323,18 @@ "Body-Help": "The body of the request being sent. Variables can be used in this field." } }, + "Unpack": { + "Description": "Allows you to unpack an archive (zip, rar, tar, etc)", + "Outputs": { + "1": "File Unpacked" + }, + "Fields": { + "DestinationPath": "Destination Folder", + "DestinationPath-Help": "The destination folder where to unpack the file.", + "File": "File", + "File-Help": "The name of the file to unpack. Can be left blank and if so the current working file will be used." + } + }, "Unzip": { "Description": "Allows you to unzip a file", "Outputs": { diff --git a/BasicNodes/Tools/Unpack.cs b/BasicNodes/Tools/Unpack.cs new file mode 100644 index 00000000..85fe25d0 --- /dev/null +++ b/BasicNodes/Tools/Unpack.cs @@ -0,0 +1,122 @@ +using System.Diagnostics; +using FileFlows.Plugin; +using FileFlows.Plugin.Attributes; +using System.IO.Compression; +using FileFlows.BasicNodes; +using SharpCompress.Archives; + +namespace BasicNodes.Tools; + +/// +/// Node used to unpack files from archives +/// +public class Unpack: Node +{ + public override int Inputs => 1; + public override int Outputs => 1; + public override FlowElementType Type => FlowElementType.Process; + public override string Icon => "fas fa-file-archive"; + /// + /// Gets the Help URL for this element + /// + public override string HelpUrl => "https://fileflows.com/docs/plugins/basic-nodes/unpack"; + + private string _DestinationPath = string.Empty; + private string _file = string.Empty; + + [Folder(1)] + public string DestinationPath + { + get => _DestinationPath; + set { _DestinationPath = value ?? ""; } + } + + [TextVariable(2)] + public string File + { + get => _file; + set { _file = value ?? ""; } + } + + public override int Execute(NodeParameters args) + { + try + { + var filename = args.ReplaceVariables(File ?? string.Empty, stripMissing: true)?.EmptyAsNull() ?? args.WorkingFile; + + var fileInfo = new FileInfo(filename); + + if (fileInfo.Exists == false) + { + args.Logger?.ELog("File does not exist: " + filename); + return -1; + } + + string destDir = args.ReplaceVariables(DestinationPath, stripMissing: true, cleanSpecialCharacters: true); + + if (fileInfo.Extension.ToLower() == ".zip") + ZipFile.ExtractToDirectory(filename, destDir, true); + else + Extract(args, args.WorkingFile, destDir); + + return 1; + } + catch (Exception ex) + { + args.Logger?.ELog("Failed unzip: " + ex.Message + Environment.NewLine + ex.StackTrace); + return -1; + } + } + + /// + /// Unpacks a file + /// + /// the node parameters + /// the file to extract + /// the location to extract to + private void Extract(NodeParameters args, string workingFile, string destinationPath) + { + bool isRar = workingFile.ToLowerInvariant().EndsWith(".cbr"); + try + { + ArchiveFactory.WriteToDirectory(workingFile, destinationPath); + } + catch (Exception ex) when (isRar && ex.Message.Contains("Unknown Rar Header")) + { + UnrarCommandLineExtract(args, workingFile, destinationPath); + } + } + + + /// + /// Unpacks a folder + /// + /// the node parameters + /// the file to extract + /// the location to extract to + void UnrarCommandLineExtract(NodeParameters args, string workingFile, string destinationPath) + { + var process = new Process(); + string unrar = args.GetToolPath("unrar")?.EmptyAsNull() ?? "unrar"; + process.StartInfo.FileName = unrar; + process.StartInfo.ArgumentList.Add("x"); + process.StartInfo.ArgumentList.Add("-o+"); + process.StartInfo.ArgumentList.Add(workingFile); + process.StartInfo.ArgumentList.Add(destinationPath); + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardError = true; + process.StartInfo.CreateNoWindow = true; + process.Start(); + string output = process.StandardError.ReadToEnd(); + string error = process.StandardError.ReadToEnd(); + process.WaitForExit(); + + args.Logger?.ILog("Unrar output:\n" + output); + if (string.IsNullOrWhiteSpace(error) == false) + args.Logger?.ELog("Unrar error:\n" + error); + + if (process.ExitCode != 0) + throw new Exception(error?.EmptyAsNull() ?? "Failed to extract rar file"); + } +} diff --git a/BasicNodes/Tools/Unzip.cs b/BasicNodes/Tools/Unzip.cs index 6e5b03f2..1a3d9c5a 100644 --- a/BasicNodes/Tools/Unzip.cs +++ b/BasicNodes/Tools/Unzip.cs @@ -1,18 +1,29 @@ -using FileFlows.Plugin; +using BasicNodes.Tools; +using FileFlows.Plugin; using FileFlows.Plugin.Attributes; -using System.IO.Compression; namespace FileFlows.BasicNodes.File; /// /// Node that unzips a file /// -public class Unzip : Node +public class Unzip : Node { + /// + /// Gets that this node is obsolete + /// + public override bool Obsolete => true; + /// + /// Gets the obsolete message + /// + public override string ObsoleteMessage => "This has been replaced with the Unpack node.\n\nUse that instead."; public override int Inputs => 1; public override int Outputs => 1; public override FlowElementType Type => FlowElementType.Process; public override string Icon => "fas fa-file-archive"; + /// + /// Gets the Help URL for this element + /// public override string HelpUrl => "https://fileflows.com/docs/plugins/basic-nodes/unzip"; private string _DestinationPath = string.Empty; @@ -32,27 +43,16 @@ public class Unzip : Node set { _zip = value ?? ""; } } + /// + /// Executes the node + /// + /// the arguments + /// the output public override int Execute(NodeParameters args) { - try - { - var zip = args.ReplaceVariables(Zip ?? string.Empty, stripMissing: true)?.EmptyAsNull() ?? args.WorkingFile; - - if (System.IO.File.Exists(zip) == false) - { - args.Logger?.ELog("File does not exist: " + zip); - return -1; - } - - string destDir = args.ReplaceVariables(DestinationPath, stripMissing: true, cleanSpecialCharacters: true); - - ZipFile.ExtractToDirectory(zip, destDir, true); - return 1; - } - catch (Exception ex) - { - args.Logger?.ELog("Failed unzip: " + ex.Message + Environment.NewLine + ex.StackTrace); - return -1; - } + var unpack = new Unpack(); + unpack.File = Zip; + unpack.DestinationPath = DestinationPath; + return unpack.Execute(args); } } diff --git a/ComicNodes/Helpers/GenericExtractor.cs b/ComicNodes/Helpers/GenericExtractor.cs index a87a129b..b73f62af 100644 --- a/ComicNodes/Helpers/GenericExtractor.cs +++ b/ComicNodes/Helpers/GenericExtractor.cs @@ -10,7 +10,7 @@ internal class GenericExtractor /// /// Uncompresses a folder /// - /// the node paratemers + /// the node parameters /// the file to extract /// the location to extract to /// if the NodeParameter.PartPercentageUpdate should end at 50%