### Simplified Bot Builder Setup Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md The `QuickStart` method provides a streamlined way to initialize the bot with a starting form and API key. It simplifies the builder configuration for new projects or migrations. ```csharp var bot = BotBaseBuilder .Create() .QuickStart("{YOUR API KEY}") .Build(); await bot.Start(); ``` -------------------------------- ### Initialize TelegramBotBase with PostgreSQL Database Source: https://github.com/majmccloud/telegrambotframework/blob/master/TelegramBotBase.Extensions.Serializer.Database.PostgreSql/README.md Configure and start a Telegram bot using the PostgreSQL database extension. Ensure the necessary using directive is included. ```csharp using TelegramBotBase.Extensions.Serializer.Database.PostgreSQL; var bot = BotBaseBuilder .Create() .WithAPIKey(APIKey) .DefaultMessageLoop() .WithStartForm() .NoProxy() .OnlyStart() .UsePostgreSqlDatabase("localhost", "8181", "telegram_bot") .UseEnglish() .Build(); bot.Start(); ``` -------------------------------- ### Configure and Start a Bot with BotBaseBuilder Source: https://context7.com/majmccloud/telegrambotframework/llms.txt Use the fluent API to define bot settings, commands, and persistence. The builder supports both full configuration and a quick-start method for simple implementations. ```csharp using TelegramBotBase; using TelegramBotBase.Builder; using TelegramBotBase.Form; // Full configuration example var bot = BotBaseBuilder .Create() .WithAPIKey("YOUR_BOT_API_KEY") .DefaultMessageLoop() .WithStartForm() .NoProxy() .CustomCommands(commands => { commands.Start("Starts the bot"); commands.Add("help", "Shows help information"); commands.Add("settings", "Opens settings menu"); }) .UseJSON("config/states.json") // Enable session persistence .UseEnglish() .UseThreadPool() .Build(); // Handle bot commands globally bot.BotCommand += async (sender, e) => { switch (e.Command) { case "/help": await e.Device.ActiveForm.NavigateTo(new HelpForm()); break; case "/settings": await e.Device.ActiveForm.NavigateTo(new SettingsForm()); break; } }; // Upload commands to BotFather await bot.UploadBotCommands(); // Start receiving messages await bot.Start(); // Quick start for simple bots var simpleBot = BotBaseBuilder .Create() .QuickStart("YOUR_BOT_API_KEY") .Build(); await simpleBot.Start(); ``` -------------------------------- ### Initialize Bot with NewtonsoftJson Serialization Source: https://github.com/majmccloud/telegrambotframework/blob/master/TelegramBotBase.Extensions.Serializer.Legacy.NewtonsoftJson/README.md Demonstrates how to configure and build a TelegramBotBase instance using Newtonsoft.Json for session serialization. Ensure the TelegramBotBase.Extensions.Serializer.Legacy.NewtonsoftJson NuGet package is installed. ```csharp using TelegramBotBase.Extensions.Serializer.Legacy.NewtonsoftJson; var bot = BotBaseBuilder .Create() .WithAPIKey(APIKey) .DefaultMessageLoop() .WithStartForm() .NoProxy() .OnlyStart() .UseNewtonsoftJson() .UseEnglish() .Build(); bot.Start(); ``` -------------------------------- ### Create and Configure a Bot Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Use BotBaseBuilder to create a bot instance, configure its API key, message loop, starting form, commands, and other settings. Remember to keep your API key secure. ```csharp var bot = BotBaseBuilder .Create() .WithAPIKey("{YOUR API KEY}") // do not store your API key as plain text in project sources .DefaultMessageLoop() .WithStartForm() .NoProxy() .CustomCommands(a => { a.Start("Starts the bot"); }) .NoSerialization() .UseEnglish() .UseSingleThread() .Build(); // Upload bot commands to BotFather await bot.UploadBotCommands(); // Start your Bot await bot.Start(); ``` -------------------------------- ### Configure Bot with Custom Message Loop Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Integrate a custom message loop into your bot using the BotBaseBuilder. This example demonstrates how to set up a bot with a custom message loop and other configurations. ```csharp var bot = BotBaseBuilder .Create() .WithAPIKey("{YOUR API KEY}") .CustomMessageLoop(new CustomMessageLoop()) .WithStartForm() .NoProxy() .DefaultCommands() .NoSerialization() .UseEnglish() .UseThreadPool() .Build(); await bot.Start(); ``` -------------------------------- ### Action Manager Configuration Source: https://github.com/majmccloud/telegrambotframework/blob/master/TelegramBotBase.Extensions.ActionManager/Readme.md This snippet demonstrates how to configure the ExternalActionManager by adding various types of actions, including integer, GUID, and startsWith actions, along with their corresponding handlers. ```APIDOC ## Action Manager Configuration ### Description Configure the ExternalActionManager to handle specific callback data patterns and values. ### Method `ExternalActionManager.Configure()` ### Parameters - `a` (ActionManagerBuilder) - A builder object to add actions. ### Actions Added - `AddInt32Action(string method, Func handler)`: Handles integer values for a specific method. - `AddGuidAction(string method, Func handler)`: Handles GUID values for a specific method. - `AddStartsWithAction(string prefix, Func handler)`: Handles string values that start with a specific prefix. ### Request Example ```csharp var eam = ExternalActionManager.Configure(a => { // Handling all callback data values where method is "test" and value is a int32 a.AddInt32Action("test", async (value, cd, ur, mr) => { await mr.Device.Send($"This is a test action. Value is {value}"); }); // Handling all callback data values where method is "test2" and value is a guid a.AddGuidAction("test2", async (value, cd, ur, mr) => { await mr.Device.Send($"This is a test action. Value is {value}"); }); // Handle all inline values starting with "test3" a.AddStartsWithAction("test3", HandleStartsWith); }); ``` ``` -------------------------------- ### Configure Bot with JSON State Serialization Source: https://context7.com/majmccloud/telegrambotframework/llms.txt Build a bot that persists session state using JSON serialization. This example configures the bot to save states to a specified file and defines a form with attributes for automatic state saving. ```csharp using TelegramBotBase; using TelegramBotBase.Builder; using TelegramBotBase.Form; using TelegramBotBase.Attributes; using TelegramBotBase.Interfaces; using TelegramBotBase.Args; // Configure bot with JSON serialization var bot = BotBaseBuilder .Create() .WithAPIKey("YOUR_API_KEY") .DefaultMessageLoop() .WithStartForm() .NoProxy() .DefaultCommands() .UseJSON("data/states.json") // Or UseSimpleJSON, UseXML .UseEnglish() .UseSingleThread() .Build(); // Form with automatic state saving via attributes public class StatefulForm : FormBase { [SaveState] public int VisitCount { get; set; } [SaveState] public string UserName { get; set; } [SaveState] public DateTime LastVisit { get; set; } // This property won't be saved public string TempData { get; set; } public override async Task Load(MessageResult message) { VisitCount++; LastVisit = DateTime.Now; await Device.Send($"Welcome back {UserName}! Visit #{VisitCount}"); } } // Form that should not be serialized [IgnoreState] public class TemporaryForm : FormBase { // This form's state will never be saved } // Manual state handling via IStateForm interface public class ManualStateForm : FormBase, IStateForm { private Dictionary _customData = new(); public Task LoadState(LoadStateEventArgs e) { var savedData = e.Get("custom_data"); if (savedData != null) { _customData = JsonSerializer.Deserialize>(savedData); } return Task.CompletedTask; } public Task SaveState(SaveStateEventArgs e) { e.Set("custom_data", JsonSerializer.Serialize(_customData)); return Task.CompletedTask; } } ``` -------------------------------- ### Configure Middleware Message Loop Source: https://context7.com/majmccloud/telegrambotframework/llms.txt Set up a custom message processing pipeline using middleware. This example demonstrates filtering update types and adding logging and authentication middleware. ```csharp using TelegramBotBase; using TelegramBotBase.Builder; using TelegramBotBase.MessageLoops; using TelegramBotBase.MessageLoops.Extensions; using Telegram.Bot.Types.Enums; var bot = BotBaseBuilder .Create() .WithAPIKey("YOUR_API_KEY") .MiddlewareMessageLoop(loop => loop // Only process certain update types .UseValidUpdateTypes(UpdateType.Message, UpdateType.CallbackQuery) // Add logging middleware .Use(async (container, next) => { Console.WriteLine($ ``` -------------------------------- ### Sending Messages with Custom Buttons Source: https://github.com/majmccloud/telegrambotframework/blob/master/TelegramBotBase.Extensions.ActionManager/Readme.md This example demonstrates how to send a message with buttons that trigger custom actions defined in the Action Manager, using serialized CallbackData objects. ```APIDOC ## Sending Messages with Custom Buttons ### Description Send a message with buttons that trigger specific actions defined in the Action Manager. This involves creating `CallbackData` objects for actions that expect specific data types (int32, GUID) or using raw strings for `startsWith` actions. ### Method `bot.Client.TelegramClient.SendTextMessageAsync()` ### Parameters - `deviceId` (long) - The ID of the device (chat) to send the message to. - `text` (string) - The message text. - `replyMarkup` (object) - The message reply markup, typically a `ButtonForm` containing `ButtonBase` objects. ### Request Example ```csharp // Send message via Telegram Bot API directly long deviceId = 1; var bf = new ButtonForm(); // Create a serialized CallbackData object for an Int32 action var cd_int32 = Int32Action.GetCallback("test", 123); bf.AddButtonRow(new ButtonBase("1. Test", cd_int32)); // Create a serialized CallbackData object for a Guid action var cd_guid = GuidAction.GetCallback("test2", Guid.NewGuid()); bf.AddButtonRow(new ButtonBase("2. Test", cd_guid)); // Add a raw string value for a startsWith action bf.AddButtonRow(new ButtonBase("3. Test", "test3")); await bot.Client.TelegramClient.SendTextMessageAsync(deviceId, "This is an example message", replyMarkup: bf); ``` ``` -------------------------------- ### Build Bot with XML State Configuration Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Configures a bot using the BotBaseBuilder, specifying an API key, default message loop, start form, and an XML file for state management. Ensures English language support and single-threaded execution. ```csharp var bot = BotBaseBuilder .Create() .WithAPIKey("{YOUR API KEY}") .DefaultMessageLoop() .WithStartForm() .NoProxy() .CustomCommands(a => { a.Start("Starts the bot"); }) .UseXML(AppContext.BaseDirectory + "config\\states.xml") .UseEnglish() .UseSingleThread() .Build(); await bot.Start(); ``` -------------------------------- ### Implement Custom Message Loop Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Implement the IMessageLoopFactory interface to gain full control over update processing. This example shows a basic custom loop that handles loading events. ```csharp public class CustomMessageLoop : IMessageLoopFactory { public UpdateType[] ConfigureUpdateTypes() { return Update.AllTypes; } public async Task MessageLoop(BotBase bot, IDeviceSession session, UpdateResult ur, MessageResult mr) { var activeForm = session.ActiveForm; //Loading Event await activeForm.Load(mr); } } ``` -------------------------------- ### Configure Bot with MSSQL Database Source: https://github.com/majmccloud/telegrambotframework/blob/master/TelegramBotBase.Extensions.Serializer.Database.MSSQL/README.md Use this snippet to configure your Telegram bot to use MSSQL for data persistence. Ensure you have the necessary NuGet package installed. The `UseSQLDatabase` method requires connection details. ```csharp using TelegramBotBase.Extensions.Serializer.Database.MSSQL; var bot = BotBaseBuilder .Create() .WithAPIKey(APIKey) .DefaultMessageLoop() .WithStartForm() .NoProxy() .OnlyStart() .UseSQLDatabase("localhost", "telegram_bot") .UseEnglish() .Build(); bot.Start(); ``` -------------------------------- ### Initialize Bot with Action Manager Source: https://github.com/majmccloud/telegrambotframework/blob/master/TelegramBotBase.Extensions.ActionManager/Readme.md Integrates the configured Action Manager into the bot startup routine using the BotBaseBuilder. ```csharp //Add it into your bot startup routine var bot = BotBaseBuilder .Create() .WithAPIKey(Environment.GetEnvironmentVariable("API_KEY") ?? throw new Exception("API_KEY is not set")) .DefaultMessageLoop(eam) .WithStartForm() .NoProxy() .CustomCommands(a => { a.Start("Starts the bot"); }) .NoSerialization() .UseEnglish() .UseThreadPool() .Build(); await bot.Start(); ``` -------------------------------- ### Integrating Action Manager into Bot Startup Source: https://github.com/majmccloud/telegrambotframework/blob/master/TelegramBotBase.Extensions.ActionManager/Readme.md This snippet shows how to integrate the configured Action Manager into the bot's startup routine using the BotBaseBuilder. ```APIDOC ## Integrating Action Manager into Bot Startup ### Description Integrate the configured Action Manager into the bot's startup process to enable handling of custom actions. ### Method `BotBaseBuilder.DefaultMessageLoop()` ### Parameters - `eam` (ExternalActionManager) - The configured instance of the ExternalActionManager. ### Request Example ```csharp var bot = BotBaseBuilder .Create() .WithAPIKey(Environment.GetEnvironmentVariable("API_KEY") ?? throw new Exception("API_KEY is not set")) .DefaultMessageLoop(eam) // eam is the configured ExternalActionManager .WithStartForm() .NoProxy() .CustomCommands(a => { a.Start("Starts the bot"); }) .NoSerialization() .UseEnglish() .UseThreadPool() .Build(); await bot.Start(); ``` ``` -------------------------------- ### Initialize and Use NavigationController Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Initializes a NavigationController with a root form and replaces the current form context with the controller. It then pushes a new form onto the navigation stack. ```csharp var nc = new NavigationController(this); var f = new FormBase(); // Replace the current form in the context with the controller. await this.NavigateTo(nc); // Push the new from onto the stack to render it nc.PushAsync(f); ``` -------------------------------- ### Configure Bot Commands and Handlers Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Set up custom commands for your bot using BotFather and define their behavior within the BotBase. This includes handling navigation and parameter passing. ```csharp var bot = 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."); }) .NoSerialization() .UseEnglish() .UseSingleThread() .Build(); bot.BotCommand += async (s, en) => { switch (en.Command) { case "/form1": var form1 = new TestForm(); await en.Device.ActiveForm.NavigateTo(form1); break; case "/form2": var form2 = new TestForm2(); await en.Device.ActiveForm.NavigateTo(form2); break; case "/params": string m = en.Parameters.DefaultIfEmpty("").Aggregate((a, b) => a + " and " + b); await en.Device.Send("Your parameters are " + m, replyTo: en.Device.LastMessage); break; } }; await bot.UploadBotCommands() await bot.Start(); ``` -------------------------------- ### Configure Bot Threading Model Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Use the BotBaseBuilder to define the threading strategy during bot initialization. ```csharp var bot = BotBaseBuilder .Create() .WithAPIKey("{YOUR API KEY}") .DefaultMessageLoop() .WithStartForm() .NoProxy() .DefaultCommands() .NoSerialization() .UseEnglish() .UseThreadPool() // or .UseSingleThread() .Build(); ``` -------------------------------- ### Implement Progress Bar Control in C# Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Demonstrates creating a progress bar with various styles and managing its lifecycle within an AutoCleanForm. ```csharp public class ProgressTest : AutoCleanForm { public ProgressTest() { this.DeleteMode = eDeleteMode.OnLeavingForm; Opened += ProgressTest_Opened; } private async Task ProgressTest_Opened(object sender, EventArgs e) { await this.Device.Send("Welcome to ProgressTest"); } public override async Task Action(MessageResult message) { var call = message.GetData(); await message.ConfirmAction(); if (call == null) return; TelegramBotBase.Controls.ProgressBar Bar = null; switch (call.Value) { case "standard": Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.standard); Bar.Device = this.Device; break; case "squares": Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.squares); Bar.Device = this.Device; break; case "circles": Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.circles); Bar.Device = this.Device; break; case "lines": Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.lines); Bar.Device = this.Device; break; case "squaredlines": Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.squaredLines); Bar.Device = this.Device; break; case "start": var sf = new Start(); await sf.Init(); await this.NavigateTo(sf); return; default: return; } // Render Progress bar and show some "example" progress await Bar.Render(); this.Controls.Add(Bar); for (int i = 0; i <= 100; i++) { Bar.Value++; await Bar.Render(); Thread.Sleep(250); } } public override async Task Render(MessageResult message) { ButtonForm btn = new ButtonForm(); btn.AddButtonRow(new ButtonBase("Standard", new CallbackData("a", "standard").Serialize()), new ButtonBase("Squares", new CallbackData("a", "squares").Serialize())); btn.AddButtonRow(new ButtonBase("Circles", new CallbackData("a", "circles").Serialize()), new ButtonBase("Lines", new CallbackData("a", "lines").Serialize())); btn.AddButtonRow(new ButtonBase("Squared Line", new CallbackData("a", "squaredlines").Serialize())); btn.AddButtonRow(new ButtonBase("Back to start", new CallbackData("a", "start").Serialize())); await this.Device.Send("Choose your progress bar:", btn); } public override async Task Closed() { foreach (var b in this.Controls) { await b.Cleanup(); } await this.Device.Send("Ciao from ProgressTest"); } } ``` -------------------------------- ### Implement ConfirmDialog and AlertDialog Source: https://context7.com/majmccloud/telegrambotframework/llms.txt Use ConfirmDialog for multi-button user choices and AlertDialog for simple notifications. Both require event handling for button clicks to manage navigation or logic. ```csharp using TelegramBotBase.Form; using TelegramBotBase.Args; public class DeleteConfirmForm : FormBase { public override async Task Render(MessageResult message) { var confirm = new ConfirmDialog( "Are you sure you want to delete this item?", new ButtonBase("Yes, Delete", "delete"), new ButtonBase("Cancel", "cancel") ); confirm.ButtonClicked += async (sender, e) => { switch (e.Button.Value) { case "delete": await Device.Send("Item deleted successfully!"); await NavigateTo(new StartForm()); break; case "cancel": await Device.Send("Deletion cancelled."); await NavigateTo(new StartForm()); break; } }; await NavigateTo(confirm); } } // AlertDialog - Simple one-button alert public async Task ShowAlert() { var alert = new AlertDialog("Operation completed successfully!", "OK"); alert.ButtonClicked += async (s, e) => { await NavigateTo(new StartForm()); }; await NavigateTo(alert); } ``` -------------------------------- ### Sending Messages and Media with DeviceSession Source: https://context7.com/majmccloud/telegrambotframework/llms.txt Demonstrates how to use DeviceSession methods within a FormBase implementation to handle various Telegram bot commands. ```csharp using TelegramBotBase.Form; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; public class MediaForm : FormBase { public override async Task Load(MessageResult message) { switch (message.Command) { case "text": // Simple text message await Device.Send("Hello World!"); // With markdown formatting await Device.Send("*Bold* _italic_ `code`", parseMode: ParseMode.Markdown); // Reply to user's message await Device.Send("This is a reply!", replyTo: message.MessageId); break; case "photo": // Send photo from URL var photoUrl = InputFile.FromUri("https://example.com/image.jpg"); await Device.SendPhoto(photoUrl, caption: "Check out this image!"); // Send photo from file var photoFile = InputFile.FromStream( new FileStream("photo.jpg", FileMode.Open), "photo.jpg" ); await Device.SendPhoto(photoFile); break; case "video": // Send video from URL await Device.SendVideo("https://example.com/video.mp4"); // Send video from bytes byte[] videoBytes = File.ReadAllBytes("video.mp4"); await Device.SendVideo("video.mp4", videoBytes); // Send local video file await Device.SendLocalVideo("path/to/video.mp4"); break; case "document": // Send document from bytes byte[] pdfBytes = File.ReadAllBytes("document.pdf"); await Device.SendDocument("report.pdf", pdfBytes, caption: "Here's your report"); // Generate and send text file await Device.SendTextFile( "data.txt", "Line 1\nLine 2\nLine 3", Encoding.UTF8, caption: "Generated text file" ); break; case "action": // Show typing indicator await Device.SetAction(ChatAction.Typing); await Task.Delay(2000); await Device.Send("Done typing!"); // Show upload indicator await Device.SetAction(ChatAction.UploadDocument); break; case "edit": // Send and edit message var msg = await Device.Send("Original message"); await Task.Delay(2000); await Device.Edit(msg.MessageId, "Edited message!"); break; case "delete": var toDelete = await Device.Send("This will be deleted in 3 seconds..."); await Task.Delay(3000); await Device.DeleteMessage(toDelete.MessageId); break; case "contact": // Request user's contact await Device.RequestContact("Share Contact", "Please share your contact"); break; case "location": // Request user's location await Device.RequestLocation("Share Location", "Please share your location"); break; } } } ``` -------------------------------- ### Implement Bot Forms with FormBase Source: https://context7.com/majmccloud/telegrambotframework/llms.txt Extend FormBase to define custom bot screens. Override lifecycle methods like Load, Action, and Render to handle messages, button callbacks, and UI updates. ```csharp using TelegramBotBase.Base; using TelegramBotBase.Form; public class StartForm : FormBase { public StartForm() { Init += StartForm_Init; Opened += StartForm_Opened; Closed += StartForm_Closed; } private async Task StartForm_Init(object sender, InitEventArgs e) { // Called once during initialization } private async Task StartForm_Opened(object sender, EventArgs e) { await Device.Send("Welcome! Choose an option:"); } private async Task StartForm_Closed(object sender, EventArgs e) { // Cleanup when leaving form } public override async Task Load(MessageResult message) { // Handle incoming text messages switch (message.Command) { case "hello": await Device.Send("Hello there!"); break; case "help": await Device.Send("Available commands: hello, settings, back"); break; } } public override async Task Action(MessageResult message) { // Handle button clicks var call = message.GetData(); if (call == null) return; await message.ConfirmAction(); switch (call.Value) { case "settings": var settingsForm = new SettingsForm(); await NavigateTo(settingsForm); break; case "profile": var profileForm = new ProfileForm(); await NavigateTo(profileForm); break; } } public override async Task Render(MessageResult message) { // Render buttons after processing var buttons = new ButtonForm(); buttons.AddButtonRow( new ButtonBase("Settings", new CallbackData("a", "settings").Serialize()), new ButtonBase("Profile", new CallbackData("a", "profile").Serialize()) ); buttons.AddButtonRow( new ButtonBase("Visit Website", "web", "https://example.com") ); await Device.Send("Main Menu", buttons); } public override async Task SentData(DataResult data) { // Handle uploaded files, photos, contacts, location if (data.Type == MessageType.Photo) { await Device.Send("Thanks for the photo!"); } } } ``` -------------------------------- ### Available Middleware Options Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md A list of available extension methods for composing message processing pipelines. ```APIDOC ## Available Middleware Options You can compose your own message processing pipeline using the following extension methods: - `.Use(Func, Task> middleware)`: Add a custom middleware delegate to the pipeline. - `.UseValidUpdateTypes(params UpdateType[])`: Only continue the pipeline for specific `UpdateType`s. - `.UseBotCommands()`: Handles bot commands and triggers the `OnBotCommand` event if a known command is received. - `.UseForms([IExternalActionManager])`: Handles all form events (PreLoad, LoadControls, Load, Action, SentData, Render, etc.). Optionally with external action manager. - `.UsePreLoad()`: Calls only the `PreLoad` event of the active form. - `.UseLoad()`: Calls `LoadControls` and `Load` events of the active form. - `.UseAttachments(params MessageType[])`: Handles only specific attachment types (Photo, Audio, Video, Contact, Location, Document). - `.UseAllAttachments()`: Handles all supported attachment types. - `.UseActions()`: Handles only action events (e.g., button clicks). - `.UseRender()`: Calls the `RenderControls` and `Render` events of the active form. - `.UseActionManager(IExternalActionManager)`: Integrates an external action manager for unhandled actions. You can chain these methods to build exactly the message processing pipeline you need. For custom logic, use `.Use(...)` and insert your own delegate. All extension methods are defined in [`TelegramBotBase.MessageLoops.Extensions.MiddlewareBaseMessageLoopExtensions`](TelegramBotBase/MessageLoops/Extensions/MiddlewareBaseMessageLoopExtensions.cs). ``` -------------------------------- ### Navigate to a New Form Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Navigates to a new form instance. This is the basic method for moving between different states or views within the bot. ```csharp var f = new FormBase(); await this.NavigateTo(f); ``` -------------------------------- ### Send Message with Action Buttons Source: https://github.com/majmccloud/telegrambotframework/blob/master/TelegramBotBase.Extensions.ActionManager/Readme.md Demonstrates how to create a button form with serialized callback data and send it via the Telegram Bot API. ```csharp //Send message via Telegram Bot API directly long deviceId = 1; var bf = new ButtonForm(); //Create a serialized CallbackData object var cd_int32 = Int32Action.GetCallback("test", 123); bf.AddButtonRow(new ButtonBase("1. Test", cd_int32)); //Create a serialized CallbackData object var cd_guid = GuidAction.GetCallback("test2", Guid.NewGuid()); bf.AddButtonRow(new ButtonBase("2. Test", cd_guid)); //Add the raw string value bf.AddButtonRow(new ButtonBase("3. Test", "test3")); await bot.Client.TelegramClient.SendTextMessageAsync(deviceId, "This is an example message", replyMarkup: bf); ``` -------------------------------- ### Handle Bot Commands Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Enable bot command handling by adding the `.UseBotCommands()` middleware. This triggers the `OnBotCommand` event for recognized commands. ```csharp .UseBotCommands() ``` -------------------------------- ### Handle Text Messages in a Simple Form Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Implement a form that responds to specific text messages. The `Load` method processes incoming messages and triggers predefined actions. ```csharp public class SimpleForm : AutoCleanForm { public SimpleForm() { DeleteSide = EDeleteSide.Both; DeleteMode = EDeleteMode.OnLeavingForm; Opened += SimpleForm_Opened; } private async Task SimpleForm_Opened(object sender, EventArgs e) { await Device.Send("Hello world! (send 'back' to get back to Start)\\r\\nOr\\r\\nhi, hello, maybe, bye and ciao"); } public override async Task Load(MessageResult message) { // message.MessageText will work also, cause it is a string you could manage a lot different scenerios here var messageId = message.MessageId; switch (message.Command) { case "hello": case "hi": // Send a simple message await this.Device.Send("Hello you there !"); break; case "maybe": // Send a simple message and reply to the one of himself await this.Device.Send("Maybe what?", replyTo: messageId); break; case "bye": case "ciao": // Send a simple message await this.Device.Send("Ok, take care !"); break; } } } ``` -------------------------------- ### Define a Bot Form Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Create a custom form by subclassing FormBase. Implement event handlers for initialization, opening, closing, and message loading. The Load method handles incoming messages. ```csharp public class Start : FormBase { public Start() { //Additional event handlers Init += Start_Init; Opened += Start_Opened; Closed += Start_Closed; } // Gets invoked on initialization, before navigation private async Task Start_Init(object sender, Args.InitEventArgs e) { } // Gets invoked after opened private async Task Start_Opened(object sender, EventArgs e) { } // Gets invoked after form has been closed private async Task Start_Closed(object sender, EventArgs e) { } // Gets invoked during Navigation to this form public override async Task PreLoad(MessageResult message) { } // Gets invoked on every Message/Action/Data in this context public override async Task Load(MessageResult message) { // `Device` is a wrapper for current chat - you can easily respond to the user await this.Device.Send("Hello world!"); } // Gets invoked on edited messages public override async Task Edited(MessageResult message) { } // Gets invoked on Button clicks public override async Task Action(MessageResult message) { } // Gets invoked on Data uploades by the user (of type Photo, Audio, Video, Contact, Location, Document) public override async Task SentData(DataResult data) { } //Gets invoked on every Message/Action/Data to render Design or Response public override async Task Render(MessageResult message) { } } ``` -------------------------------- ### Configure SimpleJSONStateMachine Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Use SimpleJSONStateMachine for basic data types. It is not suitable for complex types or generics. ```csharp var bot = BotBaseBuilder .Create() .WithAPIKey("{YOUR API KEY}") .DefaultMessageLoop() .WithStartForm() .NoProxy() .CustomCommands(a => { a.Start("Starts the bot"); }) .UseSimpleJSON(AppContext.BaseDirectory + "config\\states.json") .UseEnglish() .UseSingleThread() .Build(); await bot.Start(); ``` -------------------------------- ### Implement Alert Dialog in C# Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Displays a simple message dialog with an 'Ok' button. Navigates to a new form upon button click. ```csharp AlertDialog ad = new AlertDialog("This is a message", "Ok"); ad.ButtonClicked += async (s, en) => { var fto = new TestForm2(); await this.NavigateTo(fto); }; await this.NavigateTo(ad); ``` -------------------------------- ### Implement a multi-step registration form in C# Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Inherit from AutoCleanForm to manage stateful user input across multiple messages. Requires overriding Load, Action, and Render methods to handle data collection and navigation. ```csharp public class PerForm : AutoCleanForm { public string EMail { get; set; } public string Firstname { get; set; } public string Lastname { get; set; } public async override Task Load(MessageResult message) { if (string.IsNullOrWhiteSpace(message.MessageText)) return; if (this.Firstname == null) { this.Firstname = message.MessageText; return; } if (this.Lastname == null) { this.Lastname = message.MessageText; return; } if (this.EMail == null) { this.EMail = message.MessageText; return; } } public async override Task Action(MessageResult message) { var call = message.GetData(); await message.ConfirmAction(); if (call == null) return; switch (call.Value) { case "back": var start = new Start(); await this.NavigateTo(start); break; } } public async override Task Render(MessageResult message) { if (this.Firstname == null) { await this.Device.Send("Please sent your firstname:"); return; } if (this.Lastname == null) { await this.Device.Send("Please sent your lastname:"); return; } if (this.EMail == null) { await this.Device.Send("Please sent your email address:"); return; } string s = ""; s += "Firstname: " + this.Firstname + "\r\n"; s += "Lastname: " + this.Lastname + "\r\n"; s += "E-Mail: " + this.EMail + "\r\n"; ButtonForm bf = new ButtonForm(); bf.AddButtonRow(new ButtonBase("Back", new CallbackData("a", "back").Serialize())); await this.Device.Send("Your details:\r\n" + s, bf); } } ``` -------------------------------- ### Implement Stack-Based Navigation with NavigationController Source: https://context7.com/majmccloud/telegrambotframework/llms.txt Use NavigationController to manage a stack of forms for push/pop navigation. Initialize it with the current form as the root and then push new forms onto the stack. ```csharp using TelegramBotBase.Form; using TelegramBotBase.Form.Navigation; public class TeamListForm : FormBase { public override async Task Action(MessageResult message) { var call = message.GetData(); if (call == null) return; if (call.Value == "view_team") { // Create navigation controller with current form as root var navController = new NavigationController(this); // Replace current form with controller await NavigateTo(navController); // Push team details form var teamDetails = new TeamDetailsForm(); await navController.PushAsync(teamDetails); } } } public class TeamDetailsForm : FormBase { public override async Task Action(MessageResult message) { var call = message.GetData(); if (call == null) return; switch (call.Value) { case "view_players": // Push another form onto stack var playersForm = new PlayersListForm(); await NavigationController.PushAsync(playersForm); break; case "back": // Pop current form, go back to previous await NavigationController.PopAsync(); break; case "home": // Pop all forms back to root await NavigationController.PopToRootAsync(); break; } } public override async Task Render(MessageResult message) { var bf = new ButtonForm(); bf.AddButtonRow(new ButtonBase("View Players", new CallbackData("a", "view_players").Serialize())); bf.AddButtonRow(new ButtonBase("Back", new CallbackData("a", "back").Serialize())); bf.AddButtonRow(new ButtonBase("Home", new CallbackData("a", "home").Serialize())); await Device.Send("Team Details", bf); } } ``` -------------------------------- ### Navigate to a Different Form Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md To navigate to another form, create an instance of the desired form and use the `NavigateTo` method, passing the form instance as an argument. ```csharp var form = new TestForm(); await this.NavigateTo(form); ``` -------------------------------- ### Implement Prompt Dialog in C# Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Requests user input via a prompt dialog. The input value is accessed via the dialog's Value property after completion. ```csharp PromptDialog pd = new PromptDialog("Please tell me your name ?"); pd.Completed += async (s, en) => { await this.Device.Send("Hello " + pd.Value); }; await this.OpenModal(pd); ``` -------------------------------- ### FullMessageLoop Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md The most comprehensive message loop, reacting to all update types and triggering all relevant events. Usually only needed for special cases. ```APIDOC ## FullMessageLoop The most comprehensive message loop. Reacts to all update types and triggers all relevant events. Usually only needed for special cases where every type of update should be handled individually. ``` -------------------------------- ### Creating a Custom Message Loop Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Implement your own message loop by creating a class that implements the `IMessageLoopFactory` interface for full control over update processing. ```APIDOC ## Creating a Custom Message Loop If you need full control over how updates are processed, you can implement your own message loop by creating a class that implements the `IMessageLoopFactory` interface. **Example:** ```csharp public class CustomMessageLoop : IMessageLoopFactory { public UpdateType[] ConfigureUpdateTypes() { return Update.AllTypes; } public async Task MessageLoop(BotBase bot, IDeviceSession session, UpdateResult ur, MessageResult mr) { var activeForm = session.ActiveForm; //Loading Event await activeForm.Load(mr); } } ``` **Usage:** ```csharp var bot = BotBaseBuilder .Create() .WithAPIKey("{YOUR API KEY}") .CustomMessageLoop(new CustomMessageLoop()) .WithStartForm() .NoProxy() .DefaultCommands() .NoSerialization() .UseEnglish() .UseThreadPool() .Build(); await bot.Start(); ``` **Note:** The choice of message loop depends on the desired feature set and the complexity of your bot. For most applications, `FormBaseMessageLoop` or the middleware approach is recommended. For more details and examples, see the [Examples](#examples) section. ``` -------------------------------- ### Send a Message from a Form Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Within a form's context, use the `Device.Send` method to send messages to the user. This is typically done within the `Load` method. ```csharp await this.Device.Send("Hello world!"); ``` -------------------------------- ### Add Custom Middleware Delegate Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Use the `.Use()` extension method to insert a custom middleware delegate into the message processing pipeline for custom logic. ```csharp .Use(Func, Task> middleware) ``` -------------------------------- ### Integrate External Action Manager Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Integrate an external action manager for handling unhandled actions by using the `.UseActionManager()` middleware with an `IExternalActionManager` instance. ```csharp .UseActionManager(IExternalActionManager) ``` -------------------------------- ### Create Text Input Dialogs with PromptDialog Source: https://context7.com/majmccloud/telegrambotframework/llms.txt PromptDialog creates a modal dialog for text input. It returns the user's response via a Completed event. Supports chaining prompts and showing a back button. ```csharp using TelegramBotBase.Form; public class RegistrationForm : FormBase { private string _userName; private string _email; public override async Task Render(MessageResult message) { // Prompt for username var namePrompt = new PromptDialog("Please enter your username:"); namePrompt.Completed += async (s, e) => { _userName = e.Value; // Chain another prompt for email var emailPrompt = new PromptDialog("Now enter your email address:"); emailPrompt.ShowBackButton = true; // Show back option emailPrompt.Completed += async (s2, e2) => { _email = e2.Value; await Device.Send($"Registration complete!\nUsername: {_userName}\nEmail: {_email}"); }; await OpenModal(emailPrompt); }; await OpenModal(namePrompt); } } // Using PromptDialog with tag for context public override async Task Action(MessageResult message) { var call = message.GetData(); if (call?.Value == "edit_name") { var prompt = new PromptDialog("Enter new name:"); prompt.Tag = "name_edit"; // Store context prompt.Completed += async (s, e) => { await Device.Send($"Name updated to: {e.Value}"); }; await OpenModal(prompt); } } ``` -------------------------------- ### Configure ExternalActionManager Source: https://github.com/majmccloud/telegrambotframework/blob/master/TelegramBotBase.Extensions.ActionManager/Readme.md Registers various action handlers for callback data patterns using the ExternalActionManager configuration builder. ```csharp var eam = ExternalActionManager.Configure(a => { //Handling all callback data values where method is "test" and value is a int32 //You need to use a serialized CallbackData object for this a.AddInt32Action("test", async (value, cd, ur, mr) => { await mr.Device.Send($"This is a test action. Value is {value}"); }); //Handling all callback data values where method is "test2" and value is a guid //You need to use a serialized CallbackData object for this a.AddGuidAction("test2", async (value, cd, ur, mr) => { await mr.Device.Send($"This is a test action. Value is {value}"); }); //Handle all inline values starting with "test3" //No need to use a serialized CallbackData object for this a.AddStartsWithAction("test3", HandleStartsWith); }); ``` -------------------------------- ### Implement Confirm Dialog in C# Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Presents a confirmation dialog with custom buttons. Ensure navigation is performed from the current active form context. ```csharp ConfirmDialog cd = new ConfirmDialog("Please confirm", new ButtonBase("Ok", "ok"), new ButtonBase("Cancel", "cancel")); cd.ButtonClicked += async (s, en) => { var tf = new TestForm2(); // Remember only to navigate from the current running form. (here it is the prompt dialog, cause we have left the above already) await cd.NavigateTo(tf); }; await this.NavigateTo(cd); ``` -------------------------------- ### Implement CalendarPicker for Date Selection Source: https://context7.com/majmccloud/telegrambotframework/llms.txt Use CalendarPicker to provide an interactive calendar for users to select dates. Configure culture, first day of week, and view modes (day, month, year). ```csharp using TelegramBotBase.Controls.Inline; using TelegramBotBase.Form; using System.Globalization; public class DatePickerForm : AutoCleanForm { private CalendarPicker _calendar; public DatePickerForm() { Init += DatePickerForm_Init; } private Task DatePickerForm_Init(object sender, InitEventArgs e) { _calendar = new CalendarPicker(new CultureInfo("en-US")) { Title = "Select a date:", SelectedDate = DateTime.Today, FirstDayOfWeek = DayOfWeek.Monday, EnableDayView = true, EnableMonthView = true, EnableYearView = true }; AddControl(_calendar); return Task.CompletedTask; } public override async Task Action(MessageResult message) { await base.Action(message); var call = message.GetData(); if (call?.Value == "confirm") { await Device.Send($"Selected date: {_calendar.SelectedDate:yyyy-MM-dd}"); await NavigateTo(new StartForm()); } } public override async Task Render(MessageResult message) { var bf = new ButtonForm(); bf.AddButtonRow( new ButtonBase("Confirm Selection", new CallbackData("a", "confirm").Serialize()) ); await Device.Send("Choose your date above, then confirm:", bf); } } ``` -------------------------------- ### Implement IStateMachine Interface Source: https://github.com/majmccloud/telegrambotframework/blob/master/README.md Defines the IStateMachine interface for custom state management. Requires implementation of SaveFormStates for saving and LoadFormStates for loading form states, typically involving custom serialization logic. ```csharp public interface IStateMachine { void SaveFormStates(SaveStatesEventArgs e); StateContainer LoadFormStates(); } ```