diff --git a/README.md b/README.md index 67379a4..0d4e6e7 100644 --- a/README.md +++ b/README.md @@ -19,15 +19,17 @@ Download a release: [Releases](https://github.com/MajMcCloud/TelegramBotFramewor Donations -Bitcoin: 1NqyGWmZg8HLp9qQELbf6bChEoba3mxaFc +Bitcoin: 1GoUJYMwAvBipQTfw2FKydAz12J8RDyeJs / bc1qqwlp0p5ley29lsu6jhe0qv7s7963kfc7d0m53d -ETH: 0x795B70CFC27C69603ce115F2b450cbAC5a5460D0 +ETH: 0xAf3835104c2C3E5b3e721FA2c7365955e87DB931 -Litecoin: LM5iCN6Nz22wAi8LSFnKgdGGWEtxWfJZXv +Litecoin: LRhF1eB7kneFontcDRDU8YjJhEm2GoYHch -DASH: Xb2qyVefvbKTXusHoxZ4Soja2S6R4vLsSr +DASH: XudiUwWtSmAJj1QDdVW7jocQumJFLsyoGZ -Paypal: https://paypal.me/majmccloud +TRON: TYVZSykaVT1nKZnz9hjDgBRNB9VavU1bpW + +BITTORRENT: TYVZSykaVT1nKZnz9hjDgBRNB9VavU1bpW Thanks ! @@ -37,6 +39,7 @@ Thanks ! ## Index - [Introduction](#introduction) - [How to Start](#how-to-start) +- [Quick Start](#quick-start) - [Message Handling](#message-handling) * [Example #0 - System Calls](#add-some-system-calls-example-0---system-calls) @@ -143,11 +146,21 @@ It needs to be a subclass of "FormBase" you will find in Namespace TelegramBotBa ``` -//Prepare the System -BotBase bb = new BotBase("{YOUR API KEY}"); +//Prepare the System (New in V5) +var bb = BotBaseBuilder + .Create() + .WithAPIKey("{YOUR API KEY}") + .DefaultMessageLoop() + .WithStartForm() + .NoProxy() + .CustomCommands(a => + { + a.Start("Starts the bot") -//Add Systemcommands if you like, you could catch them later -bb.BotCommands.Add(new BotCommand() { Command = "start", Description = "Starts the bot" }); + }) + .NoSerialization() + .UseEnglish() + .Build(); //Update bot commands to botfather bb.UploadBotCommands().Wait(); @@ -169,11 +182,9 @@ public class StartForm : FormBase } - //Gets invoked during Navigation to this form - public override async Task Init(params object[] param) - { - - } + //Gets invoked during Navigation to this form + + //Init() got replaced with event handler //Opened() got replaced with event handler @@ -231,6 +242,28 @@ var tf = new TestForm(); await this.NavigateTo(tf); ``` +## Quick Start: + + +When migrating from a previous version or starting completely new, all these options can be a bit overwhelming. +For this I added a QuickStart option, directly after the Create call. It just need basic parameters like in earlier versions. + + +``` + +//Prepare the System (New in V5) +var bb = BotBaseBuilder + .Create() + .QuickStart("{YOUR API KEY}") + .Build(); + +//Start your Bot +bb.Start(); + +``` + + + ## Message Handling All examples are within the test project, so just try it out on your own. @@ -254,12 +287,24 @@ Below we have 4 options. ``` -BotBase bb = new BotBase("{YOUR API KEY}"); +var bb = BotBaseBuilder + .Create() + .WithAPIKey("{YOUR API KEY}") + .DefaultMessageLoop() + .WithStartForm() + .NoProxy() + .CustomCommands(a => + { + a.Start("Starts the bot"); + a.Add("form1","Opens test form 1" ); + a.Add("form2", "Opens test form 2" ); + a.Add("params", "Returns all send parameters as a message." ); -bb.BotCommands.Add(new BotCommand() { Command = "start", Description = "Starts the bot" }); -bb.BotCommands.Add(new BotCommand() { Command = "form1", Description = "Opens test form 1" }); -bb.BotCommands.Add(new BotCommand() { Command = "form2", Description = "Opens test form 2" }); -bb.BotCommands.Add(new BotCommand() { Command = "params", Description = "Returns all send parameters as a message." }); + + }) + .NoSerialization() + .UseEnglish() + .Build(); bb.BotCommand += async (s, en) => { @@ -965,13 +1010,19 @@ In general you didn't need to do more then, to keep the actual form: ``` //Prepare the System -BotBase bb = new BotBase("{YOUR API KEY}"); - -//Add Systemcommands if you like, you could catch them later -bb.SystemCalls.Add("/start"); - -//Set the statemachine and enable it -bb.StateMachine = new TelegramBotBase.States.SimpleJSONStateMachine(AppContext.BaseDirectory + "config\\states.json"); +var bb = BotBaseBuilder + .Create() + .WithAPIKey("{YOUR API KEY}") + .DefaultMessageLoop() + .WithStartForm() + .NoProxy() + .CustomCommands(a => + { + a.Start("Starts the bot"); + }) + .UseSimpleJSON(AppContext.BaseDirectory + "config\\states.json") + .UseEnglish() + .Build(); //Start your Bot bb.Start(); @@ -984,13 +1035,19 @@ In general you didn't need to do more then, to keep the actual form: ``` //Prepare the System -BotBase bb = new BotBase("{YOUR API KEY}"); - -//Add Systemcommands if you like, you could catch them later -bb.SystemCalls.Add("/start"); - -//Set the statemachine and enable it -bb.StateMachine = new TelegramBotBase.States.JSONStateMachine(AppContext.BaseDirectory + "config\\states.json"); +var bb = BotBaseBuilder + .Create() + .WithAPIKey("{YOUR API KEY}") + .DefaultMessageLoop() + .WithStartForm() + .NoProxy() + .CustomCommands(a => + { + a.Start("Starts the bot"); + }) + .UseJSON(AppContext.BaseDirectory + "config\\states.json") + .UseEnglish() + .Build(); //Start your Bot bb.Start(); @@ -1004,13 +1061,19 @@ In general you didn't need to do more then, to keep the actual form: ``` //Prepare the System -BotBase bb = new BotBase("{YOUR API KEY}"); - -//Add Systemcommands if you like, you could catch them later -bb.SystemCalls.Add("/start"); - -//Set the statemachine and enable it -bb.StateMachine = new TelegramBotBase.States.XMLStateMachine(AppContext.BaseDirectory + "config\\states.xml"); +var bb = BotBaseBuilder + .Create() + .WithAPIKey("{YOUR API KEY}") + .DefaultMessageLoop() + .WithStartForm() + .NoProxy() + .CustomCommands(a => + { + a.Start("Starts the bot"); + }) + .UseXML(AppContext.BaseDirectory + "config\\states.xml") + .UseEnglish() + .Build(); //Start your Bot bb.Start(); diff --git a/TelegramBotBase.Extensions.Images/ImageExtensions.cs b/TelegramBotBase.Extensions.Images/ImageExtensions.cs new file mode 100644 index 0000000..55ddbb2 --- /dev/null +++ b/TelegramBotBase.Extensions.Images/ImageExtensions.cs @@ -0,0 +1,61 @@ +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Threading.Tasks; +using Telegram.Bot.Types.InputFiles; +using Telegram.Bot.Types; +using TelegramBotBase.Sessions; +using TelegramBotBase.Form; + +namespace TelegramBotBase.Extensions.Images +{ + public static class ImageExtensions + { + public static Stream ToStream(this Image image, ImageFormat format) + { + var stream = new System.IO.MemoryStream(); + image.Save(stream, format); + stream.Position = 0; + return stream; + } + + /// + /// Sends an image + /// + /// + /// + /// + /// + /// + /// + public static async Task SendPhoto(this DeviceSession session, Image image, String name, String caption, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false) + { + using (var fileStream = ToStream(image, ImageFormat.Png)) + { + InputOnlineFile fts = new InputOnlineFile(fileStream, name); + + return await session.SendPhoto(fts, caption: caption, buttons, replyTo, disableNotification); + } + } + + /// + /// Sends an image + /// + /// + /// + /// + /// + /// + /// + public static async Task SendPhoto(this DeviceSession session, Bitmap image, String name, String caption, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false) + { + using (var fileStream = ToStream(image, ImageFormat.Png)) + { + InputOnlineFile fts = new InputOnlineFile(fileStream, name); + + return await session.SendPhoto(fts, caption: caption, buttons, replyTo, disableNotification); + } + } + } +} diff --git a/TelegramBotBase.Extensions.Images/README.md b/TelegramBotBase.Extensions.Images/README.md new file mode 100644 index 0000000..cdef1e3 --- /dev/null +++ b/TelegramBotBase.Extensions.Images/README.md @@ -0,0 +1,8 @@ +# TelegramBotBase.Extensions.Images + +[![NuGet version (TelegramBotBase)](https://img.shields.io/nuget/v/TelegramBotBase.Extensions.Images.svg?style=flat-square)](https://www.nuget.org/packages/TelegramBotBase.Extensions.Images/) +[![telegram chat](https://img.shields.io/badge/Support_Chat-Telegram-blue.svg?style=flat-square)](https://www.t.me/tgbotbase) + + +[![license](https://img.shields.io/github/license/MajMcCloud/telegrambotframework.svg?style=flat-square&maxAge=2592000&label=License)](https://raw.githubusercontent.com/MajMcCloud/TelegramBotFramework/master/LICENCE.md) +[![downloads](https://img.shields.io/nuget/dt/TelegramBotBase.Extensions.Images.svg?style=flat-square&label=Package%20Downloads)](https://www.nuget.org/packages/TelegramBotBase.Extensions.Images) diff --git a/TelegramBotBase.Extensions.Images/TelegramBotBase.Extensions.Images.csproj b/TelegramBotBase.Extensions.Images/TelegramBotBase.Extensions.Images.csproj new file mode 100644 index 0000000..4b974c8 --- /dev/null +++ b/TelegramBotBase.Extensions.Images/TelegramBotBase.Extensions.Images.csproj @@ -0,0 +1,25 @@ + + + + netstandard2.0;net5;netcoreapp3.1;net6 + https://github.com/MajMcCloud/TelegramBotFramework + https://github.com/MajMcCloud/TelegramBotFramework + MIT + true + snupkg + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + \ No newline at end of file diff --git a/TelegramBotBaseTest/App.config b/TelegramBotBase.Test/App.config similarity index 100% rename from TelegramBotBaseTest/App.config rename to TelegramBotBase.Test/App.config diff --git a/TelegramBotBaseTest/Program.cs b/TelegramBotBase.Test/Program.cs similarity index 67% rename from TelegramBotBaseTest/Program.cs rename to TelegramBotBase.Test/Program.cs index 6371196..55ac0aa 100644 --- a/TelegramBotBaseTest/Program.cs +++ b/TelegramBotBase.Test/Program.cs @@ -8,6 +8,8 @@ using TelegramBotBase; using TelegramBotBase.Form; using TelegramBotBaseTest.Tests; using TelegramBotBase.Commands; +using TelegramBotBase.Builder; + namespace TelegramBotBaseTest { class Program @@ -15,14 +17,27 @@ namespace TelegramBotBaseTest static void Main(string[] args) { - BotBase bb = new BotBase(APIKey); + String APIKey = ""; + + var bb = BotBaseBuilder + .Create() + .WithAPIKey(APIKey) + .DefaultMessageLoop() + .WithStartForm() + .NoProxy() + .CustomCommands(a => + { + a.Start("Starts the bot"); + a.Help("Should show you some help"); + a.Settings("Should show you some settings"); + a.Add("form1", "Opens test form 1"); + a.Add("form2", "Opens test form 2"); + a.Add("params", "Returns all send parameters as a message."); + }) + .NoSerialization() + .UseEnglish() + .Build(); - bb.BotCommands.AddStartCommand("Starts the bot"); - bb.BotCommands.AddHelpCommand("Should show you some help"); - bb.BotCommands.AddSettingsCommand("Should show you some settings"); - bb.BotCommands.Add(new BotCommand() { Command = "form1", Description = "Opens test form 1" }); - bb.BotCommands.Add(new BotCommand() { Command = "form2", Description = "Opens test form 2" }); - bb.BotCommands.Add(new BotCommand() { Command = "params", Description = "Returns all send parameters as a message." }); bb.BotCommand += async (s, en) => { @@ -54,7 +69,7 @@ namespace TelegramBotBaseTest case "/params": String m = en.Parameters.DefaultIfEmpty("").Aggregate((a, b) => a + " and " + b); - + await en.Device.Send("Your parameters are: " + m, replyTo: en.Device.LastMessageId); en.Handled = true; @@ -69,7 +84,7 @@ namespace TelegramBotBaseTest bb.SetSetting(TelegramBotBase.Enums.eSettings.LogAllMessages, true); - bb.Message += (s,en) => + bb.Message += (s, en) => { Console.WriteLine(en.DeviceId + " " + en.Message.MessageText + " " + (en.Message.RawData ?? "")); }; diff --git a/TelegramBotBaseTest/Properties/AssemblyInfo.cs b/TelegramBotBase.Test/Properties/AssemblyInfo.cs similarity index 100% rename from TelegramBotBaseTest/Properties/AssemblyInfo.cs rename to TelegramBotBase.Test/Properties/AssemblyInfo.cs diff --git a/TelegramBotBaseTest/TelegramBotBaseTest.csproj b/TelegramBotBase.Test/TelegramBotBaseTest.csproj similarity index 86% rename from TelegramBotBaseTest/TelegramBotBaseTest.csproj rename to TelegramBotBase.Test/TelegramBotBaseTest.csproj index f52e456..a1abbf6 100644 --- a/TelegramBotBaseTest/TelegramBotBaseTest.csproj +++ b/TelegramBotBase.Test/TelegramBotBaseTest.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1;net5 + netcoreapp3.1;net5;net6 false Debug;Release @@ -27,6 +27,7 @@ + diff --git a/TelegramBotBaseTest/Tests/ButtonTestForm.cs b/TelegramBotBase.Test/Tests/ButtonTestForm.cs similarity index 100% rename from TelegramBotBaseTest/Tests/ButtonTestForm.cs rename to TelegramBotBase.Test/Tests/ButtonTestForm.cs diff --git a/TelegramBotBaseTest/Tests/Controls/ButtonGridForm.cs b/TelegramBotBase.Test/Tests/Controls/ButtonGridForm.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Controls/ButtonGridForm.cs rename to TelegramBotBase.Test/Tests/Controls/ButtonGridForm.cs diff --git a/TelegramBotBaseTest/Tests/Controls/ButtonGridPagingForm.cs b/TelegramBotBase.Test/Tests/Controls/ButtonGridPagingForm.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Controls/ButtonGridPagingForm.cs rename to TelegramBotBase.Test/Tests/Controls/ButtonGridPagingForm.cs diff --git a/TelegramBotBaseTest/Tests/Controls/ButtonGridTagForm.cs b/TelegramBotBase.Test/Tests/Controls/ButtonGridTagForm.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Controls/ButtonGridTagForm.cs rename to TelegramBotBase.Test/Tests/Controls/ButtonGridTagForm.cs diff --git a/TelegramBotBaseTest/Tests/Controls/CalendarPickerForm.cs b/TelegramBotBase.Test/Tests/Controls/CalendarPickerForm.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Controls/CalendarPickerForm.cs rename to TelegramBotBase.Test/Tests/Controls/CalendarPickerForm.cs diff --git a/TelegramBotBaseTest/Tests/Controls/CheckedButtonListForm.cs b/TelegramBotBase.Test/Tests/Controls/CheckedButtonListForm.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Controls/CheckedButtonListForm.cs rename to TelegramBotBase.Test/Tests/Controls/CheckedButtonListForm.cs diff --git a/TelegramBotBaseTest/Tests/Controls/MonthPickerForm.cs b/TelegramBotBase.Test/Tests/Controls/MonthPickerForm.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Controls/MonthPickerForm.cs rename to TelegramBotBase.Test/Tests/Controls/MonthPickerForm.cs diff --git a/TelegramBotBaseTest/Tests/Controls/MultiToggleButtons.cs b/TelegramBotBase.Test/Tests/Controls/MultiToggleButtons.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Controls/MultiToggleButtons.cs rename to TelegramBotBase.Test/Tests/Controls/MultiToggleButtons.cs diff --git a/TelegramBotBaseTest/Tests/Controls/MultiViewForm.cs b/TelegramBotBase.Test/Tests/Controls/MultiViewForm.cs similarity index 82% rename from TelegramBotBaseTest/Tests/Controls/MultiViewForm.cs rename to TelegramBotBase.Test/Tests/Controls/MultiViewForm.cs index 543b3c5..fccdfcb 100644 --- a/TelegramBotBaseTest/Tests/Controls/MultiViewForm.cs +++ b/TelegramBotBase.Test/Tests/Controls/MultiViewForm.cs @@ -48,26 +48,6 @@ namespace TelegramBotBaseTest.Tests.Controls } } - public override async Task Load(MessageResult message) - { - - - - } - - public override async Task Action(MessageResult message) - { - - - } - - - public override async Task Render(MessageResult message) - { - - } - - } } diff --git a/TelegramBotBaseTest/Tests/Controls/Subclass/MultiViewTest.cs b/TelegramBotBase.Test/Tests/Controls/Subclass/MultiViewTest.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Controls/Subclass/MultiViewTest.cs rename to TelegramBotBase.Test/Tests/Controls/Subclass/MultiViewTest.cs diff --git a/TelegramBotBaseTest/Tests/Controls/ToggleButtons.cs b/TelegramBotBase.Test/Tests/Controls/ToggleButtons.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Controls/ToggleButtons.cs rename to TelegramBotBase.Test/Tests/Controls/ToggleButtons.cs diff --git a/TelegramBotBaseTest/Tests/Controls/TreeViewForms.cs b/TelegramBotBase.Test/Tests/Controls/TreeViewForms.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Controls/TreeViewForms.cs rename to TelegramBotBase.Test/Tests/Controls/TreeViewForms.cs diff --git a/TelegramBotBaseTest/Tests/DataForm.cs b/TelegramBotBase.Test/Tests/DataForm.cs similarity index 99% rename from TelegramBotBaseTest/Tests/DataForm.cs rename to TelegramBotBase.Test/Tests/DataForm.cs index a53f74b..4a6edec 100644 --- a/TelegramBotBaseTest/Tests/DataForm.cs +++ b/TelegramBotBase.Test/Tests/DataForm.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.InputFiles; using Telegram.Bot.Types.ReplyMarkups; diff --git a/TelegramBotBaseTest/Tests/Datasources/CustomDataSource.cs b/TelegramBotBase.Test/Tests/Datasources/CustomDataSource.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Datasources/CustomDataSource.cs rename to TelegramBotBase.Test/Tests/Datasources/CustomDataSource.cs diff --git a/TelegramBotBaseTest/Tests/Datasources/List.cs b/TelegramBotBase.Test/Tests/Datasources/List.cs similarity index 87% rename from TelegramBotBaseTest/Tests/Datasources/List.cs rename to TelegramBotBase.Test/Tests/Datasources/List.cs index b2ec372..c352384 100644 --- a/TelegramBotBaseTest/Tests/Datasources/List.cs +++ b/TelegramBotBase.Test/Tests/Datasources/List.cs @@ -49,17 +49,6 @@ namespace TelegramBotBaseTest.Tests.Datasources } } - public override async Task Load(MessageResult message) - { - - } - - - public override async Task Render(MessageResult message) - { - - } - } } diff --git a/TelegramBotBaseTest/Tests/Groups/GroupChange.cs b/TelegramBotBase.Test/Tests/Groups/GroupChange.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Groups/GroupChange.cs rename to TelegramBotBase.Test/Tests/Groups/GroupChange.cs diff --git a/TelegramBotBaseTest/Tests/Groups/LinkReplaceTest.cs b/TelegramBotBase.Test/Tests/Groups/LinkReplaceTest.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Groups/LinkReplaceTest.cs rename to TelegramBotBase.Test/Tests/Groups/LinkReplaceTest.cs diff --git a/TelegramBotBaseTest/Tests/Groups/WelcomeUser.cs b/TelegramBotBase.Test/Tests/Groups/WelcomeUser.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Groups/WelcomeUser.cs rename to TelegramBotBase.Test/Tests/Groups/WelcomeUser.cs diff --git a/TelegramBotBaseTest/Tests/Menu.cs b/TelegramBotBase.Test/Tests/Menu.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Menu.cs rename to TelegramBotBase.Test/Tests/Menu.cs diff --git a/TelegramBotBaseTest/Tests/Navigation/CustomController.cs b/TelegramBotBase.Test/Tests/Navigation/CustomController.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Navigation/CustomController.cs rename to TelegramBotBase.Test/Tests/Navigation/CustomController.cs diff --git a/TelegramBotBaseTest/Tests/Navigation/Form1.cs b/TelegramBotBase.Test/Tests/Navigation/Form1.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Navigation/Form1.cs rename to TelegramBotBase.Test/Tests/Navigation/Form1.cs diff --git a/TelegramBotBaseTest/Tests/Navigation/Start.cs b/TelegramBotBase.Test/Tests/Navigation/Start.cs similarity index 84% rename from TelegramBotBaseTest/Tests/Navigation/Start.cs rename to TelegramBotBase.Test/Tests/Navigation/Start.cs index 07402fa..1f70b5c 100644 --- a/TelegramBotBaseTest/Tests/Navigation/Start.cs +++ b/TelegramBotBase.Test/Tests/Navigation/Start.cs @@ -16,16 +16,9 @@ namespace TelegramBotBaseTest.Tests.Navigation public Start() { - this.Closed += Start_Closed; + } - private async Task Start_Closed(object sender, EventArgs e) - { - if (msg == null) - return; - - await Device.DeleteMessage(msg); - } public override async Task Load(MessageResult message) { @@ -49,12 +42,18 @@ namespace TelegramBotBaseTest.Tests.Navigation //Create navigation controller and navigate to it, keep the current form as root form so we can get back to here later var nc = new CustomController(this); + nc.ForceCleanupOnLastPop = true; var f1 = new Form1(); + await nc.PushAsync(f1); + await NavigateTo(nc); - await nc.PushAsync(f1); + if (msg == null) + return; + + await Device.DeleteMessage(msg); break; @@ -66,6 +65,10 @@ namespace TelegramBotBaseTest.Tests.Navigation await NavigateTo(mn); + if (msg == null) + return; + + await Device.DeleteMessage(msg); break; } diff --git a/TelegramBotBaseTest/Tests/Notifications/Start.cs b/TelegramBotBase.Test/Tests/Notifications/Start.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Notifications/Start.cs rename to TelegramBotBase.Test/Tests/Notifications/Start.cs diff --git a/TelegramBotBaseTest/Tests/ProgressTest.cs b/TelegramBotBase.Test/Tests/ProgressTest.cs similarity index 100% rename from TelegramBotBaseTest/Tests/ProgressTest.cs rename to TelegramBotBase.Test/Tests/ProgressTest.cs diff --git a/TelegramBotBaseTest/Tests/Register/PerForm.cs b/TelegramBotBase.Test/Tests/Register/PerForm.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Register/PerForm.cs rename to TelegramBotBase.Test/Tests/Register/PerForm.cs diff --git a/TelegramBotBaseTest/Tests/Register/PerStep.cs b/TelegramBotBase.Test/Tests/Register/PerStep.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Register/PerStep.cs rename to TelegramBotBase.Test/Tests/Register/PerStep.cs diff --git a/TelegramBotBaseTest/Tests/Register/Start.cs b/TelegramBotBase.Test/Tests/Register/Start.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Register/Start.cs rename to TelegramBotBase.Test/Tests/Register/Start.cs diff --git a/TelegramBotBaseTest/Tests/Register/Steps/Data.cs b/TelegramBotBase.Test/Tests/Register/Steps/Data.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Register/Steps/Data.cs rename to TelegramBotBase.Test/Tests/Register/Steps/Data.cs diff --git a/TelegramBotBaseTest/Tests/Register/Steps/Step1.cs b/TelegramBotBase.Test/Tests/Register/Steps/Step1.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Register/Steps/Step1.cs rename to TelegramBotBase.Test/Tests/Register/Steps/Step1.cs diff --git a/TelegramBotBaseTest/Tests/Register/Steps/Step2.cs b/TelegramBotBase.Test/Tests/Register/Steps/Step2.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Register/Steps/Step2.cs rename to TelegramBotBase.Test/Tests/Register/Steps/Step2.cs diff --git a/TelegramBotBaseTest/Tests/Register/Steps/Step3.cs b/TelegramBotBase.Test/Tests/Register/Steps/Step3.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Register/Steps/Step3.cs rename to TelegramBotBase.Test/Tests/Register/Steps/Step3.cs diff --git a/TelegramBotBaseTest/Tests/SimpleForm.cs b/TelegramBotBase.Test/Tests/SimpleForm.cs similarity index 100% rename from TelegramBotBaseTest/Tests/SimpleForm.cs rename to TelegramBotBase.Test/Tests/SimpleForm.cs diff --git a/TelegramBotBaseTest/Tests/Start.cs b/TelegramBotBase.Test/Tests/Start.cs similarity index 100% rename from TelegramBotBaseTest/Tests/Start.cs rename to TelegramBotBase.Test/Tests/Start.cs diff --git a/TelegramBotBaseTest/Tests/TestForm.cs b/TelegramBotBase.Test/Tests/TestForm.cs similarity index 91% rename from TelegramBotBaseTest/Tests/TestForm.cs rename to TelegramBotBase.Test/Tests/TestForm.cs index 57d5981..8994465 100644 --- a/TelegramBotBaseTest/Tests/TestForm.cs +++ b/TelegramBotBase.Test/Tests/TestForm.cs @@ -51,10 +51,10 @@ namespace TelegramBotBaseTest.Tests default: - if (message.RawMessageData == null) + if (message.UpdateData == null) return; - this.LastMessage = message.RawMessageData.Message.Text; + this.LastMessage = message.Message.Text; break; } diff --git a/TelegramBotBaseTest/Tests/TestForm2.cs b/TelegramBotBase.Test/Tests/TestForm2.cs similarity index 98% rename from TelegramBotBaseTest/Tests/TestForm2.cs rename to TelegramBotBase.Test/Tests/TestForm2.cs index 89855d8..089430e 100644 --- a/TelegramBotBaseTest/Tests/TestForm2.cs +++ b/TelegramBotBase.Test/Tests/TestForm2.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Telegram.Bot.Types; using Telegram.Bot.Types.ReplyMarkups; using TelegramBotBase.Base; +using TelegramBotBase.Extensions.Images; using TelegramBotBase.Form; namespace TelegramBotBaseTest.Tests diff --git a/TelegramBotBaseTest/packages.config b/TelegramBotBase.Test/packages.config similarity index 100% rename from TelegramBotBaseTest/packages.config rename to TelegramBotBase.Test/packages.config diff --git a/TelegramBotBase/Base/DataResult.cs b/TelegramBotBase/Base/DataResult.cs index c3f2a21..8fc9e34 100644 --- a/TelegramBotBase/Base/DataResult.cs +++ b/TelegramBotBase/Base/DataResult.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.InputFiles; @@ -14,7 +15,11 @@ namespace TelegramBotBase.Base /// public class DataResult : ResultBase { - public Telegram.Bot.Args.MessageEventArgs RawMessageData { get; set; } + + //public Telegram.Bot.Args.MessageEventArgs RawMessageData { get; set; } + + public UpdateResult UpdateData { get; set; } + public Contact Contact { @@ -64,11 +69,20 @@ namespace TelegramBotBase.Base } } + public Telegram.Bot.Types.Enums.MessageType Type { get { - return this.RawMessageData?.Message?.Type ?? Telegram.Bot.Types.Enums.MessageType.Unknown; + return this.Message?.Type ?? Telegram.Bot.Types.Enums.MessageType.Unknown; + } + } + + public override Message Message + { + get + { + return this.UpdateData?.Message; } } @@ -86,24 +100,15 @@ namespace TelegramBotBase.Base } } - - public DataResult(Telegram.Bot.Args.MessageEventArgs rawdata) + public DataResult(UpdateResult update) { - this.RawMessageData = rawdata; - this.Message = rawdata.Message; + this.UpdateData = update; } - public DataResult(MessageResult message) - { - this.RawMessageData = message.RawMessageData; - this.Message = message.Message; - - this.Client = message.Client; - } public async Task DownloadDocument() { - var encryptedContent = new System.IO.MemoryStream(this.Document.FileSize); + var encryptedContent = new System.IO.MemoryStream(this.Document.FileSize.Value); var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(this.Document.FileId, encryptedContent); return new InputOnlineFile(encryptedContent, this.Document.FileName); @@ -156,13 +161,13 @@ namespace TelegramBotBase.Base ms.Position = 0; var sr = new StreamReader(ms, encoding); - + return sr.ReadToEnd(); } public async Task DownloadVideo() { - var encryptedContent = new System.IO.MemoryStream(this.Video.FileSize); + var encryptedContent = new System.IO.MemoryStream(this.Video.FileSize.Value); var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(this.Video.FileId, encryptedContent); return new InputOnlineFile(encryptedContent, ""); @@ -179,7 +184,7 @@ namespace TelegramBotBase.Base public async Task DownloadAudio() { - var encryptedContent = new System.IO.MemoryStream(this.Audio.FileSize); + var encryptedContent = new System.IO.MemoryStream(this.Audio.FileSize.Value); var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(this.Audio.FileId, encryptedContent); return new InputOnlineFile(encryptedContent, ""); @@ -197,7 +202,7 @@ namespace TelegramBotBase.Base public async Task DownloadPhoto(int index) { var photo = this.Photos[index]; - var encryptedContent = new System.IO.MemoryStream(photo.FileSize); + var encryptedContent = new System.IO.MemoryStream(photo.FileSize.Value); var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(photo.FileId, encryptedContent); return new InputOnlineFile(encryptedContent, ""); diff --git a/TelegramBotBase/Base/MessageClient.cs b/TelegramBotBase/Base/MessageClient.cs index 22a71fe..e252f35 100644 --- a/TelegramBotBase/Base/MessageClient.cs +++ b/TelegramBotBase/Base/MessageClient.cs @@ -5,8 +5,13 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Text; +using System.Threading; using System.Threading.Tasks; +using Telegram.Bot.Exceptions; +using Telegram.Bot; using Telegram.Bot.Types; +using Telegram.Bot.Types.Enums; +using Telegram.Bot.Extensions.Polling; namespace TelegramBotBase.Base { @@ -19,16 +24,20 @@ namespace TelegramBotBase.Base public String APIKey { get; set; } - public Telegram.Bot.TelegramBotClient TelegramClient { get; set; } + public ITelegramBotClient TelegramClient { get; set; } private EventHandlerList __Events { get; set; } = new EventHandlerList(); + private static object __evOnMessageLoop = new object(); + private static object __evOnMessage = new object(); private static object __evOnMessageEdit = new object(); private static object __evCallbackQuery = new object(); + CancellationTokenSource __cancellationTokenSource; + public MessageClient(String APIKey) { @@ -47,13 +56,22 @@ namespace TelegramBotBase.Base Prepare(); } - public MessageClient(String APIKey, Uri proxyUrl) + + + public MessageClient(String APIKey, Uri proxyUrl, NetworkCredential credential = null) { this.APIKey = APIKey; - var proxy = new WebProxy(proxyUrl); + var proxy = new WebProxy(proxyUrl) + { + Credentials = credential + }; - this.TelegramClient = new Telegram.Bot.TelegramBotClient(APIKey, proxy); + var httpClient = new HttpClient( + new HttpClientHandler { Proxy = proxy, UseProxy = true } + ); + + this.TelegramClient = new Telegram.Bot.TelegramBotClient(APIKey, httpClient); Prepare(); } @@ -70,11 +88,17 @@ namespace TelegramBotBase.Base var proxy = new WebProxy(proxyHost, proxyPort); - this.TelegramClient = new Telegram.Bot.TelegramBotClient(APIKey, proxy); + var httpClient = new HttpClient( + new HttpClientHandler { Proxy = proxy, UseProxy = true } + ); + + this.TelegramClient = new Telegram.Bot.TelegramBotClient(APIKey, httpClient); Prepare(); } + + public MessageClient(String APIKey, Telegram.Bot.TelegramBotClient Client) { this.APIKey = APIKey; @@ -88,62 +112,49 @@ namespace TelegramBotBase.Base { this.TelegramClient.Timeout = new TimeSpan(0, 0, 30); - this.TelegramClient.OnMessage += TelegramClient_OnMessage; - this.TelegramClient.OnMessageEdited += TelegramClient_OnMessageEdited; - this.TelegramClient.OnCallbackQuery += TelegramClient_OnCallbackQuery; } - private async void TelegramClient_OnMessage(object sender, Telegram.Bot.Args.MessageEventArgs e) + + + public void StartReceiving() { - //Skip empty messages by default - if (e.Message == null) - return; + __cancellationTokenSource = new CancellationTokenSource(); - try - { - var mr = new MessageResult(e); - mr.Client = this; - OnMessage(mr); - } - catch + var receiverOptions = new ReceiverOptions { + AllowedUpdates = { } // receive all update types + }; - } + this.TelegramClient.StartReceiving(HandleUpdateAsync, HandleErrorAsync, receiverOptions, __cancellationTokenSource.Token); } - - private async void TelegramClient_OnMessageEdited(object sender, Telegram.Bot.Args.MessageEventArgs e) + public void StopReceiving() { - //Skip empty messages by default - if (e.Message == null) - return; - - try - { - var mr = new MessageResult(e); - mr.Client = this; - OnMessageEdit(mr); - } - catch - { - - } + __cancellationTokenSource.Cancel(); } - private async void TelegramClient_OnCallbackQuery(object sender, Telegram.Bot.Args.CallbackQueryEventArgs e) + + public Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken) { - try - { - var ar = new MessageResult(e); - ar.Client = this; - OnAction(ar); - } - catch - { + OnMessageLoop(new UpdateResult(update, null)); - } + return Task.CompletedTask; } + public Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, CancellationToken cancellationToken) + { + if (exception is ApiRequestException exAPI) + { + Console.WriteLine($"Telegram API Error:\n[{exAPI.ErrorCode}]\n{exAPI.Message}"); + } + else + { + Console.WriteLine(exception.ToString()); + } + return Task.CompletedTask; + } + + /// /// This will return the current list of bot commands. /// @@ -168,55 +179,23 @@ namespace TelegramBotBase.Base #region "Events" - public event EventHandler Message + + + public event Async.AsyncEventHandler MessageLoop { add { - this.__Events.AddHandler(__evOnMessage, value); + this.__Events.AddHandler(__evOnMessageLoop, value); } remove { - this.__Events.RemoveHandler(__evOnMessage, value); + this.__Events.RemoveHandler(__evOnMessageLoop, value); } } - public void OnMessage(MessageResult result) + public void OnMessageLoop(UpdateResult update) { - (this.__Events[__evOnMessage] as EventHandler)?.Invoke(this, result); - } - - public event EventHandler MessageEdit - { - add - { - this.__Events.AddHandler(__evOnMessageEdit, value); - } - remove - { - this.__Events.RemoveHandler(__evOnMessageEdit, value); - } - } - - public void OnMessageEdit(MessageResult result) - { - (this.__Events[__evOnMessageEdit] 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); + (this.__Events[__evOnMessageLoop] as Async.AsyncEventHandler)?.Invoke(this, update); } diff --git a/TelegramBotBase/Base/MessageResult.cs b/TelegramBotBase/Base/MessageResult.cs index 7da2bdd..762ac8f 100644 --- a/TelegramBotBase/Base/MessageResult.cs +++ b/TelegramBotBase/Base/MessageResult.cs @@ -3,15 +3,16 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Telegram.Bot; +using Telegram.Bot.Types; using TelegramBotBase.Sessions; namespace TelegramBotBase.Base { public class MessageResult : ResultBase { - public Telegram.Bot.Args.MessageEventArgs RawMessageData { get; set; } - public Telegram.Bot.Args.CallbackQueryEventArgs RawCallbackData { get; set; } + public Telegram.Bot.Types.Update UpdateData { get; set; } /// /// Returns the Device/ChatId @@ -20,8 +21,9 @@ namespace TelegramBotBase.Base { get { - return this.RawMessageData?.Message?.Chat.Id - ?? this.RawCallbackData?.CallbackQuery.Message?.Chat.Id + return this.UpdateData?.Message?.Chat?.Id + ?? this.UpdateData?.EditedMessage?.Chat.Id + ?? this.UpdateData?.CallbackQuery.Message?.Chat.Id ?? Device?.DeviceId ?? 0; } @@ -40,8 +42,9 @@ namespace TelegramBotBase.Base { get { - return this.Message?.MessageId - ?? this.RawCallbackData?.CallbackQuery?.Message?.MessageId + return this.UpdateData?.Message?.MessageId + ?? this.Message?.MessageId + ?? this.UpdateData?.CallbackQuery?.Message?.MessageId ?? 0; } } @@ -50,7 +53,7 @@ namespace TelegramBotBase.Base { get { - return this.RawMessageData?.Message?.Text ?? ""; + return this.UpdateData?.Message?.Text ?? ""; } } @@ -58,7 +61,7 @@ namespace TelegramBotBase.Base { get { - return this.RawMessageData?.Message?.Text ?? ""; + return this.UpdateData?.Message?.Text ?? ""; } } @@ -66,8 +69,19 @@ namespace TelegramBotBase.Base { get { - return this.RawMessageData?.Message?.Type - ?? Telegram.Bot.Types.Enums.MessageType.Unknown; + return Message?.Type ?? Telegram.Bot.Types.Enums.MessageType.Unknown; + } + } + + public Message Message + { + get + { + return this.UpdateData?.Message + ?? this.UpdateData?.EditedMessage + ?? this.UpdateData?.ChannelPost + ?? this.UpdateData?.EditedChannelPost + ?? this.UpdateData?.CallbackQuery?.Message; } } @@ -78,7 +92,7 @@ namespace TelegramBotBase.Base { get { - return (this.RawCallbackData != null); + return (this.UpdateData.CallbackQuery != null); } } @@ -133,7 +147,7 @@ namespace TelegramBotBase.Base { get { - return this.RawCallbackData?.CallbackQuery?.Data; + return this.UpdateData?.CallbackQuery?.Data; } } @@ -162,14 +176,7 @@ namespace TelegramBotBase.Base /// public async Task ConfirmAction(String message = "", bool showAlert = false, String urlToOpen = null) { - try - { - await this.Client.TelegramClient.AnswerCallbackQueryAsync(this.RawCallbackData.CallbackQuery.Id, message, showAlert, urlToOpen); - } - catch - { - - } + await this.Device.ConfirmAction(this.UpdateData.CallbackQuery.Id, message, showAlert, urlToOpen); } public override async Task DeleteMessage() @@ -189,16 +196,10 @@ namespace TelegramBotBase.Base } - public MessageResult(Telegram.Bot.Args.MessageEventArgs rawdata) + public MessageResult(Telegram.Bot.Types.Update update) { - this.RawMessageData = rawdata; - this.Message = rawdata.Message; - } + this.UpdateData = update; - public MessageResult(Telegram.Bot.Args.CallbackQueryEventArgs callback) - { - this.RawCallbackData = callback; - this.Message = callback.CallbackQuery.Message; } } diff --git a/TelegramBotBase/Base/ResultBase.cs b/TelegramBotBase/Base/ResultBase.cs index e351860..e5d37e8 100644 --- a/TelegramBotBase/Base/ResultBase.cs +++ b/TelegramBotBase/Base/ResultBase.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Telegram.Bot; namespace TelegramBotBase.Base { @@ -20,7 +21,7 @@ namespace TelegramBotBase.Base } } - public Telegram.Bot.Types.Message Message { get; set; } + public virtual Telegram.Bot.Types.Message Message { get; set; } /// /// Deletes the current message diff --git a/TelegramBotBase/Base/UpdateResult.cs b/TelegramBotBase/Base/UpdateResult.cs new file mode 100644 index 0000000..f2341dd --- /dev/null +++ b/TelegramBotBase/Base/UpdateResult.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Telegram.Bot.Types; +using TelegramBotBase.Sessions; + +namespace TelegramBotBase.Base +{ + public class UpdateResult : ResultBase + { + public UpdateResult(Update rawData, DeviceSession device) + { + RawData = rawData; + Device = device; + + + } + + /// + /// Returns the Device/ChatId + /// + public override long DeviceId + { + get + { + return this.RawData?.Message?.Chat?.Id + ?? this.RawData?.CallbackQuery?.Message?.Chat?.Id + ?? Device?.DeviceId + ?? 0; + } + } + + public Update RawData { get; set; } + + public override Message Message + { + get + { + return RawData?.Message + ?? RawData?.EditedMessage + ?? RawData?.ChannelPost + ?? RawData?.EditedChannelPost + ?? RawData?.CallbackQuery?.Message; + } + } + + + + public DeviceSession Device + { + get; + set; + } + + + } + +} diff --git a/TelegramBotBase/BotBase.cs b/TelegramBotBase/BotBase.cs index 9d9c354..c853c30 100644 --- a/TelegramBotBase/BotBase.cs +++ b/TelegramBotBase/BotBase.cs @@ -3,13 +3,17 @@ using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using Telegram.Bot; +using Telegram.Bot.Exceptions; using Telegram.Bot.Types; +using Telegram.Bot.Types.Enums; using TelegramBotBase.Args; using TelegramBotBase.Attributes; using TelegramBotBase.Base; using TelegramBotBase.Enums; +using TelegramBotBase.Factories.MessageLoops; using TelegramBotBase.Form; using TelegramBotBase.Interfaces; using TelegramBotBase.Sessions; @@ -20,8 +24,7 @@ namespace TelegramBotBase /// Bot base class for full Device/Context and Messagehandling /// /// - public class BotBase - where T : FormBase + public class BotBase { public MessageClient Client { get; set; } @@ -33,7 +36,7 @@ namespace TelegramBotBase /// /// List of all running/active sessions /// - public SessionBase Sessions { get; set; } + public SessionBase Sessions { get; set; } /// /// Contains System commands which will be available at everytime and didnt get passed to forms, i.e. /start @@ -65,10 +68,22 @@ namespace TelegramBotBase /// public IStateMachine StateMachine { get; set; } + /// + /// Offers functionality to manage the creation process of the start form. + /// + public IStartFormFactory StartFormFactory { get; set; } + /// + /// Contains the message loop factory, which cares about "message-management." + /// + public IMessageLoopFactory MessageLoopFactory { get; set; } + + /// + /// All internal used settings. + /// public Dictionary SystemSettings { get; private set; } - private BotBase() + public BotBase() { this.SystemSettings = new Dictionary(); @@ -80,77 +95,11 @@ namespace TelegramBotBase this.BotCommands = new List(); - this.Sessions = new SessionBase(); + this.Sessions = new SessionBase(); this.Sessions.BotBase = this; } - /// - /// Simple start of your Bot with the APIKey - /// - /// - public BotBase(String apiKey, bool initClient = true) : this() - { - this.APIKey = apiKey; - if (!initClient) - return; - - this.Client = new Base.MessageClient(this.APIKey); - this.Client.TelegramClient.Timeout = new TimeSpan(0, 1, 0); - - this.Sessions.Client = this.Client; - } - - /// - /// Simple start of your Bot with the APIKey and a proxyAdress - /// - /// - /// i.e. https://127.0.0.1:10000 - public BotBase(String apiKey, System.Net.Http.HttpClient proxy) : this(apiKey, false) - { - this.Client = new Base.MessageClient(this.APIKey, proxy); - - this.Sessions.Client = this.Client; - } - - /// - /// Simple start of your Bot with the APIKey and a TelegramBotClient instance. - /// - /// - /// - public BotBase(String apiKey, TelegramBotClient client) : this(apiKey, false) - { - this.Client = new Base.MessageClient(this.APIKey, client); - - this.Sessions.Client = this.Client; - } - - /// - /// Simple start of your Bot with the APIKey and a proxyAdress - /// - /// - /// i.e. https://127.0.0.1:10000 - public BotBase(String apiKey, String proxyBaseAddress) : this(apiKey, false) - { - var url = new Uri(proxyBaseAddress); - - this.Client = new Base.MessageClient(this.APIKey, url); - - this.Sessions.Client = this.Client; - } - - /// - /// Simple start of your Bot with the APIKey and a proxyAdress - /// - /// - /// i.e. 127.0.0.1 - /// i.e. 10000 - public BotBase(String apiKey, String proxyHost, int proxyPort) : this(apiKey, false) - { - this.Client = new Base.MessageClient(this.APIKey, proxyHost, proxyPort); - - this.Sessions.Client = this.Client; - } /// /// Start your Bot @@ -160,9 +109,8 @@ namespace TelegramBotBase if (this.Client == null) return; - this.Client.Message += Client_Message; - this.Client.MessageEdit += Client_MessageEdit; - this.Client.Action += Client_Action; + this.Client.MessageLoop += Client_MessageLoop; + if (this.StateMachine != null) { @@ -180,7 +128,39 @@ namespace TelegramBotBase DeviceSession.MaxNumberOfRetries = this.GetSetting(eSettings.MaxNumberOfRetries, 5); - this.Client.TelegramClient.StartReceiving(); + this.Client.StartReceiving(); + } + + + private async Task Client_MessageLoop(object sender, UpdateResult e) + { + DeviceSession ds = this.Sessions.GetSession(e.DeviceId); + if (ds == null) + { + ds = this.Sessions.StartSession(e.DeviceId).GetAwaiter().GetResult(); + e.Device = ds; + ds.LastMessage = e.RawData.Message; + + OnSessionBegins(new SessionBeginEventArgs(e.DeviceId, ds)); + } + + var mr = new MessageResult(e.RawData); + + int i = 0; + + //Should formulars get navigated (allow maximum of 10, to dont get loops) + do + { + i++; + + //Reset navigation + ds.FormSwitched = false; + + await MessageLoopFactory.MessageLoop(this, ds, e, mr); + + mr.IsFirstHandler = false; + + } while (ds.FormSwitched && i < this.GetSetting(eSettings.NavigationMaximum, 10)); } @@ -192,10 +172,10 @@ namespace TelegramBotBase if (this.Client == null) return; - this.Client.Message -= Client_Message; - this.Client.Action -= Client_Action; + this.Client.MessageLoop -= Client_MessageLoop; - this.Client.TelegramClient.StopReceiving(); + + this.Client.StopReceiving(); this.Sessions.SaveSessionStates(); } @@ -216,204 +196,7 @@ namespace TelegramBotBase } } - private async void Client_Message(object sender, MessageResult e) - { - if (this.GetSetting(eSettings.SkipAllMessages, false)) - return; - try - { - DeviceSession ds = this.Sessions.GetSession(e.DeviceId); - e.Device = ds; - - if (this.GetSetting(eSettings.LogAllMessages, false)) - { - OnMessage(new MessageIncomeEventArgs(e.DeviceId, ds, e)); - } - - ds?.OnMessageReceived(new MessageReceivedEventArgs(e.Message)); - - await Client_Loop(sender, e); - } - catch (Telegram.Bot.Exceptions.ApiRequestException ex) - { - - } - catch (Exception ex) - { - DeviceSession ds = this.Sessions.GetSession(e.DeviceId); - OnException(new SystemExceptionEventArgs(e.Message.Text, ds?.DeviceId ?? -1, ds, ex)); - } - } - - - - //private async Task Client_TryMessage(object sender, MessageResult e) - //{ - // DeviceSession ds = e.Device; - // if (ds == null) - // { - // ds = await this.Sessions.StartSession(e.DeviceId); - // e.Device = ds; - - // ds.LastMessage = e.Message; - - // OnSessionBegins(new SessionBeginEventArgs(e.DeviceId, ds)); - // } - - // ds.LastAction = DateTime.Now; - // ds.LastMessage = e.Message; - - // //Is this a bot command ? - // if (e.IsBotCommand && this.BotCommands.Count(a => "/" + a.Command == e.BotCommand) > 0) - // { - // var sce = new BotCommandEventArgs(e.BotCommand, e.BotCommandParameters, e.Message, ds.DeviceId, ds); - // await OnBotCommand(sce); - - // if (sce.Handled) - // return; - // } - - // FormBase activeForm = null; - - // int i = 0; - - // //Should formulars get navigated (allow maximum of 10, to dont get loops) - // do - // { - // i++; - - // //Reset navigation - // ds.FormSwitched = false; - - // activeForm = ds.ActiveForm; - - // //Pre Loading Event - // await activeForm.PreLoad(e); - - // //Send Load event to controls - // await activeForm.LoadControls(e); - - // //Loading Event - // await activeForm.Load(e); - - // //Is Attachment ? (Photo, Audio, Video, Contact, Location, Document) - // if (e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Contact | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Document | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Location | - // e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Photo | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Video | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Audio) - // { - // await activeForm.SentData(new DataResult(e)); - // } - - // //Render Event - // if (!ds.FormSwitched) - // { - // await activeForm.RenderControls(e); - - // await activeForm.Render(e); - // } - - // e.IsFirstHandler = false; - - // } while (ds.FormSwitched && i < this.GetSetting(eSettings.NavigationMaximum, 10)); - - - //} - - private async Task Client_Loop(object sender, MessageResult e) - { - DeviceSession ds = e.Device; - if (ds == null) - { - ds = await this.Sessions.StartSession(e.DeviceId); - e.Device = ds; - ds.LastMessage = e.Message; - - OnSessionBegins(new SessionBeginEventArgs(e.DeviceId, ds)); - } - - ds.LastAction = DateTime.Now; - ds.LastMessage = e.Message; - - //Is this a bot command ? - if (e.IsBotCommand && this.BotCommands.Count(a => "/" + a.Command == e.BotCommand) > 0) - { - var sce = new BotCommandEventArgs(e.BotCommand, e.BotCommandParameters, e.Message, ds.DeviceId, ds); - await OnBotCommand(sce); - - if (sce.Handled) - return; - } - - FormBase activeForm = null; - - int i = 0; - - //Should formulars get navigated (allow maximum of 10, to dont get loops) - do - { - i++; - - //Reset navigation - ds.FormSwitched = false; - - activeForm = ds.ActiveForm; - - //Pre Loading Event - await activeForm.PreLoad(e); - - //Send Load event to controls - await activeForm.LoadControls(e); - - //Loading Event - await activeForm.Load(e); - - //Is Attachment ? (Photo, Audio, Video, Contact, Location, Document) - if (e.MessageType == Telegram.Bot.Types.Enums.MessageType.Contact | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Document | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Location | - e.MessageType == Telegram.Bot.Types.Enums.MessageType.Photo | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Video | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Audio) - { - await activeForm.SentData(new DataResult(e)); - } - - //Action Event - if (!ds.FormSwitched && e.IsAction) - { - //Send Action event to controls - await activeForm.ActionControls(e); - - //Send Action event to form itself - 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) - { - e.Handled = true; - if (!ds.FormSwitched) - { - break; - } - } - } - - } - - if (!ds.FormSwitched) - { - //Render Event - await activeForm.RenderControls(e); - - await activeForm.Render(e); - } - - e.IsFirstHandler = false; - - } while (ds.FormSwitched && i < this.GetSetting(eSettings.NavigationMaximum, 10)); - - - } /// /// This will invoke the full message loop for the device even when no "userevent" like message or action has been raised. @@ -438,7 +221,8 @@ namespace TelegramBotBase DeviceSession ds = this.Sessions.GetSession(DeviceId); e.Device = ds; - await Client_Loop(this, e); + await MessageLoopFactory.MessageLoop(this, ds, new UpdateResult(e.UpdateData, ds), e); + //await Client_Loop(this, e); } catch (Exception ex) { @@ -447,156 +231,17 @@ namespace TelegramBotBase } } - private async void Client_MessageEdit(object sender, MessageResult e) + + /// + /// Will get invoke on an unhandled call. + /// + /// + /// + public void MessageLoopFactory_UnhandledCall(object sender, UnhandledCallEventArgs e) { - if (this.GetSetting(eSettings.SkipAllMessages, false)) - return; - - try - { - DeviceSession ds = this.Sessions.GetSession(e.DeviceId); - e.Device = ds; - - if (this.GetSetting(eSettings.LogAllMessages, false)) - { - OnMessage(new MessageIncomeEventArgs(e.DeviceId, ds, e)); - } - - //Call same, to handle received liked edited - ds?.OnMessageReceived(new MessageReceivedEventArgs(e.Message)); - - await Client_TryMessageEdit(sender, e); - } - catch (Telegram.Bot.Exceptions.ApiRequestException ex) - { - - } - catch (Exception ex) - { - DeviceSession ds = this.Sessions.GetSession(e.DeviceId); - OnException(new SystemExceptionEventArgs(e.Message.Text, ds?.DeviceId ?? -1, ds, ex)); - } + OnUnhandledCall(e); } - private async Task Client_TryMessageEdit(object sender, MessageResult e) - { - DeviceSession ds = e.Device; - if (ds == null) - { - ds = await this.Sessions.StartSession(e.DeviceId); - e.Device = ds; - } - - ds.LastAction = DateTime.Now; - ds.LastMessage = e.Message; - - //Pre Loading Event - await ds.ActiveForm.Edited(e); - - //When form has been switched due navigation within the edit method, reopen Client_Message - if (ds.FormSwitched) - { - await Client_Loop(sender, e); - } - - } - - private async void Client_Action(object sender, MessageResult e) - { - try - { - DeviceSession ds = this.Sessions.GetSession(e.DeviceId); - e.Device = ds; - - if (this.GetSetting(eSettings.LogAllMessages, false)) - { - OnMessage(new MessageIncomeEventArgs(e.DeviceId, ds, e)); - } - - await Client_Loop(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 = e.Device; - // if (ds == null) - // { - // ds = await this.Sessions.StartSession(e.DeviceId); - // e.Device = ds; - // } - - // ds.LastAction = DateTime.Now; - // ds.LastMessage = e.Message; - - // FormBase activeForm = null; - - // int i = 0; - - // //Should formulars get navigated (allow maximum of 10, to dont get loops) - // do - // { - // i++; - - // //Reset navigation - // ds.FormSwitched = false; - - // activeForm = ds.ActiveForm; - - // //Pre Loading Event - // await activeForm.PreLoad(e); - - // //Send Load event to controls - // await activeForm.LoadControls(e); - - // //Loading Event - // await activeForm.Load(e); - - // //Action Event - // if (!ds.FormSwitched) - // { - // //Send Action event to controls - // await activeForm.ActionControls(e); - - // //Send Action event to form itself - // 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) - // { - // e.Handled = true; - // if (!ds.FormSwitched) - // { - // break; - // } - // } - // } - - // } - - // //Render Event - // if (!ds.FormSwitched) - // { - // await activeForm.RenderControls(e); - - // await activeForm.Render(e); - // } - - // e.IsFirstHandler = false; - - // } while (ds.FormSwitched && i < this.GetSetting(eSettings.NavigationMaximum, 10)); - - //} - /// /// This method will update all local created bot commands to the botfather. /// diff --git a/TelegramBotBase/Builder/BotBaseBuilder.cs b/TelegramBotBase/Builder/BotBaseBuilder.cs new file mode 100644 index 0000000..517a8fb --- /dev/null +++ b/TelegramBotBase/Builder/BotBaseBuilder.cs @@ -0,0 +1,324 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using Telegram.Bot; +using Telegram.Bot.Types; +using TelegramBotBase.Base; +using TelegramBotBase.Builder.Interfaces; +using TelegramBotBase.Commands; +using TelegramBotBase.Form; +using TelegramBotBase.Interfaces; +using TelegramBotBase.Localizations; +using TelegramBotBase.States; + +namespace TelegramBotBase.Builder +{ + public class BotBaseBuilder : IAPIKeySelectionStage, IMessageLoopSelectionStage, IStartFormSelectionStage, IBuildingStage, INetworkingSelectionStage, IBotCommandsStage, ISessionSerializationStage, ILanguageSelectionStage + { + + String _apiKey = null; + + IStartFormFactory _factory = null; + + MessageClient _client = null; + + List _botcommands = new List(); + + IStateMachine _statemachine = null; + + IMessageLoopFactory _messageloopfactory = null; + + private BotBaseBuilder() + { + + } + + public static IAPIKeySelectionStage Create() + { + return new BotBaseBuilder(); + } + + #region "Step 1 (Basic Stuff)" + + public IMessageLoopSelectionStage WithAPIKey(string apiKey) + { + this._apiKey = apiKey; + return this; + } + + + public IBuildingStage QuickStart(string apiKey, Type StartForm) + { + this._apiKey = apiKey; + this._factory = new Factories.DefaultStartFormFactory(StartForm); + + DefaultMessageLoop(); + + NoProxy(); + + OnlyStart(); + + NoSerialization(); + + DefaultLanguage(); + + return this; + } + + + public IBuildingStage QuickStart(string apiKey) + where T : FormBase + { + this._apiKey = apiKey; + this._factory = new Factories.DefaultStartFormFactory(typeof(T)); + + DefaultMessageLoop(); + + NoProxy(); + + OnlyStart(); + + NoSerialization(); + + DefaultLanguage(); + + return this; + } + + public IBuildingStage QuickStart(string apiKey, IStartFormFactory StartFormFactory) + { + this._apiKey = apiKey; + this._factory = StartFormFactory; + + DefaultMessageLoop(); + + NoProxy(); + + OnlyStart(); + + NoSerialization(); + + DefaultLanguage(); + + return this; + } + + #endregion + + + #region "Step 2 (Message Loop)" + + public IStartFormSelectionStage DefaultMessageLoop() + { + _messageloopfactory = new Factories.MessageLoops.FormBaseMessageLoop(); + + return this; + } + + public IStartFormSelectionStage CustomMessageLoop(IMessageLoopFactory messageLoopClass) + { + _messageloopfactory = messageLoopClass; + + return this; + } + + public IStartFormSelectionStage CustomMessageLoop() + where T : class, new() + { + _messageloopfactory = typeof(T).GetConstructor(new Type[] { })?.Invoke(new object[] { }) as IMessageLoopFactory; + + return this; + } + + #endregion + + + #region "Step 3 (Start Form/Factory)" + + public INetworkingSelectionStage WithStartForm(Type startFormClass) + { + this._factory = new Factories.DefaultStartFormFactory(startFormClass); + return this; + } + + public INetworkingSelectionStage WithStartForm() + where T : FormBase, new() + { + this._factory = new Factories.DefaultStartFormFactory(typeof(T)); + return this; + } + + public INetworkingSelectionStage WithStartFormFactory(IStartFormFactory factory) + { + this._factory = factory; + return this; + } + + #endregion + + + #region "Step 4 (Network Settings)" + + public IBotCommandsStage WithProxy(string proxyAddress) + { + var url = new Uri(proxyAddress); + _client = new MessageClient(_apiKey, url); + _client.TelegramClient.Timeout = new TimeSpan(0, 1, 0); + return this; + } + + + public IBotCommandsStage NoProxy() + { + _client = new MessageClient(_apiKey); + _client.TelegramClient.Timeout = new TimeSpan(0, 1, 0); + return this; + } + + + public IBotCommandsStage WithBotClient(TelegramBotClient tgclient) + { + _client = new MessageClient(_apiKey, tgclient); + _client.TelegramClient.Timeout = new TimeSpan(0, 1, 0); + return this; + } + + + public IBotCommandsStage WithHostAndPort(string proxyHost, int proxyPort) + { + _client = new MessageClient(_apiKey, proxyHost, proxyPort); + _client.TelegramClient.Timeout = new TimeSpan(0, 1, 0); + return this; + } + + public IBotCommandsStage WithHttpClient(HttpClient tgclient) + { + _client = new MessageClient(_apiKey, tgclient); + _client.TelegramClient.Timeout = new TimeSpan(0, 1, 0); + return this; + } + + + #endregion + + + #region "Step 5 (Bot Commands)" + + public ISessionSerializationStage NoCommands() + { + return this; + } + + public ISessionSerializationStage OnlyStart() + { + _botcommands.Start("Starts the bot"); + + return this; + + } + + public ISessionSerializationStage DefaultCommands() + { + _botcommands.Start("Starts the bot"); + _botcommands.Help("Should show you some help"); + _botcommands.Settings("Should show you some settings"); + return this; + } + + public ISessionSerializationStage CustomCommands(Action> action) + { + action?.Invoke(_botcommands); + return this; + } + + #endregion + + + #region "Step 6 (Serialization)" + + public ILanguageSelectionStage NoSerialization() + { + return this; + } + + public ILanguageSelectionStage UseSerialization(IStateMachine machine) + { + this._statemachine = machine; + return this; + } + + + public ILanguageSelectionStage UseJSON(string path) + { + this._statemachine = new JSONStateMachine(path); + return this; + } + + public ILanguageSelectionStage UseSimpleJSON(string path) + { + this._statemachine = new SimpleJSONStateMachine(path); + return this; + } + + public ILanguageSelectionStage UseXML(string path) + { + this._statemachine = new XMLStateMachine(path); + return this; + } + + #endregion + + + #region "Step 7 (Language)" + + public IBuildingStage DefaultLanguage() + { + return this; + } + + public IBuildingStage UseEnglish() + { + Localizations.Default.Language = new Localizations.English(); + return this; + } + + public IBuildingStage UseGerman() + { + Localizations.Default.Language = new Localizations.German(); + return this; + } + + public IBuildingStage Custom(Localization language) + { + Localizations.Default.Language = language; + return this; + } + + #endregion + + + public BotBase Build() + { + var bb = new BotBase(); + + bb.APIKey = _apiKey; + bb.StartFormFactory = _factory; + + bb.Client = _client; + + bb.Sessions.Client = bb.Client; + + bb.BotCommands = _botcommands; + + bb.StateMachine = _statemachine; + + bb.MessageLoopFactory = _messageloopfactory; + + bb.MessageLoopFactory.UnhandledCall += bb.MessageLoopFactory_UnhandledCall; + + return bb; + } + + } +} diff --git a/TelegramBotBase/Builder/Interfaces/IAPIKeySelectionStage.cs b/TelegramBotBase/Builder/Interfaces/IAPIKeySelectionStage.cs new file mode 100644 index 0000000..bd6f05e --- /dev/null +++ b/TelegramBotBase/Builder/Interfaces/IAPIKeySelectionStage.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Text; +using TelegramBotBase.Form; +using TelegramBotBase.Interfaces; + +namespace TelegramBotBase.Builder.Interfaces +{ + public interface IAPIKeySelectionStage + { + /// + /// Sets the API Key which will be used by the telegram bot client. + /// + /// + /// + IMessageLoopSelectionStage WithAPIKey(String apiKey); + + + /// + /// Quick and easy way to create a BotBase instance. + /// Uses: DefaultMessageLoop, NoProxy, OnlyStart, NoSerialization, DefaultLanguage + /// + /// + /// + /// + IBuildingStage QuickStart(String apiKey, Type StartForm); + + /// + /// Quick and easy way to create a BotBase instance. + /// Uses: DefaultMessageLoop, NoProxy, OnlyStart, NoSerialization, DefaultLanguage + /// + /// + /// + IBuildingStage QuickStart(String apiKey) where T : FormBase; + + /// + /// Quick and easy way to create a BotBase instance. + /// Uses: DefaultMessageLoop, NoProxy, OnlyStart, NoSerialization, DefaultLanguage + /// + /// + /// + /// + IBuildingStage QuickStart(String apiKey, IStartFormFactory StartFormFactory); + } +} diff --git a/TelegramBotBase/Builder/Interfaces/IBotCommandsStage.cs b/TelegramBotBase/Builder/Interfaces/IBotCommandsStage.cs new file mode 100644 index 0000000..cb1507c --- /dev/null +++ b/TelegramBotBase/Builder/Interfaces/IBotCommandsStage.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Telegram.Bot.Types; + +namespace TelegramBotBase.Builder.Interfaces +{ + public interface IBotCommandsStage + { + /// + /// Does not create any commands. + /// + /// + ISessionSerializationStage NoCommands(); + + + /// + /// Creates default commands for start, help and settings. + /// + /// + ISessionSerializationStage DefaultCommands(); + + + /// + /// Only adds the start command. + /// + /// + ISessionSerializationStage OnlyStart(); + + + /// + /// Gives you the ability to add custom commands. + /// + /// + /// + ISessionSerializationStage CustomCommands(Action> action); + + } +} diff --git a/TelegramBotBase/Builder/Interfaces/IBuildingStage.cs b/TelegramBotBase/Builder/Interfaces/IBuildingStage.cs new file mode 100644 index 0000000..8313b0b --- /dev/null +++ b/TelegramBotBase/Builder/Interfaces/IBuildingStage.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace TelegramBotBase.Builder.Interfaces +{ + public interface IBuildingStage + { + BotBase Build(); + } +} diff --git a/TelegramBotBase/Builder/Interfaces/ILanguageSelectionStage.cs b/TelegramBotBase/Builder/Interfaces/ILanguageSelectionStage.cs new file mode 100644 index 0000000..2e5e01a --- /dev/null +++ b/TelegramBotBase/Builder/Interfaces/ILanguageSelectionStage.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text; +using TelegramBotBase.Localizations; + +namespace TelegramBotBase.Builder.Interfaces +{ + public interface ILanguageSelectionStage + { + + /// + /// Selects the default language for control usage. (English) + /// + /// + IBuildingStage DefaultLanguage(); + + /// + /// Selects english as the default language for control labels. + /// + /// + IBuildingStage UseEnglish(); + + /// + /// Selects german as the default language for control labels. + /// + /// + IBuildingStage UseGerman(); + + /// + /// Selects a custom language as the default language for control labels. + /// + /// + IBuildingStage Custom(Localization language); + + } +} diff --git a/TelegramBotBase/Builder/Interfaces/INetworkingSelectionStage.cs b/TelegramBotBase/Builder/Interfaces/INetworkingSelectionStage.cs new file mode 100644 index 0000000..4b5bcce --- /dev/null +++ b/TelegramBotBase/Builder/Interfaces/INetworkingSelectionStage.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using Telegram.Bot; + +namespace TelegramBotBase.Builder.Interfaces +{ + public interface INetworkingSelectionStage + { + + /// + /// Chooses a proxy as network configuration. + /// + /// + /// + IBotCommandsStage WithProxy(String proxyAddress); + + /// + /// Do not choose a proxy as network configuration. + /// + /// + IBotCommandsStage NoProxy(); + + + /// + /// Chooses a custom instance of TelegramBotClient. + /// + /// + /// + IBotCommandsStage WithBotClient(TelegramBotClient client); + + + /// + /// Sets the custom proxy host and port. + /// + /// + /// + /// + IBotCommandsStage WithHostAndPort(String proxyHost, int Port); + + /// + /// Uses a custom http client. + /// + /// + /// + IBotCommandsStage WithHttpClient(HttpClient client); + + + } +} diff --git a/TelegramBotBase/Builder/Interfaces/ISessionSerializationStage.cs b/TelegramBotBase/Builder/Interfaces/ISessionSerializationStage.cs new file mode 100644 index 0000000..a729da2 --- /dev/null +++ b/TelegramBotBase/Builder/Interfaces/ISessionSerializationStage.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Text; +using TelegramBotBase.Interfaces; + +namespace TelegramBotBase.Builder.Interfaces +{ + public interface ISessionSerializationStage + { + /// + /// Do not uses serialization. + /// + /// + ILanguageSelectionStage NoSerialization(); + + + /// + /// Sets the state machine for serialization. + /// + /// + /// + ILanguageSelectionStage UseSerialization(IStateMachine machine); + + + /// + /// Using the complex version of .Net JSON, which can serialize all objects. + /// + /// + /// + ILanguageSelectionStage UseJSON(String path); + + + /// + /// Use the easy version of .Net JSON, which can serialize basic types, but not generics and others. + /// + /// + /// + ILanguageSelectionStage UseSimpleJSON(String path); + + + /// + /// Uses the XML serializer for session serialization. + /// + /// + /// + ILanguageSelectionStage UseXML(String path); + + } +} diff --git a/TelegramBotBase/Builder/Interfaces/IStartFormSelectionStage.cs b/TelegramBotBase/Builder/Interfaces/IStartFormSelectionStage.cs new file mode 100644 index 0000000..fec05b3 --- /dev/null +++ b/TelegramBotBase/Builder/Interfaces/IStartFormSelectionStage.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; +using TelegramBotBase.Form; +using TelegramBotBase.Interfaces; + +namespace TelegramBotBase.Builder.Interfaces +{ + public interface IStartFormSelectionStage + { + + /// + /// Chooses a start form type which will be used for new sessions. + /// + /// + /// + INetworkingSelectionStage WithStartForm(Type startFormClass); + + /// + /// Chooses a generic start form which will be used for new sessions. + /// + /// + /// + INetworkingSelectionStage WithStartForm() where T : FormBase, new(); + + /// + /// Chooses a StartFormFactory which will be use for new sessions. + /// + /// + /// + INetworkingSelectionStage WithStartFormFactory(IStartFormFactory factory); + + } +} diff --git a/TelegramBotBase/Commands/Extensions.cs b/TelegramBotBase/Commands/Extensions.cs index b866439..a07c031 100644 --- a/TelegramBotBase/Commands/Extensions.cs +++ b/TelegramBotBase/Commands/Extensions.cs @@ -12,7 +12,7 @@ namespace TelegramBotBase.Commands /// /// /// - public static void AddStartCommand(this List cmds, String description) + public static void Start(this List cmds, String description) { cmds.Add(new BotCommand() { Command = "start", Description = description }); } @@ -22,7 +22,7 @@ namespace TelegramBotBase.Commands /// /// /// - public static void AddHelpCommand(this List cmds, String description) + public static void Help(this List cmds, String description) { cmds.Add(new BotCommand() { Command = "help", Description = description }); } @@ -32,9 +32,20 @@ namespace TelegramBotBase.Commands /// /// /// - public static void AddSettingsCommand(this List cmds, String description) + public static void Settings(this List cmds, String description) { cmds.Add(new BotCommand() { Command = "settings", Description = description }); } + + /// + /// Adding the command with a description. + /// + /// + /// + /// + public static void Add(this List cmds, String command, String description) + { + cmds.Add(new BotCommand() { Command = command, Description = description }); + } } } diff --git a/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs b/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs index d8bfdb1..d62179f 100644 --- a/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs +++ b/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs @@ -75,7 +75,7 @@ namespace TelegramBotBase.Controls.Hybrid /// /// Parsemode of the message. /// - public ParseMode MessageParseMode { get; set; } = ParseMode.Default; + public ParseMode MessageParseMode { get; set; } = ParseMode.Markdown; /// /// Enables automatic paging of buttons when the amount of rows is exceeding the limits. diff --git a/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs b/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs index 9c2e414..12026b2 100644 --- a/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs +++ b/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs @@ -76,7 +76,7 @@ namespace TelegramBotBase.Controls.Hybrid /// /// Parsemode of the message. /// - public ParseMode MessageParseMode { get; set; } = ParseMode.Default; + public ParseMode MessageParseMode { get; set; } = ParseMode.Markdown; /// /// Enables automatic paging of buttons when the amount of rows is exceeding the limits. diff --git a/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs b/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs index 55ed12e..cf0bc90 100644 --- a/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs +++ b/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs @@ -73,7 +73,7 @@ namespace TelegramBotBase.Controls.Hybrid /// /// Parsemode of the message. /// - public ParseMode MessageParseMode { get; set; } = ParseMode.Default; + public ParseMode MessageParseMode { get; set; } = ParseMode.Markdown; /// /// Enables automatic paging of buttons when the amount of rows is exceeding the limits. diff --git a/TelegramBotBase/Factories/DefaultStartFormFactory.cs b/TelegramBotBase/Factories/DefaultStartFormFactory.cs new file mode 100644 index 0000000..e3c7c20 --- /dev/null +++ b/TelegramBotBase/Factories/DefaultStartFormFactory.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using TelegramBotBase.Form; + +namespace TelegramBotBase.Factories +{ + public class DefaultStartFormFactory : Interfaces.IStartFormFactory + { + private readonly Type _startFormClass; + + public DefaultStartFormFactory(Type startFormClass) + { + if (!typeof(FormBase).IsAssignableFrom(startFormClass)) + throw new ArgumentException("startFormClass argument must be a FormBase type"); + + _startFormClass = startFormClass; + } + + + public FormBase CreateForm() + { + return _startFormClass.GetConstructor(new Type[] { })?.Invoke(new object[] { }) as FormBase; + } + } +} diff --git a/TelegramBotBase/Factories/LambdaStartFormFactory.cs b/TelegramBotBase/Factories/LambdaStartFormFactory.cs new file mode 100644 index 0000000..c748b20 --- /dev/null +++ b/TelegramBotBase/Factories/LambdaStartFormFactory.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; +using TelegramBotBase.Form; + +namespace TelegramBotBase.Factories +{ + public class LambdaStartFormFactory : Interfaces.IStartFormFactory + { + public delegate FormBase CreateFormDelegate(); + + private readonly CreateFormDelegate _lambda; + + public LambdaStartFormFactory(CreateFormDelegate lambda) + { + _lambda = lambda; + } + + public FormBase CreateForm() + { + return _lambda(); + } + } +} diff --git a/TelegramBotBase/Factories/MessageLoops/FormBaseMessageLoop.cs b/TelegramBotBase/Factories/MessageLoops/FormBaseMessageLoop.cs new file mode 100644 index 0000000..6568e19 --- /dev/null +++ b/TelegramBotBase/Factories/MessageLoops/FormBaseMessageLoop.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Telegram.Bot.Types; +using TelegramBotBase.Args; +using TelegramBotBase.Base; +using TelegramBotBase.Enums; +using TelegramBotBase.Interfaces; +using TelegramBotBase.Sessions; + +namespace TelegramBotBase.Factories.MessageLoops +{ + public class FormBaseMessageLoop : IMessageLoopFactory + { + private static object __evUnhandledCall = new object(); + + private EventHandlerList __Events = new EventHandlerList(); + + public FormBaseMessageLoop() + { + + } + + public async Task MessageLoop(BotBase Bot, DeviceSession session, UpdateResult ur, MessageResult mr) + { + var update = ur.RawData; + + + if (update.Type != Telegram.Bot.Types.Enums.UpdateType.Message + && update.Type != Telegram.Bot.Types.Enums.UpdateType.EditedMessage + && update.Type != Telegram.Bot.Types.Enums.UpdateType.CallbackQuery) + { + return; + } + + //Is this a bot command ? + if (mr.IsFirstHandler && mr.IsBotCommand && Bot.BotCommands.Count(a => "/" + a.Command == mr.BotCommand) > 0) + { + var sce = new BotCommandEventArgs(mr.BotCommand, mr.BotCommandParameters, mr.Message, session.DeviceId, session); + await Bot.OnBotCommand(sce); + + if (sce.Handled) + return; + } + + mr.Device = session; + + var activeForm = session.ActiveForm; + + //Pre Loading Event + await activeForm.PreLoad(mr); + + //Send Load event to controls + await activeForm.LoadControls(mr); + + //Loading Event + await activeForm.Load(mr); + + + //Is Attachment ? (Photo, Audio, Video, Contact, Location, Document) (Ignore Callback Queries) + if (update.Type == Telegram.Bot.Types.Enums.UpdateType.Message) + { + if (mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Contact + | mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Document + | mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Location + | mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Photo + | mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Video + | mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Audio) + { + await activeForm.SentData(new DataResult(ur)); + } + } + + //Action Event + if (!session.FormSwitched && mr.IsAction) + { + //Send Action event to controls + await activeForm.ActionControls(mr); + + //Send Action event to form itself + await activeForm.Action(mr); + + if (!mr.Handled) + { + var uhc = new UnhandledCallEventArgs(ur.Message.Text, mr.RawData, session.DeviceId, mr.MessageId, ur.Message, session); + OnUnhandledCall(uhc); + + if (uhc.Handled) + { + mr.Handled = true; + if (!session.FormSwitched) + { + return; + } + } + } + + } + + if (!session.FormSwitched) + { + //Render Event + await activeForm.RenderControls(mr); + + await activeForm.Render(mr); + } + + } + + /// + /// Will be called if no form handeled this call + /// + 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/AutoCleanForm.cs b/TelegramBotBase/Form/AutoCleanForm.cs index 4acc8ee..4e6a692 100644 --- a/TelegramBotBase/Form/AutoCleanForm.cs +++ b/TelegramBotBase/Form/AutoCleanForm.cs @@ -138,7 +138,7 @@ namespace TelegramBotBase.Form { var oldMessages = OldMessages.AsEnumerable(); -#if !NET472 +#if !NETSTANDARD2_0 while (oldMessages.Any()) { using var cts = new CancellationTokenSource(); @@ -150,8 +150,15 @@ namespace TelegramBotBase.Form { parallelQuery.ForAll(i => { - Device.DeleteMessage(i).GetAwaiter().GetResult(); - deletedMessages.Add(i); + try + { + Device.DeleteMessage(i).GetAwaiter().GetResult(); + deletedMessages.Add(i); + } + catch (ApiRequestException req) when (req.ErrorCode == 400) + { + deletedMessages.Add(i); + } }); } catch (AggregateException ex) @@ -160,10 +167,10 @@ namespace TelegramBotBase.Form var retryAfterSeconds = ex.InnerExceptions .Where(e => e is ApiRequestException apiEx && apiEx.ErrorCode == 429) - .Max(e =>(int?) ((ApiRequestException)e).Parameters.RetryAfter) ?? 0; + .Max(e => (int?)((ApiRequestException)e).Parameters.RetryAfter) ?? 0; retryAfterTask = Task.Delay(retryAfterSeconds * 1000); } - + //deletedMessages.AsParallel().ForAll(i => Device.OnMessageDeleted(new MessageDeletedEventArgs(i))); oldMessages = oldMessages.Where(x => !deletedMessages.Contains(x)); @@ -183,8 +190,15 @@ namespace TelegramBotBase.Form { parallelQuery.ForAll(i => { - Device.DeleteMessage(i).GetAwaiter().GetResult(); - deletedMessages.Add(i); + try + { + Device.DeleteMessage(i).GetAwaiter().GetResult(); + deletedMessages.Add(i); + } + catch (ApiRequestException req) when (req.ErrorCode == 400) + { + deletedMessages.Add(i); + } }); } catch (AggregateException ex) diff --git a/TelegramBotBase/Form/ButtonBase.cs b/TelegramBotBase/Form/ButtonBase.cs index 54ffefe..efb4466 100644 --- a/TelegramBotBase/Form/ButtonBase.cs +++ b/TelegramBotBase/Form/ButtonBase.cs @@ -46,9 +46,9 @@ namespace TelegramBotBase.Form return InlineKeyboardButton.WithCallbackData(this.Text, id + this.Value); } - var ikb = new InlineKeyboardButton(); + var ikb = new InlineKeyboardButton(this.Text); - ikb.Text = this.Text; + //ikb.Text = this.Text; ikb.Url = this.Url; return ikb; diff --git a/TelegramBotBase/Form/GroupForm.cs b/TelegramBotBase/Form/GroupForm.cs index 6b460cf..ecdc01f 100644 --- a/TelegramBotBase/Form/GroupForm.cs +++ b/TelegramBotBase/Form/GroupForm.cs @@ -24,12 +24,12 @@ namespace TelegramBotBase.Form { case Telegram.Bot.Types.Enums.MessageType.ChatMembersAdded: - await OnMemberChanges(new MemberChangeEventArgs(Telegram.Bot.Types.Enums.MessageType.ChatMembersAdded, message, message.RawMessageData.Message.NewChatMembers)); + await OnMemberChanges(new MemberChangeEventArgs(Telegram.Bot.Types.Enums.MessageType.ChatMembersAdded, message, message.Message.NewChatMembers)); break; case Telegram.Bot.Types.Enums.MessageType.ChatMemberLeft: - await OnMemberChanges(new MemberChangeEventArgs(Telegram.Bot.Types.Enums.MessageType.ChatMemberLeft, message, message.RawMessageData.Message.LeftChatMember)); + await OnMemberChanges(new MemberChangeEventArgs(Telegram.Bot.Types.Enums.MessageType.ChatMemberLeft, message, message.Message.LeftChatMember)); break; diff --git a/TelegramBotBase/Interfaces/IMessageLoopFactory.cs b/TelegramBotBase/Interfaces/IMessageLoopFactory.cs new file mode 100644 index 0000000..fec857f --- /dev/null +++ b/TelegramBotBase/Interfaces/IMessageLoopFactory.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Telegram.Bot.Types; +using TelegramBotBase.Args; +using TelegramBotBase.Base; +using TelegramBotBase.Sessions; + +namespace TelegramBotBase.Interfaces +{ + public interface IMessageLoopFactory + { + + Task MessageLoop(BotBase Bot, DeviceSession session, UpdateResult ur, MessageResult e); + + event EventHandler UnhandledCall; + + + } +} diff --git a/TelegramBotBase/Interfaces/IStartFormFactory.cs b/TelegramBotBase/Interfaces/IStartFormFactory.cs new file mode 100644 index 0000000..7c1c44d --- /dev/null +++ b/TelegramBotBase/Interfaces/IStartFormFactory.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; +using TelegramBotBase.Form; + +namespace TelegramBotBase.Interfaces +{ + public interface IStartFormFactory + { + FormBase CreateForm(); + } +} diff --git a/TelegramBotBase/SessionBase.cs b/TelegramBotBase/SessionBase.cs index 33dc0fb..b94f59a 100644 --- a/TelegramBotBase/SessionBase.cs +++ b/TelegramBotBase/SessionBase.cs @@ -16,14 +16,23 @@ namespace TelegramBotBase /// /// Base class for managing all active sessions /// - public class SessionBase - where T : FormBase + public class SessionBase { + /// + /// The Basic message client. + /// public MessageClient Client { get; set; } + /// + /// A list of all active sessions. + /// public Dictionary SessionList { get; set; } - public BotBase BotBase { get; set; } + + /// + /// Reference to the Main BotBase instance for later use. + /// + public BotBase BotBase { get; set; } public SessionBase() @@ -65,10 +74,10 @@ namespace TelegramBotBase /// /// /// - public async Task StartSession(long deviceId) - where T : FormBase + public async Task StartSession(long deviceId) { - T start = typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { }) as T; + var start = BotBase.StartFormFactory.CreateForm(); + //T start = typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { }) as T; start.Client = this.Client; @@ -239,7 +248,7 @@ namespace TelegramBotBase } - + /// diff --git a/TelegramBotBase/Sessions/DeviceSession.cs b/TelegramBotBase/Sessions/DeviceSession.cs index cf3a5c4..945abfd 100644 --- a/TelegramBotBase/Sessions/DeviceSession.cs +++ b/TelegramBotBase/Sessions/DeviceSession.cs @@ -2,12 +2,11 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; -using System.Drawing; -using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using Telegram.Bot; using Telegram.Bot.Exceptions; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; @@ -139,6 +138,23 @@ namespace TelegramBotBase.Sessions } + /// + /// Confirm incomming action (i.e. Button click) + /// + /// + /// + public async Task ConfirmAction(String CallbackQueryId, String message = "", bool showAlert = false, String urlToOpen = null) + { + try + { + await this.Client.TelegramClient.AnswerCallbackQueryAsync(CallbackQueryId, message, showAlert, urlToOpen); + } + catch + { + + } + } + /// /// Edits the text message /// @@ -146,7 +162,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task Edit(int messageId, String text, ButtonForm buttons = null, ParseMode parseMode = ParseMode.Default) + public async Task Edit(int messageId, String text, ButtonForm buttons = null, ParseMode parseMode = ParseMode.Markdown) { InlineKeyboardMarkup markup = buttons; @@ -175,7 +191,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task Edit(int messageId, String text, InlineKeyboardMarkup markup, ParseMode parseMode = ParseMode.Default) + public async Task Edit(int messageId, String text, InlineKeyboardMarkup markup, ParseMode parseMode = ParseMode.Markdown) { if (text.Length > Constants.Telegram.MaxMessageLength) { @@ -202,7 +218,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task Edit(Message message, ButtonForm buttons = null, ParseMode parseMode = ParseMode.Default) + public async Task Edit(Message message, ButtonForm buttons = null, ParseMode parseMode = ParseMode.Markdown) { InlineKeyboardMarkup markup = buttons; @@ -253,7 +269,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task Send(long deviceId, String text, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default, bool MarkdownV2AutoEscape = true) + public async Task Send(long deviceId, String text, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown, bool MarkdownV2AutoEscape = true) { if (this.ActiveForm == null) return null; @@ -293,7 +309,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task Send(String text, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default, bool MarkdownV2AutoEscape = true) + public async Task Send(String text, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown, bool MarkdownV2AutoEscape = true) { return await Send(this.DeviceId, text, buttons, replyTo, disableNotification, parseMode, MarkdownV2AutoEscape); } @@ -306,7 +322,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task Send(String text, InlineKeyboardMarkup markup, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default, bool MarkdownV2AutoEscape = true) + public async Task Send(String text, InlineKeyboardMarkup markup, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown, bool MarkdownV2AutoEscape = true) { if (this.ActiveForm == null) return null; @@ -344,7 +360,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task Send(String text, ReplyMarkupBase markup, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default, bool MarkdownV2AutoEscape = true) + public async Task Send(String text, ReplyMarkupBase markup, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown, bool MarkdownV2AutoEscape = true) { if (this.ActiveForm == null) return null; @@ -382,7 +398,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task SendPhoto(InputOnlineFile file, String caption = null, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default) + public async Task SendPhoto(InputOnlineFile file, String caption = null, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown) { if (this.ActiveForm == null) return null; @@ -404,44 +420,6 @@ namespace TelegramBotBase.Sessions } } - /// - /// Sends an image - /// - /// - /// - /// - /// - /// - /// - public async Task SendPhoto(Image image, String name, String caption, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false) - { - using (var fileStream = Tools.Images.ToStream(image, ImageFormat.Png)) - { - InputOnlineFile fts = new InputOnlineFile(fileStream, name); - - return await SendPhoto(fts, caption: caption, buttons, replyTo, disableNotification); - } - } - - /// - /// Sends an image - /// - /// - /// - /// - /// - /// - /// - public async Task SendPhoto(Bitmap image, String name, String caption, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false) - { - using (var fileStream = Tools.Images.ToStream(image, ImageFormat.Png)) - { - InputOnlineFile fts = new InputOnlineFile(fileStream, name); - - return await SendPhoto(fts, caption: caption, buttons, replyTo, disableNotification); - } - } - /// /// Sends an video /// @@ -450,7 +428,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task SendVideo(InputOnlineFile file, String caption = null, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default) + public async Task SendVideo(InputOnlineFile file, String caption = null, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown) { if (this.ActiveForm == null) return null; @@ -480,7 +458,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task SendVideo(String url, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default) + public async Task SendVideo(String url, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown) { if (this.ActiveForm == null) return null; @@ -719,11 +697,24 @@ namespace TelegramBotBase.Sessions return null; } + [Obsolete("User BanUser instead.")] public virtual async Task KickUser(long userId, DateTime until = default(DateTime)) { try { - await API(a => a.KickChatMemberAsync(this.DeviceId, userId, until)); + await API(a => a.BanChatMemberAsync(this.DeviceId, userId, until)); + } + catch + { + + } + } + + public virtual async Task BanUser(long userId, DateTime until = default(DateTime)) + { + try + { + await API(a => a.BanChatMemberAsync(this.DeviceId, userId, until)); } catch { @@ -751,7 +742,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public T RAW(Func call) + public T RAW(Func call) { return call(this.Client.TelegramClient); } @@ -762,7 +753,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task API(Func> call) + public async Task API(Func> call) { var numberOfTries = 0; while (numberOfTries < DeviceSession.MaxNumberOfRetries) @@ -776,8 +767,8 @@ namespace TelegramBotBase.Sessions if (ex.ErrorCode != 429) throw; - if (ex.Parameters != null) - await Task.Delay(ex.Parameters.RetryAfter * 1000); + if (ex.Parameters != null && ex.Parameters.RetryAfter != null) + await Task.Delay(ex.Parameters.RetryAfter.Value * 1000); numberOfTries++; } @@ -790,7 +781,7 @@ namespace TelegramBotBase.Sessions /// /// /// - public async Task API(Func call) + public async Task API(Func call) { var numberOfTries = 0; while (numberOfTries < DeviceSession.MaxNumberOfRetries) @@ -805,8 +796,8 @@ namespace TelegramBotBase.Sessions if (ex.ErrorCode != 429) throw; - if (ex.Parameters != null) - await Task.Delay(ex.Parameters.RetryAfter * 1000); + if (ex.Parameters != null && ex.Parameters.RetryAfter != null) + await Task.Delay(ex.Parameters.RetryAfter.Value * 1000); numberOfTries++; } diff --git a/TelegramBotBase/TelegramBotBase.csproj b/TelegramBotBase/TelegramBotBase.csproj index 0b31660..7d4eddc 100644 --- a/TelegramBotBase/TelegramBotBase.csproj +++ b/TelegramBotBase/TelegramBotBase.csproj @@ -1,13 +1,13 @@  - netstandard2.1;net472;net5;netcoreapp3.1 + netstandard2.0;net5;netcoreapp3.1;net6 false - false + False true https://github.com/MajMcCloud/TelegramBotFramework https://github.com/MajMcCloud/TelegramBotFramework - - moving from .Net Framework 4.7.2 to .Net Standard 2.1 for the Library and .Net Core 3.1 for the test project! + - Dependency update. Removing .Net Framework target and replacing with .Net Standard 2.0 Debug;Release; MIT false @@ -16,10 +16,14 @@ true true snupkg + $(VersionPrefix) + + + portable - + @@ -28,25 +32,14 @@ full false bin\Debug\ - DEBUG;TRACE + TRACE;DEBUG prompt 4 - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\TelegramBotBase.xml - - - - pdbonly + portable true bin\Release\ TRACE @@ -64,10 +57,8 @@ - - - - + + diff --git a/TelegramBotBase/Tools/Images.cs b/TelegramBotBase/Tools/Images.cs deleted file mode 100644 index e941884..0000000 --- a/TelegramBotBase/Tools/Images.cs +++ /dev/null @@ -1,22 +0,0 @@ -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/TelegramBotFramework.sln b/TelegramBotFramework.sln index f14d7d4..326160e 100644 --- a/TelegramBotFramework.sln +++ b/TelegramBotFramework.sln @@ -1,11 +1,11 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29324.140 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31912.275 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelegramBotBase", "TelegramBotBase\TelegramBotBase.csproj", "{0BD16FB9-7ED4-4CCB-83EB-5CEE538E1B6C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelegramBotBaseTest", "TelegramBotBaseTest\TelegramBotBaseTest.csproj", "{88EC0E02-583D-4B9D-956C-81D63C8CFCFA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelegramBotBaseTest", "TelegramBotBase.Test\TelegramBotBaseTest.csproj", "{88EC0E02-583D-4B9D-956C-81D63C8CFCFA}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3856B3FB-63E3-444A-9FF0-34171BE7AC5D}" ProjectSection(SolutionItems) = preProject @@ -18,6 +18,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemCommandsBot", "Exampl EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JoinHiderBot", "Examples\JoinHiderBot\JoinHiderBot.csproj", "{E804B9E5-7ACC-49D3-9253-806766C1D9A5}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelegramBotBase.Extensions.Images", "TelegramBotBase.Extensions.Images\TelegramBotBase.Extensions.Images.csproj", "{B5DDFA45-0E01-46A5-B67D-541300CDD606}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -40,6 +42,10 @@ Global {E804B9E5-7ACC-49D3-9253-806766C1D9A5}.Debug|Any CPU.Build.0 = Debug|Any CPU {E804B9E5-7ACC-49D3-9253-806766C1D9A5}.Release|Any CPU.ActiveCfg = Release|Any CPU {E804B9E5-7ACC-49D3-9253-806766C1D9A5}.Release|Any CPU.Build.0 = Release|Any CPU + {B5DDFA45-0E01-46A5-B67D-541300CDD606}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B5DDFA45-0E01-46A5-B67D-541300CDD606}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B5DDFA45-0E01-46A5-B67D-541300CDD606}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B5DDFA45-0E01-46A5-B67D-541300CDD606}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE