### Example Telegram Bot Token Format Source: https://github.com/telegrambots/book/blob/master/src/1/quickstart.md This snippet shows the typical format of a Telegram bot token, which is a unique key required for authenticating and sending requests to the Bot API. It's crucial to keep this token secure. ```text 1234567:4TT8bAc8GHUspu3ERYn-KGcvsvGB9u_n4ddy ``` -------------------------------- ### Complete Telegram Bot with Message, Update, and Error Handling (C#) Source: https://github.com/telegrambots/book/blob/master/src/1/full-bot.md This C# code demonstrates how to create a more complete Telegram bot using the `Telegram.Bot` library. It initializes the bot, sets up handlers for incoming messages (`OnMessage`), various updates (`OnUpdate`), and errors (`OnError`). The example shows how to respond to a `/start` command with inline keyboard buttons and handle button clicks (CallbackQuery) by answering the query and sending a new message. It also includes basic error logging for polling and handler exceptions. ```C# using Telegram.Bot; using Telegram.Bot.Polling; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; using Telegram.Bot.Types.ReplyMarkups; using var cts = new CancellationTokenSource(); var bot = new TelegramBotClient("YOUR_BOT_TOKEN", cancellationToken: cts.Token); var me = await bot.GetMe(); bot.OnError += OnError; bot.OnMessage += OnMessage; bot.OnUpdate += OnUpdate; Console.WriteLine($"@{me.Username} is running... Press Enter to terminate"); Console.ReadLine(); cts.Cancel(); // stop the bot // method to handle errors in polling or in your OnMessage/OnUpdate code async Task OnError(Exception exception, HandleErrorSource source) { Console.WriteLine(exception); // just dump the exception to the console } // method that handle messages received by the bot: async Task OnMessage(Message msg, UpdateType type) { if (msg.Text == "/start") { await bot.SendMessage(msg.Chat, "Welcome! Pick one direction", replyMarkup: new InlineKeyboardButton[] { "Left", "Right" }); } } // method that handle other types of updates received by the bot: async Task OnUpdate(Update update) { if (update is { CallbackQuery: { } query }) // non-null CallbackQuery { await bot.AnswerCallbackQuery(query.Id, $"You picked {query.Data}"); await bot.SendMessage(query.Message!.Chat, $"User {query.From} clicked on {query.Data}"); } } ``` -------------------------------- ### Initializing ReplyKeyboardMarkup with Optional Properties in C# Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-17.x.md Illustrates how to configure optional properties like `ResizeKeyboard` for `ReplyKeyboardMarkup` using C# object initialization syntax, as these properties were removed from the constructor. ```csharp var replyKeyboardMarkup = new ReplyKeyboardMarkup( new KeyboardButton[][] { new KeyboardButton[] { "1.1", "1.2" }, new KeyboardButton[] { "2.1", "2.2" }, }) { ResizeKeyboard = true }; ``` -------------------------------- ### Configure TelegramBotClient with Options (C#) Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-18.x.md Starting with Telegram.Bot v18.0, client configuration parameters should be passed through the `TelegramBotClientOptions` class. This allows for advanced settings such as specifying a custom base URL for a bot server or enabling the test environment. ```C# using Telegram.Bot; var options = new TelegramBotClientOptions( token: "" // pass an optional baseUrl if you want to use a custom bot server baseUrl: "https://custombotserverdomain.com", // pass an optional flag `true` if you want to use test environment useTestEnvironment = true ); var client = new TelegramBotClient(options); ``` -------------------------------- ### Run .NET Bot Application and View Output Source: https://github.com/telegrambots/book/blob/master/src/1/quickstart.md This command executes the compiled .NET bot application. The output demonstrates the bot successfully fetching and displaying its own information, confirming its self-awareness and connection to the Telegram API. ```bash dotnet run Hello, World! I am user 1234567 and my name is Awesome Bot. ``` -------------------------------- ### Install mdBook using Cargo Source: https://github.com/telegrambots/book/blob/master/README.md Command to install the mdBook static site generator using Rust's cargo package manager. This requires Rust to be installed on the system. ```bash cargo install mdbook --vers "^0.4.28" ``` -------------------------------- ### Set Up .NET Console Project for Telegram Bot Source: https://github.com/telegrambots/book/blob/master/src/1/quickstart.md These commands initialize a new .NET console application and add the `Telegram.Bot` NuGet package, which is necessary for interacting with the Telegram Bot API. This prepares the project environment for bot development. ```bash dotnet new console dotnet add package Telegram.Bot ``` -------------------------------- ### C# Dynamic Inline Keyboard Markup Construction Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-21.x.md New helper and extension methods simplify the dynamic creation of InlineKeyboardMarkup and ReplyKeyboardMarkup objects. This example demonstrates a fluent API for adding buttons and new rows, enabling developers to build complex interactive keyboards with concise code. ```csharp var replyMarkup = new InlineKeyboardMarkup() .AddButton(InlineKeyboardButton.WithUrl("Link to Repository", "https://github.com/TelegramBots/Telegram.Bot")) .AddNewRow().AddButton("callback").AddButton("caption", "data") .AddNewRow("with", "three", "buttons") .AddNewRow().AddButtons("A", "B", InlineKeyboardButton.WithSwitchInlineQueryCurrentChat("switch")); ``` -------------------------------- ### Run Telegram Bot Application (Bash) Source: https://github.com/telegrambots/book/blob/master/src/1/example-bot.md This command executes the compiled C# Telegram bot application from the command line, starting its operation and message polling. ```bash dotnet run ``` -------------------------------- ### Fetch Telegram Bot Information in C# Source: https://github.com/telegrambots/book/blob/master/src/1/quickstart.md This C# code snippet demonstrates how to initialize a `TelegramBotClient` with your bot token and then use the `GetMe` method to retrieve basic information about the bot, such as its ID and first name. It prints a greeting message to the console. ```c# using Telegram.Bot; var bot = new TelegramBotClient("YOUR_BOT_TOKEN"); var me = await bot.GetMe(); Console.WriteLine($"Hello, World! I am user {me.Id} and my name is {me.FirstName}."); ``` -------------------------------- ### Example Console Output for Received Message Source: https://github.com/telegrambots/book/blob/master/src/1/example-bot.md This snippet shows an example of the console output when the bot receives a text message, indicating the message content, update type, and chat information including the user's ID. ```text Received Message 'test' in Private chat with @You (123456789). ``` -------------------------------- ### C# Example: Using Simplified Constructors and Conversions Source: https://github.com/telegrambots/book/blob/master/src/3/helpers.md Demonstrates practical usage of simplified constructors and implicit conversions for various API calls like restricting chat members, setting reactions, sending messages, invoices, commands, photos, and videos. ```csharp await bot.RestrictChatMember(chatId, userId, new ChatPermissions(true)); // unmute await bot.SetMessageReaction(msg.Chat, msg.Id, ["👍"]); await bot.SendMessage(msg.Chat, "Visit t.me/tgbots_dotnet", replyParameters: msg, linkPreviewOptions: true); await bot.SendInvoice(chatId, "Product", "Description", "ProductID", "XTR", [("Price", 500)]); await Bot.SetMyCommands([("/start", "Start the bot"), ("/privacy", "Privacy policy")], BotCommandScope.AllPrivateChats()); await bot.SendPhoto(msg.Chat, "https://picsum.photos/310/200.jpg"); await bot.SendVideo(msg.Chat, msg.Video, "Sending your video back"); ``` -------------------------------- ### C# Example: Constructing Reply Markups Source: https://github.com/telegrambots/book/blob/master/src/3/helpers.md Illustrates how to construct different types of reply markups, including inline URL buttons, callback buttons, and standard keyboard text buttons, by directly passing various object types. ```csharp await bot.SendMessage(msg.Chat, "Visit our website", replyMarkup: InlineKeyboardButton.WithUrl("Click here", "https://telegrambots.github.io/book/")); await bot.SendMessage(botOwnerId, $"Annoying user: {msg.From}", replyMarkup: new InlineKeyboardButton[] { ("Ban him", $"BAN {msg.From.Id}"), ("Mute him", $"MUTE {msg.From.Id}") }); await bot.SendMessage(msg.Chat, "Keyboard buttons:", replyMarkup: new string[] { "MENU", "INFO", "LANGUAGE" }); ``` -------------------------------- ### Full Telegram Stars Transaction Flow Example in C# Source: https://github.com/telegrambots/book/blob/master/src/4/payments.md This comprehensive C# example illustrates a complete Telegram Stars payment transaction. It covers sending an invoice, validating `PreCheckoutQuery` details, and processing `SuccessfulPayment` messages by logging transaction IDs and confirming feature unlocks. ```csharp using Telegram.Bot; using Telegram.Bot.Types; var bot = new TelegramBotClient("YOUR_BOT_TOKEN"); bot.OnUpdate += OnUpdate; Console.ReadKey(); async Task OnUpdate(Update update) { switch (update) { case { Message.Text: "/start" }: await bot.SendInvoice(update.Message.Chat, "Unlock feature X", "Will give you access to feature X of this bot", "unlock_X", "XTR", [("Price", 200)], photoUrl: "https://cdn-icons-png.flaticon.com/512/891/891386.png"); break; case { PreCheckoutQuery: { } preCheckoutQuery }: if (preCheckoutQuery is { InvoicePayload: "unlock_X", Currency: "XTR", TotalAmount: 200 }) await bot.AnswerPreCheckoutQuery(preCheckoutQuery.Id); // success else await bot.AnswerPreCheckoutQuery(preCheckoutQuery.Id, "Invalid order"); break; case { Message.SuccessfulPayment: { } successfulPayment }: System.IO.File.AppendAllText("payments.log", $"{DateTime.Now}: " + $"User {update.Message.From} paid for {successfulPayment.InvoicePayload}: " + $"{successfulPayment.TelegramPaymentChargeId} {successfulPayment.ProviderPaymentChargeId}\n"); if (successfulPayment.InvoicePayload is "unlock_X") await bot.SendMessage(update.Message.Chat, "Thank you! Feature X is unlocked"); break; }; } ``` -------------------------------- ### Set Telegram Bot Commands with Tuple Syntax (C#) Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md Demonstrates how to set custom commands for a Telegram bot using the new tuple-based implicit constructor for BotCommand objects, simplifying command registration in C#. ```C# await Bot.SetMyCommands([("/start", "Start the bot"), ("/privacy", "Privacy policy")]); ``` -------------------------------- ### C# Telegram Bot: Get File Info and Download with Single Call Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-14.x.md This snippet demonstrates using GetInfoAndDownloadFileAsync() to retrieve file information and download the file in a single operation. This method is similar to the old GetFileAsync() and performs two HTTP requests internally to achieve the download. ```csharp using (var fileStream = System.IO.File.OpenWrite("path/to/file.pdf")) { File fileInfo = await bot.GetInfoAndDownloadFileAsync( fileId: "BsdfgLg4Khdlsn-bldBD", destination: fileStream ); } ``` -------------------------------- ### Configure TelegramBotClient with Token Only (C#) Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-18.x.md For simpler use cases where no custom configuration options are needed, the `TelegramBotClient` can still be initialized directly with just the bot token. This constructor provides a straightforward way to create a client instance. ```C# var client = new TelegramBotClient(""); ``` -------------------------------- ### Webhook Configuration: Migrating to System.Text.Json Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-21.x.md The Telegram.Bot library now uses `System.Text.Json` instead of `NewtonsoftJson` for webhook processing. For ASP.NET projects, you must remove the `Microsoft.AspNetCore.Mvc.NewtonsoftJson` package and follow the updated webhook configuration guide. Special considerations apply for .NET 6+ Docker deployments. ```C# // 1. Remove NewtonsoftJson package from your project dependencies // In your .csproj file or via NuGet Package Manager: // // Remove this line. // 2. Configure your web app for System.Text.Json (refer to official webhook guide) // In your Startup.cs or Program.cs (for .NET 6+ Minimal APIs): // services.AddControllers() // .AddJsonOptions(options => // { // options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; // options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); // // Add other System.Text.Json options as needed // }); // For .NET 6+ Docker builds, refer to GitHub issue #1432 for Dockerfile updates. ``` -------------------------------- ### Populate Bot Menu Commands Source: https://github.com/telegrambots/book/blob/master/src/FAQ.md Describes two methods to populate the bot's menu button or commands list: using @BotFather for static entries or `SetMyCommands` for dynamic and advanced settings. Notes that commands must start with `/` and contain only latin characters. ```APIDOC Method: SetMyCommands Description: Used for advanced and dynamic population of the bot's command list. Constraints: Commands must start with '/' and contain only latin characters (a-z_0-9). ``` -------------------------------- ### Handling Telegram.Bot Exceptions in C# Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-17.x.md This C# example demonstrates the new exception handling logic in Telegram.Bot v17. It shows how to catch ApiRequestException for specific Bot API errors (e.g., 400, 401, 403, 429) and RequestException for other issues like connection problems (HttpRequestException) or serialization errors (JsonSerializationException), as well as OperationCancelledException. ```csharp try { await bot.SendTextMessageAsync(chatId, "Hello"); } catch (ApiRequestException exception) { switch (exception.StatusCode) { case 400: // Handle incorrect requests exceptions break; case 401: // Handle incorrect bot token exception (revoked tokens) break; case 403: // Handle authorization exceptions (blocked users, unaccessible chats, etc) break; case 429: // Handle rate limiting exception break; default: // Handle other errors with valid json body: it includes status code and description of the error break; } } catch (RequestException exception) { if (exception.InnerException is HttpRequestException httpRequestException) { // Handle connection exceptions or 5XX exceptions from the Bot API } else if (exception.InnerException is JsonSerializationException serializationException) { // Handle serialization exception when a request or a response can't be serialized for some reason } else { // Handle all other exceptions } } catch (OperationCancelledException exception) { // Handle cancellation exception, e.g. when CancellationToken is cancelled } ``` -------------------------------- ### InputFile Migration Scheme for File Handling in C# Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-19.x.md This table provides a direct mapping from previous `InputFile` related class instantiations and raw types to their new equivalent `InputFile` factory methods. It serves as a quick reference for migrating existing file handling code to conform to the updated API structure. ```APIDOC Previous method | New method - | - new InputTelegramType(string) | InputFile.FromId(string), InputFile.FromString(string) new InputTelegramType(Stream, string?) | InputFile.FromStream(Stream, string?) new InputFileStream(Stream) | InputFile.FromStream(Stream) new InputOnlineFile(string) | InputFile.FromId(string), InputFile.FromString(string), InputFile.FromString(string), InputFile.FromUrl(string), InputFile.FromUrl(Uri) new InputOnlineFile(Stream, string?) | InputFile.FromStream(Stream, string?) raw Stream | InputFile.FromStream(Stream) raw string | InputFile.FromString(string) raw URI | InputFile.FromUrl(URI) ``` -------------------------------- ### New HtmlText Helper Methods Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md New helper methods ToPlain, PlainLength, and Truncate have been added to HtmlText to extract plain text from HTML, get its length, or truncate HTML based on plain text character count, useful for message limits. ```APIDOC HtmlText.ToPlain() HtmlText.PlainLength() HtmlText.Truncate() ``` -------------------------------- ### Merged AnswerShippingQuery Overloads (Breaking Change) Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md The AnswerShippingQuery method overloads have been merged. To indicate a failure, users must now explicitly pass the errorMessage: argument. ```APIDOC AnswerShippingQuery(..., errorMessage: "Your error message") ``` -------------------------------- ### C# Telegram Bot: New InlineQueryResultDocument Instantiation (Recommended) Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-14.x.md This snippet demonstrates the recommended way to instantiate InlineQueryResultDocument using its constructor with required parameters. This approach ensures all necessary properties are provided, reducing the likelihood of runtime errors and aligning with the updated API design. ```csharp var documentResult = new InlineQueryResultDocument( id: "some-id", documentUrl: "https://example.com/document.pdf", title: "Some title", mimeType: "application/pdf" ); ``` -------------------------------- ### Callback buttons Source: https://github.com/telegrambots/book/blob/master/src/2/reply-markup.md When a user presses a [callback button], no messages are sent to the chat, and your bot simply receives an `update.CallbackQuery` instead (containing many information). Upon receiving this, your bot should answer to that query within 10 seconds, using `AnswerCallbackQuery` (or else the button gets momentarily disabled). In this example, the arrays of `InlineKeyboardButton` are constructed from tuples `(title, callbackData)`. Callback data string can be up to 64 bytes. ```C# {{#include ../../Examples/2/ReplyMarkup.cs:usings}} {{#include ../../Examples/2/ReplyMarkup.cs:callback-buttons}} ``` -------------------------------- ### C# Telegram Bot: Old InlineQueryResultDocument Instantiation (Not Recommended) Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-14.x.md This snippet shows the deprecated way of instantiating InlineQueryResultDocument using object initializers. This method is prone to exceptions due to missing required properties and is no longer the preferred approach in version 14.x. ```csharp var documentResult = new InlineQueryResultDocument { Id = "some-id", Url = "https://example.com/document.pdf", Title = "Some title", MimeType = "application/pdf" }; ``` -------------------------------- ### New ChatAdministratorRights Constructor Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md A new constructor ChatAdministratorRights(bool) has been added to easily set all fields (except IsAnonymous) to either true or false. ```APIDOC new ChatAdministratorRights(true) new ChatAdministratorRights(false) ``` -------------------------------- ### Removed Obsolete Async-Suffixed Methods Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md The *Async-suffixed versions of methods, previously marked as [Obsolete] since v22.0, have been removed. Users should adapt existing code to use the non-async versions. ```APIDOC Removed: MethodNameAsync() Use: MethodName() ``` -------------------------------- ### Requesting information to be sent to the bot Source: https://github.com/telegrambots/book/blob/master/src/2/reply-markup.md Some special keyboard button types can be used to request information from the user and send them to the bot. More options are available in associated class properties. - `KeyboardButton.WithRequestLocation("Share your location")` User's position will be transmitted in a `message.Location` - `KeyboardButton.WithRequestContact("Share your info")` User's phone number will be transmitted in a `message.Contact` - `KeyboardButton.WithRequestPoll("Create a poll", PollType.Regular)` User must create a poll which gets transmitted in a `message.Poll` - `KeyboardButton.WithRequestChat("Select a chat", 1234, false)` User must pick a group (false) or channel (true) which gets transmitted in a `message.ChatShared` - `KeyboardButton.WithRequestUsers("Select user(s)", 5678, 1)` User must pick 1-10 user(s) which get transmitted in a `message.UsersShared` - `KeyboardButton.WithWebApp("Launch WebApp", "https://www.example.com/game")` Launch a [Mini-App](../4/webapps.md) ```C# {{#include ../../Examples/2/ReplyMarkup.cs:usings}} {{#include ../../Examples/2/ReplyMarkup.cs:request-info}} ``` -------------------------------- ### Tor `torcc` Configuration for SOCKS5 Proxy Setup Source: https://github.com/telegrambots/book/blob/master/src/4/proxy.md This text snippet provides the necessary configuration lines to add to the `torcc` file for setting up a SOCKS5 proxy over Tor. It specifies entry/exit nodes, strict node usage, and the SOCKS port. ```text EntryNodes {NL} ExitNodes {NL} StrictNodes 1 SocksPort 127.0.0.1:9050 ``` -------------------------------- ### New Message.IsServiceMessage Property Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md A new helper property message.IsServiceMessage has been added to easily detect whether a message is a service message or a content message. ```APIDOC message.IsServiceMessage ``` -------------------------------- ### API Usage: Telegram Stars Payments with SendInvoiceAsync Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-21.x.md To initiate a payment using Telegram Stars with the `SendInvoiceAsync` method, specific parameters must be set: `providerToken` should be `null` or an empty string, `currency` must be `"XTR"`, `prices` should contain a single price, and no tip amounts should be specified. ```APIDOC SendInvoiceAsync Parameters for Telegram Stars: providerToken: null or "" currency: "XTR" prices: [single_price_object] tip_amounts: (not specified or empty list) Example (Conceptual): await botClient.SendInvoiceAsync( chatId: ..., title: "Product Name", description: "Product Description", payload: "invoice-payload", providerToken: null, currency: "XTR", prices: new[] { new LabeledPrice("Item", 100) } // 100 Telegram Stars ); ``` -------------------------------- ### C# Object Initialization: Constructor vs. Setters Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-14.x.md This C# code snippet illustrates the recommended approach for object initialization, emphasizing the use of constructor parameters over public setters. It shows a 'bad way' using an object initializer for all properties and a 'better' way passing core parameters to the constructor, then using an object initializer for optional properties. This change aims to improve API consistency and prevent runtime issues. ```c# //bad way: var markup = new InlineKeyboardMarkup { Keyboard = buttonsArray, ResizeKeyboard = true }; // better: var markup = new InlineKeyboardMarkup(buttonsArray) { ResizeKeyboard = true }; ``` -------------------------------- ### InputFile Factory Methods for File Handling in C# Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-19.x.md This section describes the new `InputFile` hierarchy, which replaces older `InputMedia*` classes and implicit casts. It lists the new static factory methods available on the `InputFile` base class for creating specific file types like streams, URLs, or existing file IDs, simplifying file input operations and requiring explicit type specification. ```APIDOC InputFile: - FromStream(Stream stream, string? fileName = default) - FromString(string urlOrFileId) - FromUri(Uri url) - FromUri(string url) - FromFileId(string fileId) ``` -------------------------------- ### Merged Telegram Passport Functionality Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md The Telegram.Bot.Extensions.Passport package has been merged into the main Telegram.Bot library. Methods and structures supporting Telegram Passport are now up-to-date and directly available within the main library. ```APIDOC Telegram Passport related methods and structures are now directly in Telegram.Bot ``` -------------------------------- ### Accessing Derived ChatMember Properties in C# Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-17.x.md Demonstrates how to use pattern matching or type casting in C# to access properties of derived `ChatMember` types, such as `ChatMemberKicked`, after the `ChatMember` type was split into a hierarchy with a `Status` discriminator. ```csharp ChatMember member = ... //; if (chatMember is ChatMemberKicked kickedMember) { // now you can access properties of a kicked chat member if (kickedMember.Until is not null) { // do something with the value of Until } } ``` -------------------------------- ### API Enhancements: Implicit Conversions and Simplified Usage Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-21.x.md The library now offers improved backward compatibility and simplified code through various implicit conversions and relaxed property constraints. This includes easier handling of file inputs, media, message IDs, and reaction types. ```APIDOC Implicit Conversions & Simplifications: - InputFile: Accepts string (file_id/url) or Stream content. - InputMedia*: Accepts InputFile directly when no caption or other properties are needed. - MessageId: Auto-converts to/from int and from Message objects. - ReactionType: Accepts string for emoji, long for custom emoji ID. - No more enforcing 'init;' properties, allowing modification of API-returned structures. - No more JSON 'required properties' during deserialization, improving compatibility with old saved JSON files. ``` -------------------------------- ### Defining Sample Data for Inline Queries in C# Source: https://github.com/telegrambots/book/blob/master/src/3/inline.md This C# example illustrates how to define simple string arrays (`names` and `locations`) that can serve as a data source for generating inline query results. Such arrays are typically used to populate dynamic suggestions based on user input. ```C# string[] names = { "Alice", "Bob", "Charlie" }; string[] locations = { "New York", "London", "Paris" }; ``` -------------------------------- ### Copy Messages in C# Source: https://github.com/telegrambots/book/blob/master/src/2/forward-copy-delete.md Illustrates how to copy single or multiple messages, making them appear as new messages without the 'Forwarded from' header. Includes an example of copying a media message and changing its caption. ```csharp // Copy a single message await bot.CopyMessage(targetChatId, sourceChatId, messageId); // Copy an incoming message (from the update) onto a target ChatId await bot.CopyMessage(targetChatId, update.Message.Chat, update.Message.Id); // Copy a media message and change its caption at the same time await bot.CopyMessage(targetChatId, update.Message.Chat, update.Message.Id, caption: "New caption for this media", parseMode: ParseMode.Html); // Copy a bunch of messages from a source ChatId to a target ChatId, using a list of their message ids await bot.CopyMessages(targetChatId, sourceChatId, new int[] { 123, 124, 125 }); ``` -------------------------------- ### API Parameter Rename: disableWebPagePreview to linkPreviewOptions Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-21.x.md The `disableWebPagePreview` parameter has been renamed to `linkPreviewOptions`. It can still accept `true` to disable web preview or a `LinkPreviewOptions` structure for more precise preview configuration. ```APIDOC Old Parameter: disableWebPagePreview: bool New Parameter: linkPreviewOptions: bool | LinkPreviewOptions Usage: // Disable preview SendMessage(chatId, text, linkPreviewOptions: false) // Configure preview SendMessage(chatId, text, linkPreviewOptions: new LinkPreviewOptions { IsDisabled = true, Urls = ["https://example.com"] }) ``` -------------------------------- ### Reading Primary Chat Invite Link (C#) Source: https://github.com/telegrambots/book/blob/master/src/2/chats.md Demonstrates how to retrieve the fixed primary invite link of a chat using the `bot.GetChat` method in C#. This method should ideally be called only once to get the chat's full information, including its `InviteLink`. ```csharp var chatFullInfo = await bot.GetChat(chatId); // you should call this only once Console.WriteLine(chatFullInfo.InviteLink); ``` -------------------------------- ### Send Document from URL with HTML Caption (C#) Source: https://github.com/telegrambots/book/blob/master/src/2/send-msg/media-msg.md This example demonstrates sending a general file as a document using its URL. It also shows how to include a caption with HTML formatting. Sending photos or videos as documents ensures their original data and metadata are preserved without recompression. ```csharp await bot.SendDocument(chatId, "https://telegrambots.github.io/book/docs/photo-ara.jpg", "Ara bird. Source: Pixabay", ParseMode.Html); ``` -------------------------------- ### Download File in Two Steps (C#) Source: https://github.com/telegrambots/book/blob/master/src/3/files.md Demonstrates the two-step process to download a file: first, get file information using `bot.GetFile(fileId)`, then download the file content into a stream using `bot.DownloadFile(tgFile, stream)`. The `FileId` can be found in various message objects like Video, Animation, Audio, etc. ```csharp var fileId = update.Message.Video.FileId; var tgFile = await bot.GetFile(fileId); await using var stream = File.Create("../downloaded.mp4"); await bot.DownloadFile(tgFile, stream); ``` -------------------------------- ### C# Telegram Bot: Two-Step File Download (GetFileAsync & DownloadFileAsync) Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-14.x.md This snippet illustrates the new two-step process for downloading files: first, GetFileAsync() retrieves the file information, and then DownloadFileAsync() is used to download the file content. This approach provides more granular control over the file download process. ```csharp File fileInfo = await bot.GetFileAsync("BsdfgLg4Khdlsn-bldBD"); using (var fileStream = System.IO.File.OpenWrite("path/to/file.pdf")) { await bot.DownloadFileAsync( filePath: fileInfo.FilePath, destination: fileStream ); } ``` -------------------------------- ### Send Advanced Text Message with HTML and Options in C# Source: https://github.com/telegrambots/book/blob/master/src/2/send-msg/README.md This example shows how to send a text message with advanced features such as HTML formatting, content protection, replying to a specific message, and attaching an inline keyboard button. It highlights the use of `ParseMode.Html` and `replyMarkup`. ```csharp var message = await bot.SendMessage(chatId, "Trying all the parameters of sendMessage method", ParseMode.Html, protectContent: true, replyParameters: update.Message.Id, replyMarkup: new InlineKeyboardButton("Check sendMessage method", "https://core.telegram.org/bots/api#sendmessage")); ``` -------------------------------- ### Moved ConfigureTelegramBotMvc to Separate Package Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md The ConfigureTelegramBotMvc() method has been moved from the main library to the Telegram.Bot.AspNetCore NuGet package, removing the ASP.NET Core dependency from the core library. This resolves deployment issues for Docker, Android, and WebAssembly users. It's generally not needed anymore, but can be added via the new package if required. ```APIDOC Telegram.Bot.AspNetCore.ConfigureTelegramBotMvc() ``` -------------------------------- ### Configure TelegramBotClient with Tor SOCKS5 Proxy Source: https://github.com/telegrambots/book/blob/master/src/4/proxy.md This C# code demonstrates how to configure TelegramBotClient to use a SOCKS5 proxy provided by the Tor network. It's similar to the standard SOCKS5 setup but relies on Tor being active and listening on the specified port. ```csharp {{#include ../../Examples/4/Proxy.cs:usings}} {{#include ../../Examples/4/Proxy.cs:tor-proxy-client}} ``` -------------------------------- ### Creating Other Special Inline Button Types (C#) Source: https://github.com/telegrambots/book/blob/master/src/2/reply-markup.md Demonstrates various special inline button types for Telegram bots, including copy text, web app, login URL, callback game, and pay buttons. These examples use helper methods like WithCopyText, WithWebApp, WithLoginUrl, WithCallbackGame, and WithPay from InlineKeyboardButton. ```c# InlineKeyboardButton.WithCopyText("Copy info", "Text to copy") InlineKeyboardButton.WithWebApp("Launch WebApp", "https://www.example.com/game") InlineKeyboardButton.WithLoginUrl("Login", new() { Url = "https://www.example.com/telegramAuth" }) InlineKeyboardButton.WithCallbackGame("Launch game") InlineKeyboardButton.WithPay("Pay 200 XTR") ``` -------------------------------- ### Manual Long Polling Loop with GetUpdates (C#) Source: https://github.com/telegrambots/book/blob/master/src/3/updates/polling.md This C# example demonstrates how to manually implement long polling. It continuously calls `bot.GetUpdates` with an increasing offset and a timeout, processing each update. The loop includes basic error handling and respects a cancellation token. ```csharp int? offset = null; while (!cts.IsCancellationRequested) { var updates = await bot.GetUpdates(offset, timeout: 2); foreach (var update in updates) { offset = update.Id + 1; try { // put your code to handle one Update here. } catch (Exception ex) { // log exception and continue } if (cts.IsCancellationRequested) break; } } ``` -------------------------------- ### API Usage: Discouraged Request Structures Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-21.x.md Request structures (types ending with `Request`) are not the recommended way to use the library for general projects. They are considered low-level raw access for advanced programmers and may change or break. If existing code uses them, use the `MakeRequestAsync` method to send these requests. ```APIDOC Discouraged Usage: // Avoid direct use of Request structures like SendMessageRequest Recommended Low-Level Usage: var request = new SendMessageRequest(chatId, text); await botClient.MakeRequestAsync(request); ``` -------------------------------- ### Send Video from URL with Streaming and Thumbnail (C#) Source: https://github.com/telegrambots/book/blob/master/src/2/send-msg/media-msg.md This example shows how to send a video message to a Telegram chat using a direct URL. It also demonstrates how to specify a thumbnail image and enable streaming support for long videos, allowing users to seek without full download. ```csharp await bot.SendVideo(chatId, "https://telegrambots.github.io/book/docs/video-countdown.mp4", thumbnail: "https://telegrambots.github.io/book/2/docs/thumb-clock.jpg", supportsStreaming: true); ``` -------------------------------- ### Miscellaneous API Property and Method Renames in C# Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-19.x.md This section lists various other API changes, including updates to message types, chat member permissions, method renames, removal of voice chat related properties, renaming of `Thumb` to `Thumbnail`, and the introduction of `InlineQueryResultsButton` replacing older properties. Developers should review these changes to update their code accordingly. ```APIDOC Message.Type: Use MessageType.Animation instead of MessageType.Document for animations ChatMemberRestricted, ChatPermissions: CanSendMediaMessages removed, use more granular permissions GetChatMembersCountAsync: Removed, use GetChatMemberCountAsync KickChatMemberAsync: Removed, use BanChatMemberAsync VoiceChatEnded, VoiceChatParticipantsInvited, VoiceChatScheduled, VoiceChatStarted: Removed, use Video* methods/types Thumb properties: Renamed to Thumbnail SwitchPmText, SwitchPmParameter: Replaced by InlineQueryResultsButton ``` -------------------------------- ### Send Video Note by Uploading from Disk (C#) Source: https://github.com/telegrambots/book/blob/master/src/2/send-msg/media-msg.md This snippet shows how to send a video note, which is a short circular video, by uploading it from disk. It's important to note that sending video notes via URL is not currently supported. The example also specifies duration and length (width/height). ```csharp await using Stream stream = File.OpenRead("path/to/video-waves.mp4"); await bot.SendVideoNote(chatId, stream, duration: 47, length: 360); // length = width = height ``` -------------------------------- ### Send Voice Message from URL with Duration (C#) Source: https://github.com/telegrambots/book/blob/master/src/2/send-msg/media-msg.md This example demonstrates sending an OGG voice message from a URL. Unlike audio, voice messages are not shown in music players. The `duration` parameter is explicitly provided as Telegram cannot infer it from the file's metadata. ```csharp var msg = await bot.SendVoice(chatId, "https://telegrambots.github.io/book/docs/voice-nfl_commentary.ogg", duration: 36); ``` -------------------------------- ### Sticker API Method and Type Renames in C# Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-19.x.md This section outlines significant changes to sticker-related APIs. The previous distinctions between animated, static, and video stickers have been removed, consolidating methods into a single set (e.g., `AddStickerToSetAsync`). Additionally, associated emojis and masks are now part of the `InputSticker` type, requiring developers to consult official Bot API docs for detailed usage. ```APIDOC Removed methods: AddAnimatedStickerToSetAsync, AddStaticStickerToSetAsync, AddVideoStickerToSetAsync (and similar) Replaced with: Consolidated sticker methods (e.g., AddStickerToSetAsync) Type change: Associated emojis and masks moved to InputSticker ``` -------------------------------- ### Handling Unknown Enum Values in C# Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-17.x.md This C# example illustrates how to handle unknown enum values in Telegram.Bot v17, specifically for MessageEntity.Type. Since '0' is now reserved for unknown values, the 'default' case in a switch statement can reliably catch newly added or unrecognized enum members from the Bot API. ```csharp MessageEntity entity = message.Entities.First(); switch (entity.Type) { case MessageEntityType.Username: // ... break; case MessageEntityType.Command: // ... break; default: // All unknown values will go there break; } ``` -------------------------------- ### Simplified Webhook Bot Configuration Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md The Services.ConfigureTelegramBot* methods are generally no longer required for Webhook bot compatibility with Telegram updates due to library structure changes compatible with ASP.NET Core's default JsonCamelCaseNamingPolicy. In rare cases (Native AOT, Blazor, Trimming), it might still be necessary. ```APIDOC Services.ConfigureTelegramBot* (no longer necessary in most cases) ``` -------------------------------- ### .NET Target Framework Update for Telegram Bot Library Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-19.x.md This section details the change in target frameworks for the library. Support for .NET Core 3.1 has been removed, with new targets set to `netstandard2.0` and `net6.0`. Users on .NET Core 3.1 or .NET 5 runtimes should now use the `netstandard2.0` build, while those relying on `IAsyncEnumerable` implementation for the poller must migrate to .NET 6 to maintain functionality. ```APIDOC Removed Target: .NET Core 3.1 New Targets: netstandard2.0, net6.0 Migration for IAsyncEnumerable: Move to .NET 6 ``` -------------------------------- ### API Reference: Simplified Constructors and Implicit Conversions Source: https://github.com/telegrambots/book/blob/master/src/3/helpers.md Documentation for simplified constructors and implicit conversion capabilities for various Telegram Bot API types, allowing easier argument passing. ```APIDOC - ChatPermissions(bool): Constructor to set all Can* fields to the specified value - ChatAdministratorRights(bool): Constructor to set all Can* fields to the specified value - ReactionType: Implicitly construct from an emoji (string) or a customEmojiId (long) - ReplyParameters: Implicitly construct from a messageId (int) or a Message class, for replyParameters: argument - LinkPreviewOptions: Implicitly construct from a bool where true means to disable the preview - LabeledPrice: Implicitly construct from tuple (string label, long amount) - BotCommand: Implicitly construct from tuple (string command, string description) - BotCommandScope: Several static methods to construct scopes - InputFile: Implicitly construct from a fileId or URL (string) or a Stream or a received media file ``` -------------------------------- ### C# Telegram Bot: Convert Message Date to Local Time Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-14.x.md This snippet shows how to convert a Message.Date property, which is now in UTC, to local time using ToLocalTime(). While possible, the migration guide notes that converting to local time is generally not recommended. ```csharp DateTime localTime = update.Message.Date.ToLocalTime(); ``` -------------------------------- ### Troubleshoot File and Media Uploads Source: https://github.com/telegrambots/book/blob/master/src/FAQ.md Offers solutions for common difficulties encountered when uploading and sending files or media. Key points include ensuring `await` is used, managing `MemoryStream` position, and specifying unique filenames for media groups. ```C# await sendMethod(); // Ensure await until end of send method using (var fileStream = new FileStream("path", FileMode.Open)) { // File operations } // 'using' clause ensures file closure ms.Position = 0; // Rewind MemoryStream before sending InputFile.FromStream(stream, "unique_filename.jpg"); // Specify different filenames for media groups ``` -------------------------------- ### C# Telegram Bot: Send Message with Reply Keyboard for Contact/Location Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-14.x.md This snippet illustrates how to send a message with a 2-row reply keyboard, allowing users to share their contact or location. It utilizes ReplyKeyboardMarkup and KeyboardButton.WithRequestContact/WithRequestLocation factory methods, aligning with the updated API for keyboard buttons. ```csharp await bot.SendTextMessageAsync( chatId: 1234, text: "Share your contact & location", replyMarkup: new ReplyKeyboardMarkup( new [] { KeyboardButton.WithRequestContact("Share Contact") }, new [] { KeyboardButton.WithRequestLocation("Share Location") } ) ); ``` -------------------------------- ### Dynamically Constructing Telegram Bot Keyboards in C# Source: https://github.com/telegrambots/book/blob/master/src/3/helpers.md Demonstrates how to use the fluent API of `InlineKeyboardMarkup` to dynamically add buttons with URLs, callbacks, and inline query switches. It also mentions the `ReplyKeyboardMarkup(true)` constructor for resizing reply keyboards. ```csharp var replyMarkup = new InlineKeyboardMarkup() .AddButton(InlineKeyboardButton.WithUrl("Link to Repository", "https://github.com/TelegramBots/Telegram.Bot")) .AddNewRow().AddButton("callback").AddButton("caption", "data") .AddNewRow("with", "three", "buttons") .AddNewRow().AddButtons("A", "B", InlineKeyboardButton.WithSwitchInlineQueryCurrentChat("switch")); ``` -------------------------------- ### Update SendTextMessageAsync for messageThreadId in C# Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-19.x.md This snippet illustrates the migration from an older `SendTextMessageAsync` call to a new one that explicitly uses named parameters and includes the `messageThreadId` for interacting with topics in Telegram groups. It highlights the change in parameter order and the addition of the new `messageThreadId` parameter, emphasizing the use of named parameters to prevent confusion. ```diff -Message message = await bot.SendTextMessageAsync( - _fixture.SupergroupChat.Id, - "Please click on *Notify* button.", - cancellationToken); +Message message = await bot.SendTextMessageAsync( + chatId: _fixture.SupergroupChat.Id, + text: "Please click on *Notify* button.", + messageThreadId: threadId, + cancellationToken: cancellationToken); ``` -------------------------------- ### Initialize Telegram Bot and Handle Incoming Messages (C#) Source: https://github.com/telegrambots/book/blob/master/src/1/example-bot.md This C# code initializes a Telegram bot client with a given token, sets up an event handler for incoming messages, and keeps the bot running until terminated. The `OnMessage` method processes text messages, echoes them back to the sender, and logs activity to the console. ```c# using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; using var cts = new CancellationTokenSource(); var bot = new TelegramBotClient("YOUR_BOT_TOKEN", cancellationToken: cts.Token); var me = await bot.GetMe(); bot.OnMessage += OnMessage; Console.WriteLine($"@{me.Username} is running... Press Enter to terminate"); Console.ReadLine(); cts.Cancel(); // stop the bot // method that handle messages received by the bot: async Task OnMessage(Message msg, UpdateType type) { if (msg.Text is null) return; // we only handle Text messages here Console.WriteLine($"Received {type} '{msg.Text}' in {msg.Chat}"); // let's echo back received text in the chat await bot.SendMessage(msg.Chat, $"{msg.From} said: {msg.Text}"); } ``` -------------------------------- ### Getting Full Chat Information with GetChat Source: https://github.com/telegrambots/book/blob/master/src/2/chats.md Describes the `GetChat` method for retrieving detailed information about a Telegram chat or user. The returned information varies by chat type and may include birthdate, personal channel, business info for private chats, and description, permissions, linked chat ID, and forum status for groups/channels. Common information includes photo, active usernames, available reactions, and pinned messages. ```APIDOC GetChat(chatId: long | string) -> Chat Description: Retrieves detailed information about a chat or user. Parameters: chatId: The ID of the chat or user (long) or "@chatname" string for public groups/channels. Returns: Chat object with various fields. Relevant Fields (depending on ChatType): For ChatType.Private (User): Birthdate: User's birthdate. Personal channel: Link to user's personal channel. Business information: Details about user's business. Bio: User's biography. For ChatType.Group / ChatType.Supergroup / ChatType.Channel: Description: Chat description. default Permissions: Non-administrator access rights. Linked ChatId: Associated channel/discussion group ID. IsForum: Indicates if the chat group has topics. Common for all chats: Photo: Chat photo (use GetInfoAndDownloadFile with photo.BigFileId to download). Active Usernames: Multiple usernames for premium users & public chats. Available reactions: List of reactions available in this chat. Pinned Message: The most recent pinned message. ``` -------------------------------- ### Poll.Type Changed to PollType Enum (Breaking Change) Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md The Poll.Type property has changed from a string to the PollType enum, providing type safety and predefined values. ```APIDOC Poll.Type (now PollType enum instead of string) ``` -------------------------------- ### API Reference: Reply Markup Parameter Types Source: https://github.com/telegrambots/book/blob/master/src/3/helpers.md Documentation detailing the various types of objects that can be directly passed as the `replyMarkup` parameter for constructing keyboards, including implicit conversions for inline buttons. ```APIDOC Reply Markup Parameter Types for 'replyMarkup:' argument: - string: single keyboard text button - string[]: keyboard text buttons on one row - string[][]: multiple keyboard text buttons - KeyboardButton: single keyboard button - KeyboardButton[]: multiple keyboard buttons on one row - KeyboardButton[][] or IEnumerable[]: multiple keyboard buttons - InlineKeyboardButton: single inline button - InlineKeyboardButton[]: inline buttons on 1 row - InlineKeyboardButton[][] or IEnumerable[]: multiple inline buttons InlineKeyboardButton Implicit Construction: - From tuple (string text, string callbackOrUrl) for Callback or Url buttons ``` -------------------------------- ### New ChatMemberRestricted.IsMuted Property Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md A new helper property ChatMemberRestricted.IsMuted has been added to detect if a user's restriction involves muting them (available since v22.5.1). ```APIDOC chatMemberRestricted.IsMuted ``` -------------------------------- ### Rename MakeRequestAsync to SendRequest (C#) Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-22.x.md This operation renames the 'MakeRequestAsync' method to 'SendRequest'. This method is generally not recommended for direct use by library consumers. ```Regular Expression Find: MakeRequestAsync Replace: SendRequest ``` -------------------------------- ### API Reference: Chat and User Information Helpers Source: https://github.com/telegrambots/book/blob/master/src/3/helpers.md Documentation for helper methods and properties to easily access and log chat and user information. ```APIDOC - chat.ToString(): Easily print/log information about the chat - user.ToString(): Easily print/log information about the user - ChatMember: - IsAdmin: Property to simplify testing if the user is an admin - IsInChat: Property to simplify testing if the user is currently inside the chat ``` -------------------------------- ### API Type Change: Nullable ParseMode to Non-Nullable ParseMode Source: https://github.com/telegrambots/book/blob/master/src/migrate/Version-21.x.md The `ParseMode?` type has been changed to `ParseMode`. When there is no need to specify a `ParseMode`, simply pass `default` or `ParseMode.None`. ```APIDOC Old Type: Parameter: ParseMode? New Type: Parameter: ParseMode Usage: // No ParseMode needed SendMessage(chatId, text, parseMode: default) SendMessage(chatId, text, parseMode: ParseMode.None) ```