From 7ac450140f04a842fda811c28f788eb33cddb1df Mon Sep 17 00:00:00 2001 From: FlorianDahn Date: Sat, 19 May 2018 23:23:01 +0200 Subject: [PATCH] =?UTF-8?q?Projektdateien=20hinzuf=C3=BCgen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Bot.txt | 3 + Telegram.sln | 28 ++ TelegramBaseTest/App.config | 6 + TelegramBaseTest/Program.cs | 64 ++++ TelegramBaseTest/Properties/AssemblyInfo.cs | 36 ++ TelegramBaseTest/TelegramBaseTest.csproj | 66 ++++ TelegramBotBase/Base/ActionResult.cs | 91 ++++++ .../Base/ButtonClickedEventArgs.cs | 26 ++ TelegramBotBase/Base/MessageClient.cs | 126 +++++++ TelegramBotBase/Base/MessageResult.cs | 132 ++++++++ TelegramBotBase/Base/MessageSentEventArgs.cs | 29 ++ TelegramBotBase/Base/ResultBase.cs | 53 +++ TelegramBotBase/Base/SessionBeginResult.cs | 22 ++ TelegramBotBase/Base/SystemCallEventArgs.cs | 33 ++ .../Base/SystemExceptionEventArgs.cs | 36 ++ .../Base/UnhandledCallEventArgs.cs | 45 +++ TelegramBotBase/BotBase.cs | 308 ++++++++++++++++++ TelegramBotBase/Form/AlertDialog.cs | 25 ++ TelegramBotBase/Form/ArrayPromptDialog.cs | 108 ++++++ TelegramBotBase/Form/AutoCleanForm.cs | 103 ++++++ TelegramBotBase/Form/ButtonBase.cs | 27 ++ TelegramBotBase/Form/ButtonForm.cs | 81 +++++ TelegramBotBase/Form/CallbackData.cs | 66 ++++ TelegramBotBase/Form/FormBase.cs | 126 +++++++ TelegramBotBase/Form/PromptDialog.cs | 102 ++++++ TelegramBotBase/Properties/AssemblyInfo.cs | 36 ++ TelegramBotBase/SessionBase.cs | 71 ++++ TelegramBotBase/Sessions/DeviceSession.cs | 270 +++++++++++++++ TelegramBotBase/TelegramBotBase.csproj | 96 ++++++ TelegramBotBase/Tests/TestForm.cs | 83 +++++ TelegramBotBase/Tests/TestForm2.cs | 111 +++++++ TelegramBotBase/Tools/Images.cs | 22 ++ TelegramBotBase/packages.config | 37 +++ 33 files changed, 2468 insertions(+) create mode 100644 Bot.txt create mode 100644 Telegram.sln create mode 100644 TelegramBaseTest/App.config create mode 100644 TelegramBaseTest/Program.cs create mode 100644 TelegramBaseTest/Properties/AssemblyInfo.cs create mode 100644 TelegramBaseTest/TelegramBaseTest.csproj create mode 100644 TelegramBotBase/Base/ActionResult.cs create mode 100644 TelegramBotBase/Base/ButtonClickedEventArgs.cs create mode 100644 TelegramBotBase/Base/MessageClient.cs create mode 100644 TelegramBotBase/Base/MessageResult.cs create mode 100644 TelegramBotBase/Base/MessageSentEventArgs.cs create mode 100644 TelegramBotBase/Base/ResultBase.cs create mode 100644 TelegramBotBase/Base/SessionBeginResult.cs create mode 100644 TelegramBotBase/Base/SystemCallEventArgs.cs create mode 100644 TelegramBotBase/Base/SystemExceptionEventArgs.cs create mode 100644 TelegramBotBase/Base/UnhandledCallEventArgs.cs create mode 100644 TelegramBotBase/BotBase.cs create mode 100644 TelegramBotBase/Form/AlertDialog.cs create mode 100644 TelegramBotBase/Form/ArrayPromptDialog.cs create mode 100644 TelegramBotBase/Form/AutoCleanForm.cs create mode 100644 TelegramBotBase/Form/ButtonBase.cs create mode 100644 TelegramBotBase/Form/ButtonForm.cs create mode 100644 TelegramBotBase/Form/CallbackData.cs create mode 100644 TelegramBotBase/Form/FormBase.cs create mode 100644 TelegramBotBase/Form/PromptDialog.cs create mode 100644 TelegramBotBase/Properties/AssemblyInfo.cs create mode 100644 TelegramBotBase/SessionBase.cs create mode 100644 TelegramBotBase/Sessions/DeviceSession.cs create mode 100644 TelegramBotBase/TelegramBotBase.csproj create mode 100644 TelegramBotBase/Tests/TestForm.cs create mode 100644 TelegramBotBase/Tests/TestForm2.cs create mode 100644 TelegramBotBase/Tools/Images.cs create mode 100644 TelegramBotBase/packages.config diff --git a/Bot.txt b/Bot.txt new file mode 100644 index 0000000..d7d4d4f --- /dev/null +++ b/Bot.txt @@ -0,0 +1,3 @@ +@TGBaseBot + +480896099:AAHo0KIurkdugqdZ1tYh7sik3tJ9guH2uuI \ No newline at end of file diff --git a/Telegram.sln b/Telegram.sln new file mode 100644 index 0000000..633f797 --- /dev/null +++ b/Telegram.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelegramBaseTest", "TelegramBaseTest\TelegramBaseTest.csproj", "{5817184C-0D59-4924-AC6C-6B943967811C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelegramBotBase", "TelegramBotBase\TelegramBotBase.csproj", "{A61EDA27-CFDF-4BCB-B2D6-184F94904F2D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5817184C-0D59-4924-AC6C-6B943967811C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5817184C-0D59-4924-AC6C-6B943967811C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5817184C-0D59-4924-AC6C-6B943967811C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5817184C-0D59-4924-AC6C-6B943967811C}.Release|Any CPU.Build.0 = Release|Any CPU + {A61EDA27-CFDF-4BCB-B2D6-184F94904F2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A61EDA27-CFDF-4BCB-B2D6-184F94904F2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A61EDA27-CFDF-4BCB-B2D6-184F94904F2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A61EDA27-CFDF-4BCB-B2D6-184F94904F2D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/TelegramBaseTest/App.config b/TelegramBaseTest/App.config new file mode 100644 index 0000000..88fa402 --- /dev/null +++ b/TelegramBaseTest/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TelegramBaseTest/Program.cs b/TelegramBaseTest/Program.cs new file mode 100644 index 0000000..00e5d2b --- /dev/null +++ b/TelegramBaseTest/Program.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase; +using TelegramBotBase.Form; +using TelegramBotBase.Tests; + +namespace TelegramBaseTest +{ + class Program + { + static void Main(string[] args) + { + + + + BotBase bb = new BotBase("480896099:AAHo0KIurkdugqdZ1tYh7sik3tJ9guH2uuI"); + + bb.SystemCalls.Add("/start"); + bb.SystemCalls.Add("/form1"); + bb.SystemCalls.Add("/form2"); + + bb.SystemCall += (s, en) => + { + switch(en.Command) + { + case "/form1": + + var form1 = new TestForm(); + form1.Init(); + + en.Device.ActiveForm.NavigateTo(form1); + + break; + case "/form2": + + var form2 = new TestForm2(); + form2.Init(); + + en.Device.ActiveForm.NavigateTo(form2); + + break; + } + + }; + + bb.Start(); + + + + Console.WriteLine("Telegram Bot started..."); + + Console.WriteLine("Press q to quit application."); + + + Console.ReadLine(); + + bb.Stop(); + + } + } +} diff --git a/TelegramBaseTest/Properties/AssemblyInfo.cs b/TelegramBaseTest/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9b1622a --- /dev/null +++ b/TelegramBaseTest/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("TelegramBaseTest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TelegramBaseTest")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("5817184c-0d59-4924-ac6c-6b943967811c")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TelegramBaseTest/TelegramBaseTest.csproj b/TelegramBaseTest/TelegramBaseTest.csproj new file mode 100644 index 0000000..c648fdf --- /dev/null +++ b/TelegramBaseTest/TelegramBaseTest.csproj @@ -0,0 +1,66 @@ + + + + + Debug + AnyCPU + {5817184C-0D59-4924-AC6C-6B943967811C} + Exe + Properties + TelegramBaseTest + TelegramBaseTest + v4.5.2 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + {a61eda27-cfdf-4bcb-b2d6-184f94904f2d} + TelegramBotBase + + + + + \ No newline at end of file diff --git a/TelegramBotBase/Base/ActionResult.cs b/TelegramBotBase/Base/ActionResult.cs new file mode 100644 index 0000000..f8f6a0f --- /dev/null +++ b/TelegramBotBase/Base/ActionResult.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TelegramBotBase.Base +{ + //public class ActionResult : ResultBase + //{ + // public Telegram.Bot.Args.CallbackQueryEventArgs RawCallbackData { get; set; } + + // public override long DeviceId + // { + // get + // { + // return this.RawCallbackData?.CallbackQuery.Message?.Chat.Id ?? 0; + // } + // } + + // public String Command + // { + // get + // { + // return this.RawCallbackData.CallbackQuery.Message.Text ?? ""; + // } + // } + + // public String RawData + // { + // get + // { + // return this.RawCallbackData.CallbackQuery.Data; + // } + // } + + // public T GetData() + // where T : class + // { + // T cd = null; + // try + // { + // cd = Newtonsoft.Json.JsonConvert.DeserializeObject(this.RawData); + + // return cd; + // } + // catch + // { + + // } + + // return null; + // } + + // /// + // /// Bestätigt den Erhalt der Aktion. + // /// + // /// + // /// + // public async Task ConfirmAction(String message = "") + // { + // try + // { + // await this.Client.TelegramClient.AnswerCallbackQueryAsync(this.RawCallbackData.CallbackQuery.Id, message); + // } + // catch + // { + + // } + // } + + // public override async Task DeleteMessage() + // { + // try + // { + // await this.Client.TelegramClient.DeleteMessageAsync(this.DeviceId, this.RawCallbackData.CallbackQuery.Message.MessageId); + // } + // catch + // { + + // } + // } + + // public ActionResult(Telegram.Bot.Args.CallbackQueryEventArgs callback) + // { + // this.RawCallbackData = callback; + // this.Message = callback.CallbackQuery.Message; + // } + + //} +} diff --git a/TelegramBotBase/Base/ButtonClickedEventArgs.cs b/TelegramBotBase/Base/ButtonClickedEventArgs.cs new file mode 100644 index 0000000..33750d9 --- /dev/null +++ b/TelegramBotBase/Base/ButtonClickedEventArgs.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Form; + +namespace TelegramBotBase.Base +{ + public class ButtonClickedEventArgs : EventArgs + { + public ButtonBase Button { get; set; } + + + public ButtonClickedEventArgs() + { + + } + + public ButtonClickedEventArgs(ButtonBase button) + { + this.Button = button; + } + + } +} diff --git a/TelegramBotBase/Base/MessageClient.cs b/TelegramBotBase/Base/MessageClient.cs new file mode 100644 index 0000000..9ab07eb --- /dev/null +++ b/TelegramBotBase/Base/MessageClient.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TelegramBotBase.Base +{ + public class MessageClient + { + + public String APIKey { get; set; } + + public Telegram.Bot.TelegramBotClient TelegramClient { get; set; } + + private EventHandlerList __Events { get; set; } = new EventHandlerList(); + + private static object __evOnMessage = new object(); + + private static object __evCallbackQuery = new object(); + + + public MessageClient(String APIKey) + { + this.APIKey = APIKey; + this.TelegramClient = new Telegram.Bot.TelegramBotClient(APIKey); + + Prepare(); + } + + public MessageClient(String APIKey, Telegram.Bot.TelegramBotClient Client) + { + this.APIKey = APIKey; + this.TelegramClient = Client; + + Prepare(); + } + + + public void Prepare() + { + this.TelegramClient.Timeout = new TimeSpan(0, 0, 30); + + + this.TelegramClient.OnMessage += TelegramClient_OnMessage; + this.TelegramClient.OnCallbackQuery += TelegramClient_OnCallbackQuery; + + } + + + private async void TelegramClient_OnMessage(object sender, Telegram.Bot.Args.MessageEventArgs e) + { + //Skip empty messages by default + if (e.Message == null) + return; + + try + { + var mr = new MessageResult(e); + mr.Client = this; + OnMessage(mr); + } + catch + { + + } + } + + private async void TelegramClient_OnCallbackQuery(object sender, Telegram.Bot.Args.CallbackQueryEventArgs e) + { + try + { + var ar = new MessageResult(e); + ar.Client = this; + OnAction(ar); + } + catch + { + + } + } + + + #region "Events" + + public event EventHandler Message + { + add + { + this.__Events.AddHandler(__evOnMessage, value); + } + remove + { + this.__Events.RemoveHandler(__evOnMessage, value); + } + } + + public void OnMessage(MessageResult result) + { + (this.__Events[__evOnMessage] as EventHandler)?.Invoke(this, result); + } + + public event EventHandler Action + { + add + { + this.__Events.AddHandler(__evCallbackQuery, value); + } + remove + { + this.__Events.RemoveHandler(__evCallbackQuery, value); + } + } + + public void OnAction(MessageResult result) + { + (this.__Events[__evCallbackQuery] as EventHandler)?.Invoke(this, result); + } + + + #endregion + + + } +} diff --git a/TelegramBotBase/Base/MessageResult.cs b/TelegramBotBase/Base/MessageResult.cs new file mode 100644 index 0000000..7dec05f --- /dev/null +++ b/TelegramBotBase/Base/MessageResult.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TelegramBotBase.Base +{ + public class MessageResult : ResultBase + { + public Telegram.Bot.Args.MessageEventArgs RawMessageData { get; set; } + + public Telegram.Bot.Args.CallbackQueryEventArgs RawCallbackData { get; set; } + + public override long DeviceId + { + get + { + return this.RawMessageData?.Message?.Chat.Id ?? this.RawCallbackData?.CallbackQuery.Message?.Chat.Id ?? 0; + } + } + + /// + /// Die Id der Nachricht + /// + public new int MessageId + { + get + { + return this.Message?.MessageId ?? this.RawCallbackData?.CallbackQuery?.Message?.MessageId ?? 0; + } + } + + public String Command + { + get + { + return this.RawMessageData?.Message?.Text ?? ""; + } + } + + public String MessageText + { + get + { + return this.RawMessageData?.Message?.Text ?? ""; + } + } + + /// + /// Ist diese eine Aktion? (z.B.: Button Klick) + /// + public bool IsAction + { + get + { + return (this.RawCallbackData != null); + } + } + + public bool Handled { get; set; } = false; + + public String RawData + { + get + { + return this.RawCallbackData.CallbackQuery.Data; + } + } + + public T GetData() + where T : class + { + T cd = null; + try + { + cd = Newtonsoft.Json.JsonConvert.DeserializeObject(this.RawData); + + return cd; + } + catch + { + + } + + return null; + } + + /// + /// Bestätigt den Erhalt der Aktion. + /// + /// + /// + public async Task ConfirmAction(String message = "") + { + try + { + await this.Client.TelegramClient.AnswerCallbackQueryAsync(this.RawCallbackData.CallbackQuery.Id, message); + } + catch + { + + } + } + + public override async Task DeleteMessage() + { + try + { + await base.DeleteMessage(this.MessageId); + } + catch + { + + } + } + + + public MessageResult(Telegram.Bot.Args.MessageEventArgs rawdata) + { + this.RawMessageData = rawdata; + this.Message = rawdata.Message; + } + + public MessageResult(Telegram.Bot.Args.CallbackQueryEventArgs callback) + { + this.RawCallbackData = callback; + this.Message = callback.CallbackQuery.Message; + } + + } +} diff --git a/TelegramBotBase/Base/MessageSentEventArgs.cs b/TelegramBotBase/Base/MessageSentEventArgs.cs new file mode 100644 index 0000000..c71072a --- /dev/null +++ b/TelegramBotBase/Base/MessageSentEventArgs.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Telegram.Bot.Types; + +namespace TelegramBotBase.Base +{ + public class MessageSentEventArgs + { + public int MessageId { get; set; } + + public Message Message { get; set; } + + public MessageSentEventArgs() + { + + } + + public MessageSentEventArgs(int MessageId, Message message) + { + this.MessageId = MessageId; + this.Message = message; + } + + + } +} diff --git a/TelegramBotBase/Base/ResultBase.cs b/TelegramBotBase/Base/ResultBase.cs new file mode 100644 index 0000000..b792b7d --- /dev/null +++ b/TelegramBotBase/Base/ResultBase.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TelegramBotBase.Base +{ + public class ResultBase + { + public MessageClient Client { get; set; } + + public virtual long DeviceId { get; set; } + + public int MessageId + { + get + { + return this.Message.MessageId; + } + } + + public Telegram.Bot.Types.Message Message { get; set; } + + /// + /// Löscht die aktuelle Nachricht, oder die übergebene + /// + /// + /// + public virtual async Task DeleteMessage() + { + await DeleteMessage(this.MessageId); + } + + /// + /// Löscht die aktuelle Nachricht, oder die übergebene + /// + /// + /// + public virtual async Task DeleteMessage(int messageId = -1) + { + try + { + await this.Client.TelegramClient.DeleteMessageAsync(this.DeviceId, (messageId == -1 ? this.MessageId : messageId)); + } + catch + { + + } + } + + } +} diff --git a/TelegramBotBase/Base/SessionBeginResult.cs b/TelegramBotBase/Base/SessionBeginResult.cs new file mode 100644 index 0000000..084d41a --- /dev/null +++ b/TelegramBotBase/Base/SessionBeginResult.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Sessions; + +namespace TelegramBotBase.Base +{ + public class SessionBeginResult : EventArgs + { + public long DeviceId { get; set; } + + public DeviceSession Device { get; set; } + + public SessionBeginResult(long DeviceId, DeviceSession Device) + { + this.DeviceId = DeviceId; + this.Device = Device; + } + } +} diff --git a/TelegramBotBase/Base/SystemCallEventArgs.cs b/TelegramBotBase/Base/SystemCallEventArgs.cs new file mode 100644 index 0000000..bf0b0f3 --- /dev/null +++ b/TelegramBotBase/Base/SystemCallEventArgs.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Sessions; + +namespace TelegramBotBase.Base +{ + public class SystemCallEventArgs : EventArgs + { + public String Command { get; set; } + + public long DeviceId { get; set; } + + public DeviceSession Device {get;set;} + + + public SystemCallEventArgs() + { + + + } + + public SystemCallEventArgs(String Command, long DeviceId, DeviceSession Device) + { + this.Command = Command; + this.DeviceId = DeviceId; + this.Device = Device; + } + + } +} diff --git a/TelegramBotBase/Base/SystemExceptionEventArgs.cs b/TelegramBotBase/Base/SystemExceptionEventArgs.cs new file mode 100644 index 0000000..af2bba6 --- /dev/null +++ b/TelegramBotBase/Base/SystemExceptionEventArgs.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Sessions; + +namespace TelegramBotBase.Base +{ + public class SystemExceptionEventArgs : EventArgs + { + + public String Command { get; set; } + + public long DeviceId { get; set; } + + public DeviceSession Device { get; set; } + + public Exception Error { get; set; } + + public SystemExceptionEventArgs() + { + + + } + + public SystemExceptionEventArgs(String Command, long DeviceId, DeviceSession Device, Exception error) + { + this.Command = Command; + this.DeviceId = DeviceId; + this.Device = Device; + this.Error = error; + } + } + +} diff --git a/TelegramBotBase/Base/UnhandledCallEventArgs.cs b/TelegramBotBase/Base/UnhandledCallEventArgs.cs new file mode 100644 index 0000000..0d2209a --- /dev/null +++ b/TelegramBotBase/Base/UnhandledCallEventArgs.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Telegram.Bot.Types; +using TelegramBotBase.Sessions; + +namespace TelegramBotBase.Base +{ + public class UnhandledCallEventArgs : EventArgs + { + public String Command { get; set; } + + public long DeviceId { get; set; } + + public DeviceSession Device {get;set;} + + public String RawData { get; set; } + + public int MessageId { get; set; } + + public Message Message { get; set; } + + public bool Handled { get; set; } + + + public UnhandledCallEventArgs() + { + this.Handled = false; + + } + + public UnhandledCallEventArgs(String Command,String RawData, long DeviceId, int MessageId, Message message, DeviceSession Device) : this() + { + this.Command = Command; + this.RawData = RawData; + this.DeviceId = DeviceId; + this.MessageId = MessageId; + this.Message = message; + this.Device = Device; + } + + } +} diff --git a/TelegramBotBase/BotBase.cs b/TelegramBotBase/BotBase.cs new file mode 100644 index 0000000..699620d --- /dev/null +++ b/TelegramBotBase/BotBase.cs @@ -0,0 +1,308 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Base; +using TelegramBotBase.Form; +using TelegramBotBase.Sessions; + +namespace TelegramBotBase +{ + public class BotBase + where T : FormBase + { + public MessageClient Client { get; set; } + + public String APIKey { get; set; } = ""; + + + public SessionBase Sessions { get; set; } + + /// + /// Beinhaltet Systembefehle die immer erreichbar sind und nicht an die Formulare weitergereicht werden. z.b. /start + /// + public List SystemCalls { get; set; } + + private EventHandlerList __Events = new EventHandlerList(); + + private static object __evSessionBegins = new object(); + + private static object __evSystemCall = new object(); + + private static object __evException = new object(); + + private static object __evUnhandledCall = new object(); + + public BotBase(String apiKey) + { + this.APIKey = apiKey; + + this.Client = new Base.MessageClient(this.APIKey); + + this.SystemCalls = new List(); + + this.Sessions = new SessionBase(); + this.Sessions.Client = this.Client; + } + + public void Start() + { + if (this.Client == null) + return; + + this.Client.Message += Client_Message; + this.Client.Action += Client_Action; + + + this.Client.TelegramClient.StartReceiving(); + } + + + public void Stop() + { + if (this.Client == null) + return; + + this.Client.TelegramClient.StopReceiving(); + } + + + public async Task SentToAll(String message) + { + if (this.Client == null) + return; + + foreach (var s in this.Sessions.SessionList) + { + await this.Client.TelegramClient.SendTextMessageAsync(s.Key, message); + } + } + + private void Client_Message(object sender, MessageResult e) + { + try + { + Client_TryMessage(sender, e); + } + catch (Exception ex) + { + DeviceSession ds = this.Sessions.GetSession(e.DeviceId); + OnException(new SystemExceptionEventArgs(e.Message.Text, ds?.DeviceId ?? -1, ds, ex)); + } + } + + private async void Client_TryMessage(object sender, MessageResult e) + { + DeviceSession ds = this.Sessions.GetSession(e.DeviceId); + if (ds == null) + { + ds = await this.Sessions.StartSession(e.DeviceId); + + ds.LastMessage = e.MessageId; + + OnSessionBegins(new SessionBeginResult(e.DeviceId, ds)); + } + + ds.LastAction = DateTime.Now; + ds.LastMessage = e.MessageId; + + + //Ist das ein Systembefehl ? + if (e.Message.Text != null && this.SystemCalls.Contains(e.Message.Text)) + { + var sce = new SystemCallEventArgs(e.Message.Text, ds.DeviceId, ds); + OnSystemCall(sce); + //return; + } + + FormBase activeForm = null; + + int i = 0; + + //Sollten die Formulare gewechselt werden, alle durchgehen (maximal 10 Versuche, um Schleifen zu verhindern) + do + { + i++; + + activeForm = ds.ActiveForm; + + //Wenn das Formular sich selbst um die Events kümmert, nicht weiter machen + if (activeForm.CustomEventManagement) + return; + + //Pre Loading Event + await activeForm.PreLoad(e); + + //Loading Event + await activeForm.Load(e); + + ////Action Event + //if (!activeForm.FormSwitched) + // await activeForm.Action(e); + + //Render Event + if (!activeForm.FormSwitched) + await activeForm.Render(e); + + } while (activeForm.FormSwitched && i < 10); + + } + + private void Client_Action(object sender, MessageResult e) + { + try + { + Client_TryAction(sender, e); + } + catch (Exception ex) + { + DeviceSession ds = this.Sessions.GetSession(e.DeviceId); + OnException(new SystemExceptionEventArgs(e.Message.Text, ds?.DeviceId ?? -1, ds, ex)); + } + } + + private async void Client_TryAction(object sender, MessageResult e) + { + DeviceSession ds = this.Sessions.GetSession(e.DeviceId); + if (ds == null) + { + ds = await this.Sessions.StartSession(e.DeviceId); + } + + + ds.LastAction = DateTime.Now; + ds.LastMessage = e.MessageId; + + FormBase activeForm = null; + + int i = 0; + + //Sollten die Formulare gewechselt werden, alle durchgehen (maximal 10 Versuche, um Schleifen zu verhindern) + do + { + i++; + + activeForm = ds.ActiveForm; + + //Wenn das Formular sich selbst um die Events kümmert, nicht weiter machen + if (activeForm.CustomEventManagement) + return; + + //Pre Loading Event + await activeForm.PreLoad(e); + + //Loading Event + await activeForm.Load(e); + + //Action Event + if (!activeForm.FormSwitched) + { + await activeForm.Action(e); + + if (!e.Handled) + { + var uhc = new UnhandledCallEventArgs(e.Message.Text, e.RawData, ds.DeviceId, e.MessageId, e.Message, ds); + OnUnhandledCall(uhc); + + if (uhc.Handled) + { + if (activeForm.FormSwitched) + { + continue; + } + else + { + break; + } + } + } + + } + + //Render Event + if (!activeForm.FormSwitched) + await activeForm.Render(e); + + } while (activeForm.FormSwitched && i < 10); + + } + + /// + /// Wird aufgerufen wenn eine Session begonnen wird + /// + + public event EventHandler SessionBegins + { + add + { + this.__Events.AddHandler(__evSessionBegins, value); + } + remove + { + this.__Events.RemoveHandler(__evSessionBegins, value); + } + } + + public void OnSessionBegins(SessionBeginResult e) + { + (this.__Events[__evSessionBegins] as EventHandler)?.Invoke(this, e); + + } + + public event EventHandler SystemCall + { + add + { + this.__Events.AddHandler(__evSystemCall, value); + } + remove + { + this.__Events.RemoveHandler(__evSystemCall, value); + } + } + + public void OnSystemCall(SystemCallEventArgs e) + { + (this.__Events[__evSystemCall] as EventHandler)?.Invoke(this, e); + + } + + public event EventHandler Exception + { + add + { + this.__Events.AddHandler(__evException, value); + } + remove + { + this.__Events.RemoveHandler(__evException, value); + } + } + + public void OnException(SystemExceptionEventArgs e) + { + (this.__Events[__evException] as EventHandler)?.Invoke(this, e); + + } + + public event EventHandler UnhandledCall + { + add + { + this.__Events.AddHandler(__evUnhandledCall, value); + } + remove + { + this.__Events.RemoveHandler(__evUnhandledCall, value); + } + } + + public void OnUnhandledCall(UnhandledCallEventArgs e) + { + (this.__Events[__evUnhandledCall] as EventHandler)?.Invoke(this, e); + + } + } +} diff --git a/TelegramBotBase/Form/AlertDialog.cs b/TelegramBotBase/Form/AlertDialog.cs new file mode 100644 index 0000000..4634970 --- /dev/null +++ b/TelegramBotBase/Form/AlertDialog.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Base; + +namespace TelegramBotBase.Form +{ + public class AlertDialog : PromptDialog + { + public String ButtonText { get; set; } + + public AlertDialog(String Message, String ButtonText, FormBase FormToOpen = null) : base(Message) + { + this.Buttons.Add(new ButtonBase(ButtonText, "ok")); + this.ButtonText = ButtonText; + + if (FormToOpen != null) + this.ButtonForms.Add("ok", FormToOpen); + } + + } +} diff --git a/TelegramBotBase/Form/ArrayPromptDialog.cs b/TelegramBotBase/Form/ArrayPromptDialog.cs new file mode 100644 index 0000000..7a423b8 --- /dev/null +++ b/TelegramBotBase/Form/ArrayPromptDialog.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Base; + +namespace TelegramBotBase.Form +{ + public class ArrayPromptDialog : FormBase + { + public String Message { get; set; } + + + public ButtonBase[][] Buttons { get; set; } + + public Dictionary ButtonForms { get; set; } = new Dictionary(); + + private EventHandlerList __Events { get; set; } = new EventHandlerList(); + + private static object __evButtonClicked { get; } = new object(); + + public ArrayPromptDialog() + { + + } + + public ArrayPromptDialog(String Message) + { + this.Message = Message; + } + + public ArrayPromptDialog(String Message, params ButtonBase[][] Buttons) + { + this.Message = Message; + this.Buttons = Buttons; + } + + public override async Task Action(MessageResult message) + { + var call = message.GetData(); + + message.Handled = true; + + if (!message.IsAction) + return; + + await message.ConfirmAction(); + + await message.DeleteMessage(); + + var buttons = this.Buttons.Aggregate((a, b) => a.Union(b).ToArray()).ToList(); + + if(call==null) + { + return; + } + + ButtonBase button = buttons.FirstOrDefault(a => a.Value == call.Value); + + if (button == null) + { + return; + } + + OnButtonClicked(new ButtonClickedEventArgs(button)); + + FormBase fb = ButtonForms.ContainsKey(call.Value) ? ButtonForms[call.Value] : null; + + if (fb != null) + { + await this.NavigateTo(fb); + } + } + + + public override async Task Render(MessageResult message) + { + ButtonForm btn = new ButtonForm(); + + foreach(var bl in this.Buttons) + { + btn.AddButtonRow(bl.Select(a => new ButtonBase(a.Text, CallbackData.Create("action", a.Value))).ToList()); + } + + await this.Device.Send(this.Message, btn); + } + + + public event EventHandler ButtonClicked + { + add + { + this.__Events.AddHandler(__evButtonClicked, value); + } + remove + { + this.__Events.RemoveHandler(__evButtonClicked, value); + } + } + + public void OnButtonClicked(ButtonClickedEventArgs e) + { + (this.__Events[__evButtonClicked] as EventHandler)?.Invoke(this, e); + } + } +} diff --git a/TelegramBotBase/Form/AutoCleanForm.cs b/TelegramBotBase/Form/AutoCleanForm.cs new file mode 100644 index 0000000..22caa82 --- /dev/null +++ b/TelegramBotBase/Form/AutoCleanForm.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Telegram.Bot.Types; +using TelegramBotBase.Base; + +namespace TelegramBotBase.Form +{ + public class AutoCleanForm : FormBase + { + List OldMessages { get; set; } + + public eDeleteMode DeleteMode { get; set; } + + public enum eDeleteMode + { + OnEveryCall = 0, + OnLeavingForm = 1 + } + + public AutoCleanForm() + { + this.OldMessages = new List(); + this.DeleteMode = eDeleteMode.OnEveryCall; + + } + + public override async Task Init(params object[] args) + { + if (this.Device == null) + return; + + this.Device.MessageSent += Device_MessageSent; + } + + private void Device_MessageSent(object sender, MessageSentEventArgs e) + { + this.OldMessages.Add(e.Message); + } + + public override async Task PreLoad(MessageResult message) + { + if (this.DeleteMode != eDeleteMode.OnEveryCall) + return; + + while (this.OldMessages.Count > 0) + { + if (!await this.Device.DeleteMessage(this.OldMessages[0].MessageId)) + { + //Nachricht konnte nicht gelöscht werden, vermutlich existiert diese nicht mehr + if (this.OldMessages.Count > 0) + this.OldMessages.RemoveAt(0); + } + } + } + + /// + /// Fügt eine Nachricht zu der Liste der löschenden hinzu. + /// + /// + public void AddMessage(Message m) + { + this.OldMessages.Add(m); + } + + /// + /// Behält die Nachricht mit der angegebenen Id. + /// + /// + public void LeaveMessage(int Id) + { + var m = this.OldMessages.FirstOrDefault(a => a.MessageId == Id); + if (m == null) + return; + + this.OldMessages.Remove(m); + } + + /// + /// Behält die zuletzt gesendete Nachricht. + /// + public void LeaveLastMessage() + { + if (this.OldMessages.Count == 0) + return; + + this.OldMessages.RemoveAt(this.OldMessages.Count - 1); + } + + public async override Task Closed() + { + if (this.DeleteMode != eDeleteMode.OnLeavingForm) + return; + + foreach (var m in this.OldMessages) + { + await this.Device.DeleteMessage(m.MessageId); + } + } + } +} diff --git a/TelegramBotBase/Form/ButtonBase.cs b/TelegramBotBase/Form/ButtonBase.cs new file mode 100644 index 0000000..ac9e34d --- /dev/null +++ b/TelegramBotBase/Form/ButtonBase.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TelegramBotBase.Form +{ + public class ButtonBase + { + public String Text { get; set; } + + public String Value { get; set; } + + public ButtonBase() + { + + } + + public ButtonBase(String Text, String Value) + { + this.Text = Text; + this.Value = Value; + } + + } +} diff --git a/TelegramBotBase/Form/ButtonForm.cs b/TelegramBotBase/Form/ButtonForm.cs new file mode 100644 index 0000000..28ab687 --- /dev/null +++ b/TelegramBotBase/Form/ButtonForm.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Telegram.Bot.Types.InlineKeyboardButtons; +using Telegram.Bot.Types.ReplyMarkups; + +namespace TelegramBotBase.Form +{ + public class ButtonForm + { + List> Buttons = new List>(); + + public ButtonForm() + { + + } + + public void AddButtonRow(List row) + { + Buttons.Add(row); + } + + public void AddButtonRow(params ButtonBase[] row) + { + AddButtonRow(row.ToList()); + } + + public static T[][] SplitTo(IEnumerable items, int itemsPerRow = 2) + { + T[][] splitted = default(T[][]); + + try + { + var t = items.Select((a, index) => new { a, index }) + .GroupBy(a => a.index / itemsPerRow) + .Select(a => a.Select(b => b.a).ToArray()).ToArray(); + + splitted = t; + } + catch + { + + } + + return splitted; + } + + /// + /// Fügt die Buttons automatisch aufgesplittet in Spalten ein. + /// + /// + /// + public void AddSplitted(IEnumerable buttons, int buttonsPerRow = 2) + { + var sp = SplitTo(buttons, buttonsPerRow); + + foreach(var bl in sp) + { + AddButtonRow(bl); + } + } + + public InlineKeyboardButton[][] ToArray() + { + var ikb = this.Buttons.Select(a => a.Select(b => InlineKeyboardButton.WithCallbackData(b.Text, b.Value)).ToArray()).ToArray(); + + return ikb; + } + + public static implicit operator InlineKeyboardMarkup(ButtonForm form) + { + InlineKeyboardMarkup ikm = new InlineKeyboardMarkup(); + + ikm.InlineKeyboard = form.ToArray(); + + return ikm; + } + } +} diff --git a/TelegramBotBase/Form/CallbackData.cs b/TelegramBotBase/Form/CallbackData.cs new file mode 100644 index 0000000..8f31a11 --- /dev/null +++ b/TelegramBotBase/Form/CallbackData.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TelegramBotBase.Form +{ + public class CallbackData + { + public String Method { get; set; } + + public String Value { get; set; } + + + public CallbackData() + { + + } + + public CallbackData(String method, String value) + { + this.Method = method; + this.Value = value; + } + + public static String Create(String method, String value) + { + return new CallbackData(method, value).Serialize(); + } + + public String Serialize() + { + String s = ""; + try + { + + s = Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + catch + { + + + } + return s; + } + + public static CallbackData Deserialize(String data) + { + CallbackData cd = null; + try + { + cd = Newtonsoft.Json.JsonConvert.DeserializeObject(data); + + return cd; + } + catch + { + + } + + return null; + } + + } +} diff --git a/TelegramBotBase/Form/FormBase.cs b/TelegramBotBase/Form/FormBase.cs new file mode 100644 index 0000000..c7103a9 --- /dev/null +++ b/TelegramBotBase/Form/FormBase.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Base; +using TelegramBotBase.Sessions; + +namespace TelegramBotBase.Form +{ + public class FormBase : IDisposable + { + public DeviceSession Device { get; set; } + + public MessageClient Client { get; set; } + + public bool CustomEventManagement { get; set; } = false; + + /// + /// Gibt an, dass das Formular gewechselt wurde, es werden keine weiteren Events ausgeführt + /// + public bool FormSwitched { get; set; } = false; + + public FormBase() + { + + } + + public FormBase(MessageClient Client) + { + this.Client = Client; + } + + /// + /// Wird nur aufgerufen, beim erstmaligen Laden des Formulares. + /// + public virtual async Task Init(params object[] args) + { + + } + + public virtual async Task Opened() + { + + } + + public virtual async Task Closed() + { + + } + + public virtual async Task PreLoad(MessageResult message) + { + + } + + public virtual async Task Load(MessageResult message) + { + + } + + public virtual async Task Action(MessageResult message) + { + + } + + + public virtual async Task Render(MessageResult message) + { + + } + + ///// + ///// Navigiert zur neuen Form. + ///// + ///// + ///// + //public async Task NavigateTo(FormBase newForm) + //{ + // DeviceSession ds = this.Device; + // if (ds == null) + // return; + + // this.FormSwitched = true; + + // ds.ActiveForm = newForm; + // newForm.Client = this.Client; + // newForm.Device = ds; + + // await this.Closed(); + + // await newForm.Opened(); + //} + + /// + /// Navigiert zur neuen Form. + /// + /// + /// + public async Task NavigateTo(FormBase newForm, params object[] args) + { + DeviceSession ds = this.Device; + if (ds == null) + return; + + this.FormSwitched = true; + + ds.ActiveForm = newForm; + newForm.Client = this.Client; + newForm.Device = ds; + + await newForm.Init(args); + + await this.Closed(); + + await newForm.Opened(); + } + + public void Dispose() + { + this.Client = null; + this.Device = null; + this.FormSwitched = false; + } + } +} diff --git a/TelegramBotBase/Form/PromptDialog.cs b/TelegramBotBase/Form/PromptDialog.cs new file mode 100644 index 0000000..1ea9df4 --- /dev/null +++ b/TelegramBotBase/Form/PromptDialog.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Base; + +namespace TelegramBotBase.Form +{ + public class PromptDialog : FormBase + { + public String Message { get; set; } + + + public List Buttons { get; set; } + + public Dictionary ButtonForms { get; set; } = new Dictionary(); + + private EventHandlerList __Events { get; set; } = new EventHandlerList(); + + private static object __evButtonClicked { get; } = new object(); + + public PromptDialog() + { + + } + + public PromptDialog(String Message) + { + this.Message = Message; + this.Buttons = new List(); + } + + public PromptDialog(String Message, params ButtonBase[] Buttons) + { + this.Message = Message; + this.Buttons = Buttons.ToList(); + } + + public override async Task Action(MessageResult message) + { + var call = message.GetData(); + if (call == null) + return; + + message.Handled = true; + + await message.ConfirmAction(); + + await message.DeleteMessage(); + + + ButtonBase button = this.Buttons.FirstOrDefault(a => a.Value == call.Value); + + if (button == null) + { + return; + } + + OnButtonClicked(new ButtonClickedEventArgs(button)); + + FormBase fb = ButtonForms.ContainsKey(call.Value) ? ButtonForms[call.Value] : null; + + if (fb != null) + { + await this.NavigateTo(fb); + } + } + + + public override async Task Render(MessageResult message) + { + ButtonForm btn = new ButtonForm(); + + + var buttons = this.Buttons.Select(a => new ButtonBase(a.Text, CallbackData.Create("action", a.Value))).ToList(); + btn.AddButtonRow(buttons); + + await this.Device.Send(this.Message, btn); + } + + + public event EventHandler ButtonClicked + { + add + { + this.__Events.AddHandler(__evButtonClicked, value); + } + remove + { + this.__Events.RemoveHandler(__evButtonClicked, value); + } + } + + public void OnButtonClicked(ButtonClickedEventArgs e) + { + (this.__Events[__evButtonClicked] as EventHandler)?.Invoke(this, e); + } + + } +} diff --git a/TelegramBotBase/Properties/AssemblyInfo.cs b/TelegramBotBase/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3ef8564 --- /dev/null +++ b/TelegramBotBase/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("TelegramBotBase")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TelegramBotBase")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("a61eda27-cfdf-4bcb-b2d6-184f94904f2d")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TelegramBotBase/SessionBase.cs b/TelegramBotBase/SessionBase.cs new file mode 100644 index 0000000..482aa32 --- /dev/null +++ b/TelegramBotBase/SessionBase.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Base; +using TelegramBotBase.Form; +using TelegramBotBase.Sessions; +namespace TelegramBotBase +{ + public class SessionBase + { + public MessageClient Client { get; set; } + + public Dictionary SessionList { get; set; } + + + public SessionBase() + { + this.SessionList = new Dictionary(); + } + + public DeviceSession this[long key] + { + get + { + return this.SessionList[key]; + } + set + { + this.SessionList[key] = value; + } + } + + public DeviceSession GetSession(long deviceId) + { + DeviceSession ds = this.SessionList.FirstOrDefault(a => a.Key == deviceId).Value ?? null; + return ds; + } + + public async Task StartSession(long deviceId) + where T : FormBase + { + T start = typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { }) as T; + + start.Client = this.Client; + + DeviceSession ds = new Sessions.DeviceSession(deviceId, start); + + start.Device = ds; + await start.Init(); + + await start.Opened(); + + this[deviceId] = ds; + return ds; + } + + + public void EndSession(long deviceId) + { + var d = this[deviceId]; + if (d != null) + { + this.SessionList.Remove(deviceId); + + } + } + + } +} diff --git a/TelegramBotBase/Sessions/DeviceSession.cs b/TelegramBotBase/Sessions/DeviceSession.cs new file mode 100644 index 0000000..d79cbff --- /dev/null +++ b/TelegramBotBase/Sessions/DeviceSession.cs @@ -0,0 +1,270 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Telegram.Bot.Types; +using Telegram.Bot.Types.Enums; +using Telegram.Bot.Types.ReplyMarkups; +using TelegramBotBase.Base; +using TelegramBotBase.Form; + +namespace TelegramBotBase.Sessions +{ + public class DeviceSession + { + public long DeviceId { get; set; } + + public DateTime LastAction { get; set; } + + public FormBase ActiveForm { get; set; } + + public int LastMessage { get; set; } + + private MessageClient Client + { + get + { + return this.ActiveForm.Client; + } + } + + public EventHandlerList __Events = new EventHandlerList(); + + private static object __evMessageSent = new object(); + + public DeviceSession() + { + this.LastMessage = 0; + } + + public DeviceSession(long DeviceId) + { + this.DeviceId = DeviceId; + } + + public DeviceSession(long DeviceId, FormBase StartForm) + { + this.DeviceId = DeviceId; + this.ActiveForm = StartForm; + this.ActiveForm.Device = this; + } + + /// + /// Bearbeitet die bestehende Text-Nachricht. + /// + /// + /// + /// + /// + public async Task Edit(int messageId, String text, ButtonForm buttons = null) + { + if (this.ActiveForm == null) + return; + + InlineKeyboardMarkup markup = null; + if (buttons != null) + { + markup = buttons; + } + + var message = await this.Client.TelegramClient.EditMessageTextAsync(this.DeviceId, messageId, text, replyMarkup: markup); + + } + + /// + /// Sendet eine einfache Text-Nachricht. + /// + /// + /// + /// + /// + public async Task Send(String text, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false) + { + if (this.ActiveForm == null) + return; + + InlineKeyboardMarkup markup = null; + if (buttons != null) + { + markup = buttons; + } + + var message = await (this.Client.TelegramClient.SendTextMessageAsync(this.DeviceId, text, replyToMessageId: replyTo, replyMarkup: markup, disableNotification: disableNotification)); + + OnMessageSent(new MessageSentEventArgs(message.MessageId, message)); + } + + /// + /// Sendet eine einfache Text-Nachricht. + /// + /// + /// + /// + /// + public async Task Send(String text, InlineKeyboardMarkup markup , int replyTo = 0, bool disableNotification = false) + { + if (this.ActiveForm == null) + return; + + var message = await (this.Client.TelegramClient.SendTextMessageAsync(this.DeviceId, text, replyToMessageId: replyTo, replyMarkup: markup, disableNotification: disableNotification)); + + OnMessageSent(new MessageSentEventArgs(message.MessageId, message)); + } + + /// + /// Sendet ein Bild + /// + /// + /// + /// + /// + public async Task SendPhoto(FileToSend file, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false) + { + if (this.ActiveForm == null) + return; + + InlineKeyboardMarkup markup = null; + if (buttons != null) + { + markup = buttons; + } + + var message = await this.Client.TelegramClient.SendPhotoAsync(this.DeviceId, file, replyToMessageId: replyTo, replyMarkup: markup, disableNotification: disableNotification); + + OnMessageSent(new MessageSentEventArgs(message.MessageId, message)); + } + + /// + /// Sendet ein Bild + /// + /// + /// + /// + /// + /// + public async Task SendPhoto(Image image, String name, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false) + { + using (var fileStream = Tools.Images.ToStream(image, ImageFormat.Png)) + { + var fts = new FileToSend(name, fileStream); + + await SendPhoto(fts, buttons, replyTo, disableNotification); + } + } + + /// + /// Sendet ein Bild + /// + /// + /// + /// + /// + /// + public async Task SendPhoto(Bitmap image, String name, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false) + { + using (var fileStream = Tools.Images.ToStream(image, ImageFormat.Png)) + { + var fts = new FileToSend(name, fileStream); + + await SendPhoto(fts, buttons, replyTo, disableNotification); + } + } + + /// + /// Sendet ein Dokument + /// + /// + /// + /// + /// + /// + /// + /// + public async Task SendDocument(String filename, byte[] document, String caption = "", ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false) + { + MemoryStream ms = new MemoryStream(document); + + FileToSend fts = new FileToSend(filename, ms); + + await SendDocument(fts, caption, buttons, replyTo, disableNotification); + } + + /// + /// Sendet ein Dokument + /// + /// + /// + /// + /// + /// + /// + public async Task SendDocument(FileToSend document, String caption = "", ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false) + { + InlineKeyboardMarkup markup = null; + if (buttons != null) + { + markup = buttons; + } + + var message = await this.Client.TelegramClient.SendDocumentAsync(this.DeviceId, document, caption, replyMarkup: markup, disableNotification: disableNotification, replyToMessageId: replyTo); + + OnMessageSent(new MessageSentEventArgs(message.MessageId, message)); + } + + /// + /// Legt eine Chat Aktion Fest (Wird angezeigt) + /// + /// + /// + public async Task SetAction(ChatAction action) + { + await this.Client.TelegramClient.SendChatActionAsync(this.DeviceId, action); + } + + /// + /// Löscht die aktuelle Nachricht, oder die übergebene + /// + /// + /// + public virtual async Task DeleteMessage(int messageId = -1) + { + try + { + await this.Client.TelegramClient.DeleteMessageAsync(this.DeviceId, messageId); + + return true; + } + catch + { + + } + + return false; + } + + + public event EventHandler MessageSent + { + add + { + this.__Events.AddHandler(__evMessageSent, value); + } + remove + { + this.__Events.RemoveHandler(__evMessageSent, value); + } + } + + + public void OnMessageSent(MessageSentEventArgs e) + { + (this.__Events[__evMessageSent] as EventHandler)?.Invoke(this, e); + } + + } +} diff --git a/TelegramBotBase/TelegramBotBase.csproj b/TelegramBotBase/TelegramBotBase.csproj new file mode 100644 index 0000000..bc0acc8 --- /dev/null +++ b/TelegramBotBase/TelegramBotBase.csproj @@ -0,0 +1,96 @@ + + + + + Debug + AnyCPU + {A61EDA27-CFDF-4BCB-B2D6-184F94904F2D} + Library + Properties + TelegramBotBase + TelegramBotBase + v4.5.2 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + True + + + + + + + + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + + + + + + + + + ..\packages\Telegram.Bot.13.2.1\lib\netstandard1.1\Telegram.Bot.dll + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramBotBase/Tests/TestForm.cs b/TelegramBotBase/Tests/TestForm.cs new file mode 100644 index 0000000..8c12aa4 --- /dev/null +++ b/TelegramBotBase/Tests/TestForm.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Telegram.Bot.Types; +using TelegramBotBase.Base; +using TelegramBotBase.Form; + +namespace TelegramBotBase.Tests +{ + public class TestForm : FormBase + { + + + String LastMessage { get; set; } + + public override async Task Init(params object[] param) + { + + } + + public override async Task Opened() + { + await this.Device.Send("Willkommen in Formular 1"); + } + + public override async Task Closed() + { + await this.Device.Send("Tschüss in Formular 1"); + } + + public override async Task Load(MessageResult message) + { + + + } + + + public override async Task Action(MessageResult message) + { + switch (message.Command) + { + case "reply": + + + + break; + + case "navigate": + + var tf = new TestForm2(); + + await tf.Init(); + + await this.NavigateTo(tf); + + break; + + default: + + this.LastMessage = message.RawMessageData.Message.Text; + + break; + } + + + } + + + public override async Task Render(MessageResult message) + { + if (message.Command == "reply") + { + + await this.Device.Send("Letzte Nachricht: " + this.LastMessage); + + } + + } + + } +} diff --git a/TelegramBotBase/Tests/TestForm2.cs b/TelegramBotBase/Tests/TestForm2.cs new file mode 100644 index 0000000..c412f20 --- /dev/null +++ b/TelegramBotBase/Tests/TestForm2.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Telegram.Bot.Types; +using Telegram.Bot.Types.InlineKeyboardButtons; +using Telegram.Bot.Types.ReplyMarkups; +using TelegramBotBase.Base; +using TelegramBotBase.Form; + +namespace TelegramBotBase.Tests +{ + public class TestForm2 : FormBase + { + + public override async Task Init(params object[] param) + { + + } + + public override async Task Opened() + { + await this.Device.Send("Willkommen in Formular 2"); + } + + public override async Task Closed() + { + await this.Device.Send("Tschüss in Formular 2"); + } + + public override async Task Load(MessageResult message) + { + + } + + public override async Task Action(MessageResult message) + { + var call = message.GetData(); + + await message.ConfirmAction(); + + await message.DeleteMessage(); + + if (call.Value == "testform1") + { + + var tf = new TestForm(); + + await tf.Init(); + + await this.NavigateTo(tf); + } + else if (call.Value == "alert") + { + var fto = new TestForm2(); + await fto.Init(); + + AlertDialog ad = new AlertDialog("Dies ist eine Meldung !", "Ok", fto); + + + await this.NavigateTo(ad); + } + else if (call.Value == "prompt") + { + PromptDialog pd = new PromptDialog("Bitte bestätigen !", new ButtonBase("Ok", "ok"), new ButtonBase("Abbrechen", "cancel")); + + var tf = new TestForm2(); + + await tf.Init(); + + pd.ButtonForms.Add("ok", tf); + pd.ButtonForms.Add("cancel", tf); + + await this.NavigateTo(pd); + } + + + } + + public override async Task Render(MessageResult message) + { + + Bitmap bmp = new Bitmap(800, 600); + using (Graphics g = Graphics.FromImage(bmp)) + { + + g.FillRectangle(Brushes.White, 0, 0, bmp.Width, bmp.Height); + + g.DrawString("Testbild", new Font("Arial", 24, FontStyle.Bold, GraphicsUnit.Pixel), Brushes.Black, new PointF(50, 50)); + + } + + await this.Device.SetAction(Telegram.Bot.Types.Enums.ChatAction.UploadPhoto); + + ButtonForm btn = new ButtonForm(); + + btn.AddButtonRow(new ButtonBase("Zum Testformular 1", CallbackData.Create("navigate", "testform1")), new ButtonBase("Zum Testformular 1", CallbackData.Create("navigate", "testform1"))); + + btn.AddButtonRow(new ButtonBase("Info Dialog", CallbackData.Create("navigate", "alert")), new ButtonBase("Bestätigungs Dialog", CallbackData.Create("navigate", "prompt"))); + + + await this.Device.SendPhoto(bmp, "Test", btn); + + } + + + } +} diff --git a/TelegramBotBase/Tools/Images.cs b/TelegramBotBase/Tools/Images.cs new file mode 100644 index 0000000..e941884 --- /dev/null +++ b/TelegramBotBase/Tools/Images.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TelegramBotBase.Tools +{ + public static class Images + { + public static Stream ToStream(this Image image, ImageFormat format) + { + var stream = new System.IO.MemoryStream(); + image.Save(stream, format); + stream.Position = 0; + return stream; + } + } +} diff --git a/TelegramBotBase/packages.config b/TelegramBotBase/packages.config new file mode 100644 index 0000000..a0682e2 --- /dev/null +++ b/TelegramBotBase/packages.config @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file