diff --git a/FileFlowsPlugins.sln b/FileFlowsPlugins.sln
index 3be1c211..2a12a945 100644
--- a/FileFlowsPlugins.sln
+++ b/FileFlowsPlugins.sln
@@ -29,6 +29,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AudioNodes", "AudioNodes\Au
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComicNodes", "ComicNodes\ComicNodes.csproj", "{45568FCB-00FF-4AEA-AA43-DC569D667B04}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegram", "Telegram\Telegram.csproj", "{BFAD621E-4C82-47FC-A9C8-03F09FF9926C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -87,6 +89,10 @@ Global
{45568FCB-00FF-4AEA-AA43-DC569D667B04}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45568FCB-00FF-4AEA-AA43-DC569D667B04}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45568FCB-00FF-4AEA-AA43-DC569D667B04}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BFAD621E-4C82-47FC-A9C8-03F09FF9926C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BFAD621E-4C82-47FC-A9C8-03F09FF9926C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BFAD621E-4C82-47FC-A9C8-03F09FF9926C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BFAD621E-4C82-47FC-A9C8-03F09FF9926C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Gotify/Communication/Gotify.cs b/Gotify/Communication/Gotify.cs
index 3facebb6..7e2485e1 100644
--- a/Gotify/Communication/Gotify.cs
+++ b/Gotify/Communication/Gotify.cs
@@ -3,26 +3,58 @@ using System.Text.Json;
namespace FileFlows.Gotify.Communication;
+///
+/// A Gotify flow element that sends a message
+///
public class Gotify: Node
{
+ ///
+ /// Gets the number of inputs to this flow element
+ ///
public override int Inputs => 1;
+ ///
+ /// Gets the number of outputs to this flow element
+ ///
public override int Outputs => 2;
- public override FlowElementType Type => FlowElementType.Communication;
+ ///
+ /// Gets the type of flow element
+ ///
+ public override FlowElementType Type => FlowElementType.Communication;
+ ///
+ /// Gets the icon for this flow element
+ ///
public override string Icon => "fas fa-bell";
+ ///
+ /// Gets if this can be used in a failure flow
+ ///
public override bool FailureNode => true;
+ ///
+ /// Gets or sets the message to send
+ ///
[Required]
[TextVariable(1)]
public string Message { get; set; }
-
+
+ ///
+ /// Gets or sets the title of the message
+ ///
[TextVariable(2)]
public string Title { get; set; }
+ ///
+ /// Gets or sets the priority of the message
+ ///
[NumberInt(3)]
[Range(1, 100)]
[DefaultValue(2)]
public int Priority { get; set; } = 2;
+ ///
+ /// Executes the flow element
+ ///
+ /// the node parameters
+ /// the output to call next
public override int Execute(NodeParameters args)
{
try
diff --git a/Gotify/ExtensionMethods.cs b/Gotify/ExtensionMethods.cs
index 6177cfcc..584c0978 100644
--- a/Gotify/ExtensionMethods.cs
+++ b/Gotify/ExtensionMethods.cs
@@ -1,6 +1,14 @@
namespace FileFlows.Gotify;
+///
+/// Extension methods
+///
internal static class ExtensionMethods
{
+ ///
+ /// Returns an empty string as null, otherwise returns the original string
+ ///
+ /// the input string
+ /// the string or null if empty
public static string? EmptyAsNull(this string str) => str == string.Empty ? null : str;
}
diff --git a/Gotify/Plugin.cs b/Gotify/Plugin.cs
index 734125d5..c35d2be3 100644
--- a/Gotify/Plugin.cs
+++ b/Gotify/Plugin.cs
@@ -1,11 +1,28 @@
namespace FileFlows.Gotify;
+///
+/// A Gotify Plugin
+///
public class Plugin : FileFlows.Plugin.IPlugin
{
+ ///
+ /// Gets the UID for this plugin
+ ///
public Guid Uid => new Guid("3d8e13f2-819f-437f-b177-be40147c6e2b");
+
+ ///
+ /// Gets the name of this plugin
+ ///
public string Name => "Gotify Nodes";
+
+ ///
+ /// Gets the minimum version of FileFlows required for this plugin
+ ///
public string MinimumVersion => "1.0.4.2019";
+ ///
+ /// Initializes this plugin
+ ///
public void Init()
{
}
diff --git a/Gotify/PluginSettings.cs b/Gotify/PluginSettings.cs
index 825558be..73d8a105 100644
--- a/Gotify/PluginSettings.cs
+++ b/Gotify/PluginSettings.cs
@@ -1,18 +1,21 @@
-namespace FileFlows.Gotify
+namespace FileFlows.Gotify;
+
+///
+/// The plugin settings for this plugin
+///
+public class PluginSettings : IPluginSettings
{
- using FileFlows.Plugin;
- using FileFlows.Plugin.Attributes;
- using System;
- using System.ComponentModel.DataAnnotations;
+ ///
+ /// Gets or sets the URL to the server to send messages to
+ ///
+ [Text(1)]
+ [Required]
+ public string ServerUrl { get; set; }
- public class PluginSettings:IPluginSettings
- {
- [Text(1)]
- [Required]
- public string ServerUrl { get; set; }
-
- [Text(2)]
- [Required]
- public string AccessToken { get; set; }
- }
+ ///
+ /// Gets or sets the Access Token for the server
+ ///
+ [Text(2)]
+ [Required]
+ public string AccessToken { get; set; }
}
diff --git a/Telegram/Communication/Telegram.cs b/Telegram/Communication/Telegram.cs
new file mode 100644
index 00000000..9b13c94b
--- /dev/null
+++ b/Telegram/Communication/Telegram.cs
@@ -0,0 +1,101 @@
+namespace FileFlows.Telegram.Communication;
+
+///
+/// A Telegram flow element that sends a message
+///
+public class Telegram: Node
+{
+ ///
+ /// Gets the number of inputs to this flow element
+ ///
+ public override int Inputs => 1;
+ ///
+ /// Gets the number of outputs to this flow element
+ ///
+ public override int Outputs => 2;
+ ///
+ /// Gets the type of flow element
+ ///
+ public override FlowElementType Type => FlowElementType.Communication;
+ ///
+ /// Gets the icon for this flow element
+ ///
+ public override string Icon => "fas fa-bell";
+ ///
+ /// Gets if this can be used in a failure flow
+ ///
+ public override bool FailureNode => true;
+
+ ///
+ /// Gets or sets the message to send
+ ///
+ [Required]
+ [TextVariable(1)]
+ public string Message { get; set; }
+
+ ///
+ /// Sends a telegram message
+ ///
+ /// the bot token
+ /// the chat id
+ /// the message to send
+ /// true if successful, otherwise false
+ internal static bool SendMessage(string botToken, string chatId, string message)
+ {
+ using (HttpClient client = new HttpClient())
+ {
+ string apiUrl = $"https://api.telegram.org/bot{botToken}/sendMessage";
+
+ var content = new FormUrlEncodedContent(new[]
+ {
+ new KeyValuePair("chat_id", chatId.ToString()),
+ new KeyValuePair("text", message)
+ });
+
+ var response = client.PostAsync(apiUrl, content).Result;
+ return response.IsSuccessStatusCode;
+ }
+ }
+
+ ///
+ /// Executes the flow element
+ ///
+ /// the node parameters
+ /// the output to call next
+ public override int Execute(NodeParameters args)
+ {
+ try
+ {
+ var settings = args.GetPluginSettings();
+
+ if (settings == null)
+ {
+ args.Logger?.ILog("Failed to load plugin settings");
+ return 2;
+ }
+
+ if (string.IsNullOrWhiteSpace(settings?.BotToken))
+ {
+ args.Logger?.WLog("No Bot Token set");
+ return 2;
+ }
+
+ if (string.IsNullOrWhiteSpace(settings?.ChatId))
+ {
+ args.Logger?.WLog("No Chat ID set");
+ return 2;
+ }
+
+ var message = args.ReplaceVariables(Message);
+
+ var result = SendMessage(settings.BotToken, settings.ChatId, message);
+
+ return result ? 1 : 2;
+ }
+ catch (Exception ex)
+ {
+ args.Logger?.WLog("Error sending message: " + ex.Message);
+ return 2;
+ }
+ }
+}
diff --git a/Telegram/ExtensionMethods.cs b/Telegram/ExtensionMethods.cs
new file mode 100644
index 00000000..af5a3c9f
--- /dev/null
+++ b/Telegram/ExtensionMethods.cs
@@ -0,0 +1,14 @@
+namespace FileFlows.Telegram;
+
+///
+/// Extension methods
+///
+internal static class ExtensionMethods
+{
+ ///
+ /// Returns an empty string as null, otherwise returns the original string
+ ///
+ /// the input string
+ /// the string or null if empty
+ public static string? EmptyAsNull(this string str) => str == string.Empty ? null : str;
+}
diff --git a/Telegram/GlobalUsings.cs b/Telegram/GlobalUsings.cs
new file mode 100644
index 00000000..9c301eba
--- /dev/null
+++ b/Telegram/GlobalUsings.cs
@@ -0,0 +1,5 @@
+global using System;
+global using System.Text;
+global using System.ComponentModel.DataAnnotations;
+global using FileFlows.Plugin;
+global using FileFlows.Plugin.Attributes;
\ No newline at end of file
diff --git a/Telegram/Plugin.cs b/Telegram/Plugin.cs
new file mode 100644
index 00000000..355f9264
--- /dev/null
+++ b/Telegram/Plugin.cs
@@ -0,0 +1,29 @@
+namespace FileFlows.Telegram;
+
+///
+/// A Telegram Plugin
+///
+public class Plugin : FileFlows.Plugin.IPlugin
+{
+ ///
+ /// Gets the UID for this plugin
+ ///
+ public Guid Uid => new Guid("a610837d-c6d6-438b-8470-33a407ea7c98");
+
+ ///
+ /// Gets the name of this plugin
+ ///
+ public string Name => "Telegram";
+
+ ///
+ /// Gets the minimum version of FileFlows required for this plugin
+ ///
+ public string MinimumVersion => "1.0.4.2019";
+
+ ///
+ /// Initializes this plugin
+ ///
+ public void Init()
+ {
+ }
+}
diff --git a/Telegram/PluginSettings.cs b/Telegram/PluginSettings.cs
new file mode 100644
index 00000000..930d3f34
--- /dev/null
+++ b/Telegram/PluginSettings.cs
@@ -0,0 +1,21 @@
+namespace FileFlows.Telegram;
+
+///
+/// The plugin settings for this plugin
+///
+public class PluginSettings : IPluginSettings
+{
+ ///
+ /// Gets or sets the bot token
+ ///
+ [Text(1)]
+ [Required]
+ public string BotToken { get; set; }
+
+ ///
+ /// Gets or sets the chat ID
+ ///
+ [Text(1)]
+ [Required]
+ public string ChatId { get; set; }
+}
\ No newline at end of file
diff --git a/Telegram/Telegram.en.json b/Telegram/Telegram.en.json
new file mode 100644
index 00000000..7c7b5c4b
--- /dev/null
+++ b/Telegram/Telegram.en.json
@@ -0,0 +1,28 @@
+{
+ "Plugins": {
+ "Telegram": {
+ "Description": "A plugin that allows you to send Telegram messages.",
+ "Fields": {
+ "BotToken": "Bot Token",
+ "BotToken-Help":"Your telegram bot token.",
+ "ChatId": "Chat ID",
+ "ChatId-Help":"The ID of the chat to send messages to."
+ }
+ }
+ },
+ "Flow": {
+ "Parts": {
+ "Telegram": {
+ "Outputs": {
+ "1": "Telegram message sent",
+ "2": "Telegram message failed to send"
+ },
+ "Description": "Sends a Telegram message.",
+ "Fields": {
+ "Message": "Message",
+ "Message-Help": "The message to send."
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Telegram/Tests/TelegramTests.cs b/Telegram/Tests/TelegramTests.cs
new file mode 100644
index 00000000..0f59d48e
--- /dev/null
+++ b/Telegram/Tests/TelegramTests.cs
@@ -0,0 +1,23 @@
+#if(DEBUG)
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace FileFlows.Telegram.Tests;
+
+[TestClass]
+public class TelegramTests
+{
+ [TestMethod]
+ public void SendMessage()
+ {
+ string botToken = "sometoken";
+ string chatId = "somechat";
+
+ var result =
+ Communication.Telegram.SendMessage(botToken, chatId, "this is a test");
+
+ Assert.IsTrue(result);
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Telegram/Tests/TestLogger.cs b/Telegram/Tests/TestLogger.cs
new file mode 100644
index 00000000..054d3552
--- /dev/null
+++ b/Telegram/Tests/TestLogger.cs
@@ -0,0 +1,59 @@
+#if(DEBUG)
+
+namespace FileFlows.Telegram.Tests;
+
+using FileFlows.Plugin;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+internal class TestLogger : ILogger
+{
+ private List Messages = new List();
+
+ public void DLog(params object[] args) => Log("DBUG", args);
+
+ public void ELog(params object[] args) => Log("ERRR", args);
+
+ public void ILog(params object[] args) => Log("INFO", args);
+
+ public void WLog(params object[] args) => Log("WARN", args);
+ private void Log(string type, object[] args)
+ {
+ if (args == null || args.Length == 0)
+ return;
+ string message = type + " -> " +
+ string.Join(", ", args.Select(x =>
+ x == null ? "null" :
+ x.GetType().IsPrimitive || x is string ? x.ToString() :
+ System.Text.Json.JsonSerializer.Serialize(x)));
+ Messages.Add(message);
+ }
+
+ public bool Contains(string message)
+ {
+ if (string.IsNullOrWhiteSpace(message))
+ return false;
+
+ string log = string.Join(Environment.NewLine, Messages);
+ return log.Contains(message);
+ }
+
+ public override string ToString()
+ {
+ return String.Join(Environment.NewLine, this.Messages.ToArray());
+ }
+
+ public string GetTail(int length = 50)
+ {
+ if (length <= 0)
+ length = 50;
+ if (Messages.Count <= length)
+ return string.Join(Environment.NewLine, Messages);
+ return string.Join(Environment.NewLine, Messages.TakeLast(length));
+ }
+}
+
+#endif
\ No newline at end of file