added Failure nodes and started working on ffmpeg metadata node

This commit is contained in:
John Andrews
2022-04-17 15:35:03 +12:00
parent b740894f99
commit e5f2489a43
47 changed files with 533 additions and 179 deletions
Binary file not shown.
+12 -6
View File
@@ -1,10 +1,16 @@
namespace BasicNodes
namespace FileFlows.BasicNodes;
internal static class ExtensionMethods
{
internal static class ExtensionMethods
public static string? EmptyAsNull(this string str)
{
public static string? EmptyAsNull(this string str)
{
return str == string.Empty ? null : str;
}
return str == string.Empty ? null : str;
}
public static void AddOrUpdate(this Dictionary<string, object> dict, string key, object value)
{
if (dict.ContainsKey(key))
dict[key] = value;
else
dict.Add(key, value);
}
}
+49
View File
@@ -0,0 +1,49 @@
using FileFlows.Plugin;
namespace FileFlows.BasicNodes;
public class FlowFailure: Node
{
public override int Outputs => 1;
public override FlowElementType Type => FlowElementType.Failure;
public override string Icon => "fas fa-exclamation-triangle";
public override bool FailureNode => true;
private Dictionary<string, object> _Variables;
public override Dictionary<string, object> Variables => _Variables;
public FlowFailure()
{
_Variables = new Dictionary<string, object>()
{
{ "fail.Flow", "The Flow Name" },
{ "fail.Log", "A short tail of the log" },
{ "fail.Message", "A formatted message containing the failure details" },
{ "fail.Node", "FailedNodeName" },
};
}
public override int Execute(NodeParameters args)
{
try
{
string log = args.Logger?.GetTail(10)?.EmptyAsNull() ?? "No log available";
string failedNode = args.GetVariable("FailedNode") as string ?? "Unknown";
string flowName = args.GetVariable("FlowName") as string ?? "Unknown";
string message = @$"Failed processing file {args.FileName}
Flow: {flowName}
Node: {failedNode}
{log}";
Variables.AddOrUpdate("fail.Node", failedNode);
Variables.AddOrUpdate("fail.Flow", flowName);
Variables.AddOrUpdate("fail.Message", message);
Variables.AddOrUpdate("fail.Log", log);
args.UpdateVariables(Variables);
return 1;
}
catch (Exception)
{
return 0; // special case, we never want to report an error here
}
}
}
+1
View File
@@ -16,6 +16,7 @@ namespace FileFlows.BasicNodes.Functions
public override int Inputs => 1;
public override FlowElementType Type => FlowElementType.Logic;
public override string Icon => "fas fa-code";
public override bool FailureNode => true;
public override string HelpUrl => "https://github.com/revenz/FileFlows/wiki/Function-Node";
+1 -1
View File
@@ -5,7 +5,7 @@ namespace FileFlows.BasicNodes
public class Plugin : FileFlows.Plugin.IPlugin
{
public string Name => "Basic Nodes";
public string MinimumVersion => "0.5.0.683";
public string MinimumVersion => "0.5.2.690";
public void Init() { }
}
+2
View File
@@ -41,6 +41,8 @@ namespace BasicNodes.Tests
string log = string.Join(Environment.NewLine, Messages);
return log.Contains(message);
}
public string GetTail(int length = 50) => "Not implemented";
}
}
+23 -25
View File
@@ -1,37 +1,35 @@
#if(DEBUG)
namespace BasicNodes.Tests
{
using BasicNodes.Tools;
using FileFlows.BasicNodes.File;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace BasicNodes.Tests;
[TestClass]
public class WebRequestTests
using FileFlows.BasicNodes.Tools;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class WebRequestTests
{
[TestMethod]
public void WebRequest_PostJson()
{
[TestMethod]
public void WebRequest_PostJson()
{
var logger = new TestLogger();
var args = new FileFlows.Plugin.NodeParameters(@"c:\test\testfile.mkv", logger, false, string.Empty);
WebRequest node = new();
node.Method = "POST";
node.Url = "http://localhost:7096/Users/New";
node.ContentType = "application/json";
node.Headers = new List<KeyValuePair<string, string>>();
node.Headers.Add(new KeyValuePair<string, string> ("X-MediaBrowser-Token", ""));
node.Body = @$"{{
var logger = new TestLogger();
var args = new FileFlows.Plugin.NodeParameters(@"c:\test\testfile.mkv", logger, false, string.Empty);
WebRequest node = new();
node.Method = "POST";
node.Url = "http://localhost:7096/Users/New";
node.ContentType = "application/json";
node.Headers = new List<KeyValuePair<string, string>>();
node.Headers.Add(new KeyValuePair<string, string> ("X-MediaBrowser-Token", ""));
node.Body = @$"{{
""Name"": ""{Guid.NewGuid()}""
}}";
var result = node.Execute(args);
var result = node.Execute(args);
string body = node.Variables["web.Body"] as string;
Assert.IsFalse(string.IsNullOrWhiteSpace(body));
string body = node.Variables["web.Body"] as string;
Assert.IsFalse(string.IsNullOrWhiteSpace(body));
Assert.AreEqual(1, result);
}
Assert.AreEqual(1, result);
}
}
+128 -128
View File
@@ -1,141 +1,141 @@
namespace BasicNodes.Tools
namespace FileFlows.BasicNodes.Tools;
using FileFlows.Plugin;
using FileFlows.Plugin.Attributes;
using System;
using System.Text;
public class WebRequest : Node
{
using FileFlows.Plugin;
using FileFlows.Plugin.Attributes;
using System;
using System.Text;
public override int Inputs => 1;
public override int Outputs => 2;
public override FlowElementType Type => FlowElementType.Communication;
public override bool FailureNode => true;
public override string Icon => "fas fa-globe";
public class WebRequest : Node
[TextVariable(1)]
public string Url { get; set; }
[Select(nameof(MethodOptions), 2)]
public string Method { get; set; }
private static List<ListOption> _MethodOptions;
public static List<ListOption> MethodOptions
{
public override int Inputs => 1;
public override int Outputs => 2;
public override FlowElementType Type => FlowElementType.Process;
public override string Icon => "fas fa-globe";
[TextVariable(1)]
public string Url { get; set; }
[Select(nameof(MethodOptions), 2)]
public string Method { get; set; }
private static List<ListOption> _MethodOptions;
public static List<ListOption> MethodOptions
get
{
get
if (_MethodOptions == null)
{
if (_MethodOptions == null)
_MethodOptions = new List<ListOption>
{
_MethodOptions = new List<ListOption>
{
new ListOption { Label = "GET", Value = "GET"},
new ListOption { Label = "POST", Value = "POST"},
new ListOption { Label = "PUT", Value = "PUT"},
new ListOption { Label = "DELETE", Value = "DELETE"},
};
}
return _MethodOptions;
}
}
[Select(nameof(ContentTypeOptions), 3)]
public string ContentType { get; set; }
private static List<ListOption> _ContentTypeOptions;
public static List<ListOption> ContentTypeOptions
{
get
{
if (_ContentTypeOptions == null)
{
_ContentTypeOptions = new List<ListOption>
{
new ListOption { Label = "None", Value = ""},
new ListOption { Label = "JSON", Value = "application/json"},
new ListOption { Label = "Form Data", Value = "application/x-www-form-urlencoded"},
};
}
return _ContentTypeOptions;
}
}
[KeyValue(4)]
public List<KeyValuePair<string, string>> Headers { get; set; }
[TextArea(5)]
public string Body { get; set; }
private Dictionary<string, object> _Variables;
public override Dictionary<string, object> Variables => _Variables;
public WebRequest()
{
_Variables = new Dictionary<string, object>()
{
{ "web.StatusCode", 200 },
{ "web.Body", "this is a sample body" }
};
}
public override int Execute(NodeParameters args)
{
try
{
using var client = new HttpClient();
string url = args.ReplaceVariables(this.Url, stripMissing: true);
HttpMethod method = this.Method switch
{
"POST" => HttpMethod.Post,
"PUT" => HttpMethod.Put,
"DELETE" => HttpMethod.Delete,
_ => HttpMethod.Get
new ListOption { Label = "GET", Value = "GET"},
new ListOption { Label = "POST", Value = "POST"},
new ListOption { Label = "PUT", Value = "PUT"},
new ListOption { Label = "DELETE", Value = "DELETE"},
};
args.Logger.ILog("Requesting: [" + method + "] " + url);
HttpRequestMessage message = new HttpRequestMessage(method, url);
if(this.Headers?.Any() == true)
{
foreach(var header in this.Headers)
{
if (string.IsNullOrEmpty(header.Key) || string.IsNullOrEmpty(header.Value))
continue;
message.Headers.Add(header.Key, header.Value);
}
}
if (string.IsNullOrEmpty(this.ContentType) == false && method != HttpMethod.Get && string.IsNullOrWhiteSpace(this.Body) == false)
{
string body = args.ReplaceVariables(this.Body, stripMissing: false);
message.Content = new StringContent(body, Encoding.UTF8, this.ContentType?.EmptyAsNull() ?? "application/json");
}
var result = client.Send(message);
string stringBody = result.Content.ReadAsStringAsync().Result ?? string.Empty;
args.UpdateVariables(new Dictionary<string, object>{
{ "web.StatusCode", (int)result.StatusCode },
{ "web.Body", stringBody }
});
if (result.IsSuccessStatusCode == false)
{
args.Logger.WLog("Non successfully status code returned: " + result.StatusCode);
return 2;
}
args.Logger?.ILog("Successful status code returned: " + result.StatusCode);
return 1;
}
catch (Exception ex)
return _MethodOptions;
}
}
[Select(nameof(ContentTypeOptions), 3)]
public string ContentType { get; set; }
private static List<ListOption> _ContentTypeOptions;
public static List<ListOption> ContentTypeOptions
{
get
{
if (_ContentTypeOptions == null)
{
args.Logger?.ELog("Failed sending web request: " + ex.Message + Environment.NewLine + ex.StackTrace);
return -1;
_ContentTypeOptions = new List<ListOption>
{
new ListOption { Label = "None", Value = ""},
new ListOption { Label = "JSON", Value = "application/json"},
new ListOption { Label = "Form Data", Value = "application/x-www-form-urlencoded"},
};
}
return _ContentTypeOptions;
}
}
[KeyValue(4)]
public List<KeyValuePair<string, string>> Headers { get; set; }
[TextArea(5)]
public string Body { get; set; }
private Dictionary<string, object> _Variables;
public override Dictionary<string, object> Variables => _Variables;
public WebRequest()
{
_Variables = new Dictionary<string, object>()
{
{ "web.StatusCode", 200 },
{ "web.Body", "this is a sample body" }
};
}
public override int Execute(NodeParameters args)
{
try
{
using var client = new HttpClient();
string url = args.ReplaceVariables(this.Url, stripMissing: true);
HttpMethod method = this.Method switch
{
"POST" => HttpMethod.Post,
"PUT" => HttpMethod.Put,
"DELETE" => HttpMethod.Delete,
_ => HttpMethod.Get
};
args.Logger.ILog("Requesting: [" + method + "] " + url);
HttpRequestMessage message = new HttpRequestMessage(method, url);
if(this.Headers?.Any() == true)
{
foreach(var header in this.Headers)
{
if (string.IsNullOrEmpty(header.Key) || string.IsNullOrEmpty(header.Value))
continue;
message.Headers.Add(header.Key, header.Value);
}
}
if (string.IsNullOrEmpty(this.ContentType) == false && method != HttpMethod.Get && string.IsNullOrWhiteSpace(this.Body) == false)
{
string body = args.ReplaceVariables(this.Body, stripMissing: false);
message.Content = new StringContent(body, Encoding.UTF8, this.ContentType?.EmptyAsNull() ?? "application/json");
}
var result = client.Send(message);
string stringBody = result.Content.ReadAsStringAsync().Result ?? string.Empty;
args.UpdateVariables(new Dictionary<string, object>{
{ "web.StatusCode", (int)result.StatusCode },
{ "web.Body", stringBody }
});
if (result.IsSuccessStatusCode == false)
{
args.Logger.WLog("Non successfully status code returned: " + result.StatusCode);
return 2;
}
args.Logger?.ILog("Successful status code returned: " + result.StatusCode);
return 1;
}
catch (Exception ex)
{
args.Logger?.ELog("Failed sending web request: " + ex.Message + Environment.NewLine + ex.StackTrace);
return -1;
}
}
}