added ScriptNode for scripts, updated minimum version to 0.6.3

This commit is contained in:
John Andrews
2022-05-30 21:27:29 +12:00
parent 69eb371399
commit 0c84679240
40 changed files with 304 additions and 22 deletions

Binary file not shown.

View File

@@ -3,7 +3,7 @@ namespace FileFlows.Apprise;
public class Plugin : FileFlows.Plugin.IPlugin
{
public string Name => "Apprise Nodes";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init()
{

Binary file not shown.

View File

@@ -0,0 +1,109 @@
using FileFlows.Plugin;
using Jint;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
namespace BasicNodes;
/// <summary>
/// A Javascript code executor
/// </summary>
internal class JavascriptExecutor
{
/// <summary>
/// Delegate used by the executor so log messages can be passed from the javascript code into the flow runner
/// </summary>
/// <param name="values">the parameters for the logger</param>
delegate void LogDelegate(params object[] values);
/// <summary>
/// Executes javascript
/// </summary>
/// <param name="execArgs">the execution arguments</param>
/// <returns>the output to be called next</returns>
public static int Execute(JavascriptExecutionArgs execArgs)
{
if (string.IsNullOrEmpty(execArgs?.Code))
return -1; // no code, flow cannot continue doesnt know what to do
var args = execArgs.Args;
try
{
long fileSize = 0;
var fileInfo = new FileInfo(args.WorkingFile);
if (fileInfo.Exists)
fileSize = fileInfo.Length;
// replace Variables. with dictionary notation
string tcode = execArgs.Code;
foreach (string k in args.Variables.Keys.OrderByDescending(x => x.Length))
{
// replace Variables.Key or Variables?.Key?.Subkey etc to just the variable
// so Variables.file?.Orig.Name, will be replaced to Variables["file.Orig.Name"]
// since its just a dictionary key value
string keyRegex = @"Variables(\?)?\." + k.Replace(".", @"(\?)?\.");
object? value = args.Variables[k];
if (value is JsonElement jElement)
{
if (jElement.ValueKind == JsonValueKind.String)
value = jElement.GetString();
if (jElement.ValueKind == JsonValueKind.Number)
value = jElement.GetInt64();
}
tcode = Regex.Replace(tcode, keyRegex, "Variables['" + k + "']");
}
var sb = new StringBuilder();
var log = new
{
ILog = new LogDelegate(args.Logger.ILog),
DLog = new LogDelegate(args.Logger.DLog),
WLog = new LogDelegate(args.Logger.WLog),
ELog = new LogDelegate(args.Logger.ELog),
};
var engine = new Engine(options =>
{
options.LimitMemory(4_000_000);
options.MaxStatements(500);
})
.SetValue("Logger", args.Logger)
.SetValue("Variables", args.Variables)
.SetValue("Flow", args);
foreach (var arg in execArgs.AdditionalArguments)
engine.SetValue(arg.Key, arg.Value);
var result = int.Parse(engine.Evaluate(tcode).ToObject().ToString());
return result;
}
catch (Exception ex)
{
args.Logger?.ELog("Failed executing function: " + ex.Message + Environment.NewLine + ex.StackTrace);
return -1;
}
}
}
/// <summary>
/// The arguments to pass to the javascript executor
/// </summary>
public class JavascriptExecutionArgs
{
/// <summary>
/// Gets or sets the code to execute
/// </summary>
public string Code { get; set; }
/// <summary>
/// Gets or sets teh NodeParameters
/// </summary>
public NodeParameters Args { get; set; }
/// <summary>
/// Gets a collection of additional arguments to be passed to the javascript executor
/// </summary>
public Dictionary<string, object> AdditionalArguments { get; private set; } = new Dictionary<string, object>();
}

View File

@@ -5,7 +5,7 @@ namespace FileFlows.BasicNodes
public class Plugin : FileFlows.Plugin.IPlugin
{
public string Name => "Basic Nodes";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init() { }
}

63
BasicNodes/ScriptNode.cs Normal file
View File

@@ -0,0 +1,63 @@
using BasicNodes;
using FileFlows.Plugin;
using System.Dynamic;
namespace FileFlows.BasicNodes;
/// <summary>
/// A special node that is not shown in the UI and only created
/// by the Flow Runner to execute a script.
/// This Node exists in this plugin to make use of the Javascript executor
/// </summary>
public class ScriptNode:Node
{
/// <summary>
/// Gets the number of inputs of this node
/// </summary>
public override int Inputs => 1;
/// <summary>
/// Gets or sets the model to pass to the node
/// </summary>
public ExpandoObject Model { get; set; }
/// <summary>
/// Gets or sets the code to execute
/// </summary>
public string Code { get; set; }
/// <summary>
/// Executes the script node
/// </summary>
/// <param name="args">the NodeParameters passed into this from the flow runner</param>
/// <returns>the output node to call next</returns>
public override int Execute(NodeParameters args)
{
// will throw exception if invalid
var script = new ScriptParser().Parse("ScriptNode", Code);
// build up the entry point
string epParams = string.Join(", ", script.Parameters?.Select(x => x.Name).ToArray());
// all scripts must contain the "Script" method we then add this to call that
string entryPoint = $"Script({epParams});";
var execArgs = new JavascriptExecutionArgs
{
Args = args,
Code = Code + "\n\n" + entryPoint
};
if (script.Parameters?.Any() == true)
{
var dictModel = Model as IDictionary<string, object>;
foreach (var p in script.Parameters)
{
var value = dictModel?.ContainsKey(p.Name) == true ? dictModel[p.Name] : null;
execArgs.AdditionalArguments.Add(p.Name, value);
}
}
return JavascriptExecutor.Execute(execArgs);
}
}

Binary file not shown.

View File

@@ -3,7 +3,7 @@ namespace ChecksumNodes
public class Plugin : IPlugin
{
public string Name => "Checksum Nodes";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init()
{

View File

@@ -6,7 +6,7 @@ namespace CollectionNodes
public class Plugin : IPlugin
{
public string Name => "Collection Nodes";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
[Folder(1)]
[Required]

Binary file not shown.

View File

@@ -3,7 +3,7 @@ namespace FileFlows.DiscordNodes;
public class Plugin : FileFlows.Plugin.IPlugin
{
public string Name => "Discord";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init()
{

Binary file not shown.

View File

@@ -3,7 +3,7 @@
public class Plugin : IPlugin
{
public string Name => "Email";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init()
{

Binary file not shown.

View File

@@ -3,7 +3,7 @@ namespace FileFlows.Emby;
public class Plugin : FileFlows.Plugin.IPlugin
{
public string Name => "Emby";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init()
{

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -3,7 +3,7 @@ namespace FileFlows.Gotify;
public class Plugin : FileFlows.Plugin.IPlugin
{
public string Name => "Gotify Nodes";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init()
{

Binary file not shown.

View File

@@ -3,7 +3,7 @@ namespace FileFlows.ImageNodes;
public class Plugin : FileFlows.Plugin.IPlugin
{
public string Name => "Image Nodes";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init()
{

Binary file not shown.

View File

@@ -5,7 +5,7 @@ namespace MetaNodes
public class Plugin : FileFlows.Plugin.IPlugin
{
public string Name => "Meta Nodes";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init() { }
}

Binary file not shown.

View File

@@ -6,7 +6,7 @@ namespace FileFlows.MusicNodes
public class Plugin : FileFlows.Plugin.IPlugin
{
public string Name => "Music Nodes";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init()
{

Binary file not shown.

View File

@@ -3,7 +3,7 @@ namespace FileFlows.Plex;
public class Plugin : FileFlows.Plugin.IPlugin
{
public string Name => "Plex";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init()
{

View File

@@ -6,7 +6,7 @@ namespace FileFlows.VideoNodes
public class Plugin : FileFlows.Plugin.IPlugin
{
public string Name => "Video Nodes";
public string MinimumVersion => "0.6.1.900";
public string MinimumVersion => "0.6.3.1000";
public void Init()
{

Binary file not shown.

View File

@@ -203,6 +203,17 @@
Gets the location of the node configuration file
</summary>
</member>
<member name="P:FileFlows.ServerShared.Helpers.DirectoryHelper.ServerConfigFile">
<summary>
Gets the location of the server configuration file
</summary>
</member>
<member name="M:FileFlows.ServerShared.Helpers.DirectoryHelper.CleanDirectory(System.String)">
<summary>
Deletes all files and folders from a directory
</summary>
<param name="path">the path of the directory</param>
</member>
<member name="T:FileFlows.ServerShared.Helpers.FileHelper">
<summary>
A helper for interacting with files
@@ -800,6 +811,41 @@
<returns>the updated plugininfo</returns>
<exception cref="T:System.NotImplementedException">This not yet implemented</exception>
</member>
<member name="T:FileFlows.ServerShared.Services.IScriptService">
<summary>
Script Service interface
</summary>
</member>
<member name="M:FileFlows.ServerShared.Services.IScriptService.GetCode(System.Guid)">
<summary>
Get the code for a script
</summary>
<param name="uid">The UID identifying the script</param>
<returns>the code for the script</returns>
</member>
<member name="T:FileFlows.ServerShared.Services.ScriptService">
<summary>
A service used to get script data from the FileFlows server
</summary>
</member>
<member name="P:FileFlows.ServerShared.Services.ScriptService.Loader">
<summary>
Gets or sets a function used to load new instances of the service
</summary>
</member>
<member name="M:FileFlows.ServerShared.Services.ScriptService.Load">
<summary>
Loads an instance of the script service
</summary>
<returns>an instance of the script service</returns>
</member>
<member name="M:FileFlows.ServerShared.Services.ScriptService.GetCode(System.Guid)">
<summary>
Get the code for a script
</summary>
<param name="uid">The UID identifying the script</param>
<returns>the code for the script</returns>
</member>
<member name="T:FileFlows.ServerShared.Services.Service">
<summary>
A service lets you communicate with the FileFLows server
@@ -953,14 +999,6 @@
</summary>
<returns>if auto updates are enabled</returns>
</member>
<member name="M:FileFlows.ServerShared.Workers.UpdaterWorker.DownloadFile(System.String,System.String)">
<summary>
Downloads a file and saves it
</summary>
<param name="url">The url of the file to download</param>
<param name="file">the location to save the file</param>
<exception cref="T:System.Exception">throws if the file fails to download</exception>
</member>
<member name="T:FileFlows.ServerShared.Workers.Worker">
<summary>
A worker that will run at a set schedule

View File

@@ -256,11 +256,20 @@
<param name="data">any data to send with the request</param>
<returns>the request result</returns>
</member>
<member name="M:FileFlows.Shared.Helpers.HttpHelper.Log(System.String)">
<member name="M:FileFlows.Shared.Helpers.HttpHelper.DownloadFile(System.String,System.String)">
<summary>
Downloads a file from a URL
</summary>
<param name="url">the URL of the download</param>
<param name="destination">where the download should be saved</param>
<exception cref="T:System.Exception">throws if the file fails to download</exception>
</member>
<member name="M:FileFlows.Shared.Helpers.HttpHelper.Log(System.String,System.Boolean)">
<summary>
Logs a message to the log
</summary>
<param name="message">the message to log</param>
<param name="error">if the message is an error message or info</param>
</member>
<member name="M:FileFlows.Shared.Helpers.HttpHelper.MakeRequest``1(System.Net.Http.HttpMethod,System.String,System.Object,System.Int32,System.Boolean)">
<summary>
@@ -502,6 +511,12 @@
Gets or sets optional place holder text, this can be a translation key
</summary>
</member>
<member name="P:FileFlows.Shared.Models.ElementField.Description">
<summary>
Gets or sets the description of the element, if this is set, this will be used instead of the HelpHint
Note: this is used by the Script which the user defines the description for
</summary>
</member>
<member name="P:FileFlows.Shared.Models.ElementField.InputType">
<summary>
Gets or sets the input type of this field
@@ -924,6 +939,11 @@
Gets or sets the name of the element
</summary>
</member>
<member name="P:FileFlows.Shared.Models.FlowElement.Description">
<summary>
Gets or sets a description for this element, only used by scripts where the description is user defined
</summary>
</member>
<member name="P:FileFlows.Shared.Models.FlowElement.DisplayName">
<summary>
Gets or sets the display name of the element
@@ -1638,6 +1658,21 @@
Gets or sets the output from this node
</summary>
</member>
<member name="T:FileFlows.Shared.Models.LibraryFileDatalistModel">
<summary>
Model class for the Library Files page
</summary>
</member>
<member name="P:FileFlows.Shared.Models.LibraryFileDatalistModel.LibraryFiles">
<summary>
Gets or sets a list of library files to show in the UI
</summary>
</member>
<member name="P:FileFlows.Shared.Models.LibraryFileDatalistModel.Status">
<summary>
Gets or sets the status data for the libraries
</summary>
</member>
<member name="T:FileFlows.Shared.Models.LibraryStatus">
<summary>
Library status
@@ -1935,6 +1970,16 @@
Gets or sets the parsed response object
</summary>
</member>
<member name="T:FileFlows.Shared.Models.Script">
<summary>
A script is a special function node that lets you reuse them
</summary>
</member>
<member name="P:FileFlows.Shared.Models.Script.Code">
<summary>
Gets or sets the javascript code of the script
</summary>
</member>
<member name="T:FileFlows.Shared.Models.Settings">
<summary>
Settings for FileFlows
@@ -2054,6 +2099,21 @@
Gets or sets the processing time of the executed node
</summary>
</member>
<member name="T:FileFlows.Shared.Models.SystemInfo">
<summary>
Gets the system information about FileFlows
</summary>
</member>
<member name="P:FileFlows.Shared.Models.SystemInfo.MemoryUsage">
<summary>
Gets the amount of memory used by FileFlows
</summary>
</member>
<member name="P:FileFlows.Shared.Models.SystemInfo.CpuUsage">
<summary>
Gets the how much CPU is used by FileFlows
</summary>
</member>
<member name="T:FileFlows.Shared.Models.Tool">
<summary>
A tool in FileFlows, e.g. an external application
@@ -2196,6 +2256,18 @@
<param name="value">The value to validate</param>
<returns>true if the value has a propre value</returns>
</member>
<member name="T:FileFlows.Shared.Validators.ScriptValidator">
<summary>
Validator that checks a Script object is valid
</summary>
</member>
<member name="M:FileFlows.Shared.Validators.ScriptValidator.Validate(System.Object)">
<summary>
Validates a Script
</summary>
<param name="value">the Script code to validate</param>
<returns>true if valid, otherwise false</returns>
</member>
<member name="T:FileFlows.Shared.Validators.Validator">
<summary>
A validator used to validate a value