### Complete Bot Setup and Event Handlers Source: https://telegrambots.github.io/book/print.html This snippet sets up a Telegram bot client, registers handlers for messages, updates, and errors, and starts the polling process. It includes example implementations for OnMessage, OnUpdate (specifically for callback queries), and OnError. ```csharp 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}"); } } ``` -------------------------------- ### InlineQueryResultDocument Example Source: https://telegrambots.github.io/book/print.html Demonstrates the creation of an InlineQueryResultDocument with essential parameters. ```csharp var documentResult = new InlineQueryResultDocument( id: "some-id", documentUrl: "https://example.com/document.pdf", title: "Some title", mimeType: "application/pdf" ); ``` -------------------------------- ### Get File Information and Download Source: https://telegrambots.github.io/book/print.html Retrieve file information using GetFile and then download the file content into a stream. This is a two-step process. ```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); ``` -------------------------------- ### Get File Info and Download with Helper Function Source: https://telegrambots.github.io/book/print.html Utilize the GetInfoAndDownloadFile helper function to simplify the process of obtaining file information and downloading the file into a MemoryStream. ```csharp await using var ms = new MemoryStream(); var tgFile = await bot.GetInfoAndDownloadFile(fileId, ms); ``` -------------------------------- ### Configure Telegram Bot Client with Options Source: https://telegrambots.github.io/book/print.html Instantiate TelegramBotClientOptions to configure the client with a token, optional base URL, and test environment flag. This is the recommended way to configure the client starting with this release. ```csharp 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); ``` -------------------------------- ### Get File Info and Download Separately Source: https://telegrambots.github.io/book/migrate/Version-14.x.html This approach first retrieves file information using GetFileAsync and then downloads the file content using DownloadFileAsync. This separates the two steps of file retrieval. ```csharp // New version of GetFileAsync() only gets the file info (step 1) File fileInfo = await bot.GetFileAsync("BsdfgLg4Khdlsn-bldBD"); // Download file from server (step 2) using (var fileStream = System.IO.File.OpenWrite("path/to/file.pdf")) { await bot.DownloadFileAsync( filePath: fileInfo.FilePath, destination: fileStream ); } ``` -------------------------------- ### Send Photo and Video Source: https://telegrambots.github.io/book/print.html Provides examples for sending a photo via URL and sending a video file. The video can be sent using a received `Video` object. ```csharp await bot.SendPhoto(msg.Chat, "https://picsum.photos/310/200.jpg"); ``` ```csharp await bot.SendVideo(msg.Chat, msg.Video, "Sending your video back"); ``` -------------------------------- ### Download File Info and Content with GetInfoAndDownloadFileAsync Source: https://telegrambots.github.io/book/migrate/Version-14.x.html This method combines getting file information and downloading the file content in a single operation. It sends two HTTP requests to the Bot API. ```csharp // Gets file info and saves it to "path/to/file.pdf" using (var fileStream = System.IO.File.OpenWrite("path/to/file.pdf")) { File fileInfo = await bot.GetInfoAndDownloadFileAsync( fileId: "BsdfgLg4Khdlsn-bldBD", destination: fileStream ); } ``` -------------------------------- ### Build an Interactive Echo Bot Source: https://telegrambots.github.io/book/print.html Implement an interactive bot that listens for incoming messages and echoes the received text back to the user. This example uses an event handler for message updates and requires your bot token. ```csharp 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}"); } ``` -------------------------------- ### Send HTML Message with Image After Text Source: https://telegrambots.github.io/book/print.html Demonstrates that text preceding an image will appear above it, and text following will appear below it. This example shows text before the image. ```csharp var msg = await bot.SendHtml(chatId, """ Ara bird. Source: Pixabay """); ``` -------------------------------- ### Download, Decrypt Passport File Translation to Byte Array Source: https://telegrambots.github.io/book/print.html This example shows how to download and decrypt a certified English translation of a document, treating it as a passport file. The decrypted content is obtained as a byte array and then written to a file on disk. ```csharp PassportFile passportFile = element.Translation[0]; FileCredentials fileCreds = credentials.SecureData.DriverLicense.Translation[0]; // fetch passport file info TGFile encryptedFileInfo = await bot.GetFile(passportFile.FileId); // download encrypted file and get its bytes byte[] encryptedContent; using (System.IO.MemoryStream stream = new System.IO.MemoryStream(encryptedFileInfo.FileSize) ) { await bot.DownloadFile(encryptedFileInfo, stream); encryptedContent = stream.ToArray(); } // decrypt the content and get bytes of the actual selfie photo byte[] content = decrypter.DecryptFile( encryptedContent, fileCreds ); // write the file to disk await System.IO.File.WriteAllBytesAsync("/path/to/translation.jpg", content); ``` -------------------------------- ### Configure SOCKS5 Proxy over Tor for Telegram Bot Client (Testing Only) Source: https://telegrambots.github.io/book/4/proxy.html Set up a SOCKS5 proxy connection through the Tor network for testing purposes. This configuration requires Tor Browser to be installed and running, and the bot will only function while Tor is active. ```csharp // using System.Net; // using System.Net.Http; WebProxy proxy = new ("socks5://127.0.0.1:9050"); HttpClient httpClient = new ( new SocketsHttpHandler { Proxy = proxy, UseProxy = true } ); var bot = new TelegramBotClient("YOUR_API_TOKEN", httpClient); ``` -------------------------------- ### Get File Info and Download File Source: https://telegrambots.github.io/book/print.html This method retrieves file information and downloads the file in a single operation, making two HTTP requests to the Bot API. It saves the file to the specified destination stream. ```csharp // Gets file info and saves it to "path/to/file.pdf" using (var fileStream = System.IO.File.OpenWrite("path/to/file.pdf")) { File fileInfo = await bot.GetInfoAndDownloadFileAsync( fileId: "BsdfgLg4Khdlsn-bldBD", destination: fileStream ); } ``` -------------------------------- ### Create and Configure a New Console Project Source: https://telegrambots.github.io/book/print.html Set up a new .NET console application and add the necessary Telegram.Bot package. This is the initial step for building your bot. ```bash dotnet new console dotnet add package Telegram.Bot ``` -------------------------------- ### Get Plain Text Length Source: https://telegrambots.github.io/book/migrate/Version-22.x.html Use the HtmlText.PlainLength method to get the number of characters in the plain text representation of HTML content. This is useful for character count limits. ```csharp HtmlText.PlainLength(html); ``` -------------------------------- ### Constructor Initialization for InlineKeyboardMarkup Source: https://telegrambots.github.io/book/migrate/Version-14.x.html Demonstrates the recommended way to initialize InlineKeyboardMarkup with required parameters in the constructor, contrasting it with the older property-based assignment. ```csharp //bad way: var markup = new InlineKeyboardMarkup { Keyboard = buttonsArray, ResizeKeyboard = true }; // better: var markup = new InlineKeyboardMarkup(buttonsArray) { ResizeKeyboard = true }; ``` -------------------------------- ### Initialize ReplyKeyboardMarkup with ResizeKeyboard Source: https://telegrambots.github.io/book/print.html Use object initialization syntax to configure optional properties like ResizeKeyboard when creating a ReplyKeyboardMarkup. ```csharp var replyKeyboardMarkup = new ReplyKeyboardMarkup( new KeyboardButton[][] { new KeyboardButton[] { "1.1", "1.2" }, new KeyboardButton[] { "2.1", "2.2" }, }) { ResizeKeyboard = true }; ``` -------------------------------- ### Get Chat Invite Link Source: https://telegrambots.github.io/book/print.html Retrieve the fixed primary invite link for a chat. This should be called only once. ```csharp var chatFullInfo = await bot.GetChat(chatId); // you should call this only once Console.WriteLine(chatFullInfo.InviteLink); ``` -------------------------------- ### Configuring ReplyKeyboardMarkup with Optional Properties Source: https://telegrambots.github.io/book/migrate/Version-17.x.html When ResizeKeyboard and OneTimeKeyboard are optional, they must be configured using object initialization syntax after creating the ReplyKeyboardMarkup instance. ```csharp var replyKeyboardMarkup = new ReplyKeyboardMarkup( new KeyboardButton[][] { new KeyboardButton[] { "1.1", "1.2" }, new KeyboardButton[] { "2.1", "2.2" }, }) { ResizeKeyboard = true }; ``` -------------------------------- ### Creating InlineKeyboardMarkup with Constructor Source: https://telegrambots.github.io/book/print.html Illustrates the preferred way to instantiate InlineKeyboardMarkup using its constructor, passing the keyboard array directly. ```csharp //bad way: var markup = new InlineKeyboardMarkup { Keyboard = buttonsArray, ResizeKeyboard = true }; // better: var markup = new InlineKeyboardMarkup(buttonsArray) { ResizeKeyboard = true }; ``` -------------------------------- ### Configure Telegram Bot in ASP.NET Core (Recommended) Source: https://telegrambots.github.io/book/print.html Add the Telegram.Bot.AspNetCore NuGet package and configure the bot services in Program.cs or Startup.cs for .NET 6.0+. ```csharp services.ConfigureTelegramBotMvc(); ``` -------------------------------- ### Send Message with UTC DateTime Source: https://telegrambots.github.io/book/print.html When making requests that involve dates, use UTC time to ensure consistency. This example shows kicking a chat member until a future UTC date. ```csharp // Use UTC time when making a request await bot.KickChatMemberAsync( chatId: -9876, userId: 1234, untilDate: DateTime.UtcNow.AddDays(2) ); ``` -------------------------------- ### Sending Video with Stream and FileId Source: https://telegrambots.github.io/book/print.html Demonstrates how to send a video using a stream for the first time and then reuse its FileId for subsequent sends. This is applicable for videos and photos. ```csharp var msg = await bot.SendVideo(chatId, stream, ....); var fileId = msg.Video.FileId // next times: await bot.SendVideo(chatId2, fileId, ...); ``` -------------------------------- ### Set Bot Commands with Tuples Source: https://telegrambots.github.io/book/migrate/Version-22.x.html Use implicit construction from tuples to set bot commands. Ensure the command and description strings are correctly formatted. ```csharp await Bot.SetMyCommands([("/start", "Start the bot"), ("/privacy", "Privacy policy")]); ``` -------------------------------- ### Instantiate TelegramBotClient with Token Source: https://telegrambots.github.io/book/migrate/Version-18.x.html Create a TelegramBotClient instance using only the bot token when no additional configuration is needed. ```csharp var client = new TelegramBotClient(""); ``` -------------------------------- ### Configure TelegramBotClient with Options Source: https://telegrambots.github.io/book/migrate/Version-18.x.html Instantiate TelegramBotClient with custom options, including a base URL for a custom bot server or to enable the test environment. ```csharp 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); ``` -------------------------------- ### Tor Browser 'torcc' Configuration for SOCKS Proxy Source: https://telegrambots.github.io/book/4/proxy.html Configure the 'torcc' file in Tor Browser to enable a SOCKS port for proxying. This example sets specific entry and exit nodes and enables the SOCKS port on localhost. ```plaintext EntryNodes {NL} ExitNodes {NL} StrictNodes 1 SocksPort 127.0.0.1:9050 ``` -------------------------------- ### Basic Update Handling Source: https://telegrambots.github.io/book/print.html A simple way to handle incoming updates by subscribing to the `OnUpdate` event. This is suitable for bots that do not require complex parallel processing. ```csharp bot.OnUpdate += async update => OnUpdate(update); ``` -------------------------------- ### Configure Telegram Bot in ASP.NET Core (Any Version) Source: https://telegrambots.github.io/book/print.html Configure bot services in Program.cs or Startup.cs for any .NET version by specifying JSON options. ```csharp services.ConfigureTelegramBot(opt => opt.JsonSerializerOptions); ``` -------------------------------- ### Send Video by Uploading from Disk Source: https://telegrambots.github.io/book/print.html Uploads a video file from the local disk and sends it. Ensure the video file exists at the specified path. ```csharp await using Stream stream = File.OpenRead("./video-hawk.mp4"); await bot.SendVideo(chatId, stream); ``` -------------------------------- ### Fetch Bot Information using getMe Source: https://telegrambots.github.io/book/print.html Use your bot token to initialize the TelegramBotClient and call the getMe method to retrieve information about your bot. Replace YOUR_BOT_TOKEN with your actual bot token. ```csharp 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}."); ``` -------------------------------- ### Instantiate InlineQueryResultDocument using Constructor Source: https://telegrambots.github.io/book/migrate/Version-14.x.html Use the constructor with required properties to instantiate InlineQueryResultDocument. This is the preferred and safer way compared to object initialization, reducing the risk of exceptions. ```csharp // good way var documentResult = new InlineQueryResultDocument( id: "some-id", documentUrl: "https://example.com/document.pdf", title: "Some title", mimeType: "application/pdf" ); ``` -------------------------------- ### Create InlineKeyboardButton with LoginUrl Source: https://telegrambots.github.io/book/4/index.html Use this to create an inline button that initiates a login connection to your website using Telegram user credentials. Ensure your website domain is associated with your bot via @BotFather. ```csharp replyMarkup: InlineKeyboardButton.WithLoginUrl("login", new LoginUrl { Url = "https://yourdomain.com/url" }) ``` -------------------------------- ### Create Inline Keyboard with Callback Buttons Source: https://telegrambots.github.io/book/print.html Construct an inline keyboard with multiple rows and columns of buttons. Each button is defined by a tuple of (title, callbackData). Callback data is limited to 64 bytes. ```csharp // using Telegram.Bot.Types.ReplyMarkups; var sent = await bot.SendMessage(chatId, "A message with an inline keyboard markup", replyMarkup: new InlineKeyboardButton[][] { [("1.1", "11"), ("1.2", "12")], // two buttons on first row [("2.1", "21"), ("2.2", "22")] // two buttons on second row }); ``` -------------------------------- ### Static Sticker Set Methods Source: https://telegrambots.github.io/book/print.html Static .WEBP sticker set methods and requests are now prefixed with 'Static' to differentiate them from new video sticker methods. ```csharp Static ``` -------------------------------- ### Run the Console Application Source: https://telegrambots.github.io/book/print.html Execute the .NET console application to see the bot information printed to the console. This command compiles and runs your C# code. ```bash dotnet run ``` -------------------------------- ### Answering a Pre-Checkout Query Source: https://telegrambots.github.io/book/print.html Confirm or deny a PreCheckoutQuery within 10 seconds. This is done after the user has confirmed payment information. ```csharp if (confirm) await bot.AnswerPreCheckoutQuery(preCheckoutQuery.Id); // success else await bot.AnswerPreCheckoutQuery(preCheckoutQuery.Id, "Can't process your order: "); ``` -------------------------------- ### Dynamically Build InlineKeyboardMarkup Source: https://telegrambots.github.io/book/print.html Construct an InlineKeyboardMarkup programmatically. Supports adding single buttons, new rows, multiple buttons per row, and buttons with specific types like SwitchInlineQuery. ```csharp var replyMarkup = new InlineKeyboardMarkup() .AddButton(new InlineKeyboardButton("Link to Repository", "https://github.com/TelegramBots/Telegram.Bot")) .AddNewRow().AddButton("callback").AddButton("caption", "data") .AddNewRow("with", "three", "buttons") .AddNewRow().AddButtons("A", "B", new("switch", InlineButtonType.SwitchInlineQueryCurrentChat)); ``` -------------------------------- ### Instantiate InlineQueryResultDocument with Constructor Source: https://telegrambots.github.io/book/print.html Use the constructor with required properties to create an InlineQueryResultDocument. This is the preferred and safer way compared to object initialization. ```csharp var documentResult = new InlineQueryResultDocument( id: "some-id", title: "Some title", inputMessageContent: new InputTextMessageContent("https://example.com/document.pdf"), url: "https://example.com/document.pdf", mimeType: "application/pdf" ); ``` -------------------------------- ### Answer Shipping Query with Options Source: https://telegrambots.github.io/book/4/payments.html Respond to a ShippingQuery for physical goods by providing available shipping options. Each option can include multiple price lines for packaging and shipping. ```csharp var shippingOptions = new List(); shippingOptions.Add(new() { Title = "DHL Express", Id = "dhl-express", Prices = [("Shipping", 1200)] }); shippingOptions.Add(new() { Title = "FedEx Fragile", Id = "fedex-fragile", Prices = [("Packaging", 500), ("Shipping", 1800)] }); await bot.AnswerShippingQuery(shippingQuery.Id, shippingOptions); ``` -------------------------------- ### Send Video Note from File Source: https://telegrambots.github.io/book/print.html Send a video note by providing the chat ID and a stream to the video file. Duration and length (width/height) must be specified. Note that sending video notes via URL is not supported. ```csharp await using Stream stream = File.OpenRead("path/to/video-waves.mp4"); await bot.SendVideoNote(chatId, stream, duration: 47, length: 360); // length = width = height ``` -------------------------------- ### Create ChatPermissions with All True/False Source: https://telegrambots.github.io/book/migrate/Version-22.x.html Instantiate ChatPermissions with a boolean to set all fields to true or false simultaneously. This simplifies setting default permissions. ```csharp new ChatPermissions(true); ``` -------------------------------- ### Configure HTTP Proxy with WebProxy Source: https://telegrambots.github.io/book/print.html Configure HttpClient with WebProxy to use an HTTP proxy. This is useful when direct connections to Telegram servers may be blocked. Ensure the host and port are correctly specified. ```csharp // using System.Net; // using System.Net.Http; WebProxy webProxy = new (Host: "https://example.org", Port: 8080) { // Credentials if needed: Credentials = new NetworkCredential("USERNAME", "PASSWORD") }; HttpClient httpClient = new ( new HttpClientHandler { Proxy = webProxy, UseProxy = true, } ); var bot = new TelegramBotClient("YOUR_API_TOKEN", httpClient); ``` -------------------------------- ### Create Inline Keyboard with Switch to Inline Buttons Source: https://telegrambots.github.io/book/print.html Implement buttons that allow users to switch to an inline mode, either in the current chat or another chat. This is useful for sharing content or initiating inline searches. ```csharp // using Telegram.Bot.Types.ReplyMarkups; var sent = await bot.SendMessage(chatId, "A message with an inline keyboard markup", replyMarkup: new InlineKeyboardButton[] { new("switch_inline_query", InlineButtonType.SwitchInlineQuery), new("switch_inline_query_current_chat", InlineButtonType.SwitchInlineQueryCurrentChat) }); ``` -------------------------------- ### Send Message with Reply Keyboard for Contact and Location Source: https://telegrambots.github.io/book/print.html Create a reply keyboard with buttons that request the user's contact or location using factory methods. ```csharp // Message to a private chat having a 2-row reply keyboard await bot.SendTextMessageAsync( chatId: 1234, text: "Share your contact & location", replyMarkup: new ReplyKeyboardMarkup( new [] { KeyboardButton.WithRequestContact("Share Contact") }, new [] { KeyboardButton.WithRequestLocation("Share Location") }, ) ); ``` -------------------------------- ### Send Video with Streaming Support and Thumbnail Source: https://telegrambots.github.io/book/print.html Sends a video file from a URL, enabling streaming support and specifying a custom thumbnail. This allows users to seek through the video without downloading it completely. ```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); ``` -------------------------------- ### Send HTML Message with Local Streams Source: https://telegrambots.github.io/book/print.html Send local files as images by providing them as streams. Reference streams using 'stream://N' where N is the index in the provided streams list. ```csharp await using var stream0 = File.OpenRead(@"C:\Pictures\banner.png"); await using var stream1 = File.OpenRead(@"C:\Pictures\image.jpg"); var msg = await bot.SendHtml(chatId, """ """, streams: [stream0, stream1]); ``` -------------------------------- ### Upload Document from Local Machine Source: https://telegrambots.github.io/book/print.html Use this method to upload a document from your local file system. Ensure the file path is correct. Limitations apply for file sizes (50 MB for non-photos). ```csharp await using var stream = File.OpenRead("../hamlet.pdf"); var message = await bot.SendDocument(chatId, stream, "The Tragedy of Hamlet,\nPrince of Denmark"); ``` -------------------------------- ### Send Sticker by URL and File ID Source: https://telegrambots.github.io/book/print.html Sends the same sticker twice: first using a URL to a WebP file, and second by reusing the FileId of the previously sent sticker. ```csharp var message1 = await bot.SendSticker(chatId, "https://telegrambots.github.io/book/docs/sticker-fred.webp"); var message2 = await bot.SendSticker(chatId, message1.Sticker!.FileId); ``` -------------------------------- ### Handle Update in ASP.NET Core Minimal APIs Source: https://telegrambots.github.io/book/print.html This snippet demonstrates how to set up a POST endpoint in ASP.NET Core Minimal APIs to receive and handle Telegram updates. ```csharp app.MapPost("/bot", (Update update) => HandleUpdate(update)); ... async Task HandleUpdate(Update update) { // put your code to handle one Update here. } ``` -------------------------------- ### Download File Helper Source: https://telegrambots.github.io/book/migrate/Version-22.x.html Utilize the new DownloadFile helper method to download files associated with a TGFile object. This method simplifies file retrieval. ```csharp await Bot.DownloadFile(TGFile file, ...); ``` -------------------------------- ### Set Bot Commands with Scope Source: https://telegrambots.github.io/book/print.html Demonstrates setting bot commands for all private chats using `BotCommandScope.AllPrivateChats()`. Commands can be constructed from tuples. ```csharp await Bot.SetMyCommands([("/start", "Start the bot"), ("/privacy", "Privacy policy")], BotCommandScope.AllPrivateChats()); ``` -------------------------------- ### Send Invoice with Labeled Price Source: https://telegrambots.github.io/book/print.html Illustrates sending an invoice for a product, including a labeled price. The `LabeledPrice` can be constructed from a tuple. ```csharp await bot.SendInvoice(chatId, "Product", "Description", "ProductID", "XTR", [("Price", 500)]); ``` -------------------------------- ### Create Chat Invite Link Source: https://telegrambots.github.io/book/print.html Create a new invite link for a chat. This method allows for custom naming and additional parameters. ```csharp var link = await bot.CreateChatInviteLink(chatId, "name/reason", ...); Console.WriteLine(link.InviteLink); ``` -------------------------------- ### Restrict Chat Member and Send Message with Link Preview Source: https://telegrambots.github.io/book/print.html Demonstrates how to restrict a chat member (unmute) and send a message with a link preview enabled. The `ChatPermissions` constructor simplifies setting permissions. ```csharp await bot.RestrictChatMember(chatId, userId, new ChatPermissions(true)); // unmute ``` ```csharp await bot.SendMessage(msg.Chat, "Visit t.me/tgbot_net", replyParameters: msg, linkPreviewOptions: true); ``` -------------------------------- ### Building Inline Keyboards Dynamically Source: https://telegrambots.github.io/book/migrate/Version-21.x.html Use InlineKeyboardMarkup methods like AddButton, NewRow, and AddButtons to construct complex inline keyboards programmatically. Supports various button types including URLs and callback data. ```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")); ``` -------------------------------- ### Answer Inline Queries with Results Source: https://telegrambots.github.io/book/print.html This method handles incoming inline queries by generating a list of articles and sending them as a response. Each article includes an ID, title, and content. ```csharp async Task OnInlineQueryReceived(ITelegramBotClient bot, InlineQuery inlineQuery) { var results = new List(); var counter = 0; foreach (var site in sites) { results.Add(new InlineQueryResultArticle( $ירת{counter}", // we use the counter as an id for inline query results site, // inline query result title new InputTextMessageContent(siteDescriptions[counter])) // content that is submitted when the inline query result title is clicked ); counter++; } await bot.AnswerInlineQuery(inlineQuery.Id, results); // answer by sending the inline query result list } ``` -------------------------------- ### Inline Query Button Configuration Source: https://telegrambots.github.io/book/print.html The SwitchPmText and SwitchPmParameter properties have been replaced by the InlineQueryResultsButton type for configuring inline query buttons. ```csharp SwitchPmText ``` ```csharp SwitchPmParameter ``` ```csharp InlineQueryResultsButton ``` -------------------------------- ### InputFile Factory Methods for File Handling Source: https://telegrambots.github.io/book/print.html Use explicit InputType classes like InputFileStream, InputFileUrl, or InputFileId. The InputFile base class provides factory methods for convenience. ```csharp InputFile.FromStream(Stream stream, string? fileName = default) ``` ```csharp InputFile.FromString(string urlOrFileId) ``` ```csharp InputFile.FromUri(Uri url) ``` ```csharp InputFile.FromUri(string url) ``` ```csharp InputFile.FromFileId(string fileId) ``` -------------------------------- ### Send HTML Message with Multiple Images (Album) Source: https://telegrambots.github.io/book/print.html Send multiple images as an album. The caption provided will be attached to the last image in the sequence. ```csharp var msg = await bot.SendHtml(chatId, """ Album caption (attached to the last photo) """); ``` -------------------------------- ### Answer Pre-Checkout Query Source: https://telegrambots.github.io/book/4/payments.html Confirm or reject a pre-checkout query. Reply with success or an error message within 10 seconds to proceed with the payment. ```csharp if (confirm) await bot.AnswerPreCheckoutQuery(preCheckoutQuery.Id); // success else await bot.AnswerPreCheckoutQuery(preCheckoutQuery.Id, "Can't process your order: "); ``` -------------------------------- ### Create Inline Keyboard with URL Button Source: https://telegrambots.github.io/book/print.html Add a button to an inline keyboard that opens an external URL when pressed. The constructor automatically detects the second argument as a URL if it's not callback data. ```csharp // using Telegram.Bot.Types.ReplyMarkups; var sent = await bot.SendMessage(chatId, "A message with an inline keyboard markup", replyMarkup: new InlineKeyboardButton("Repository Link", "https://github.com/TelegramBots/Telegram.Bot")); ``` -------------------------------- ### Create Passport Authorization Request Parameters Source: https://telegrambots.github.io/book/print.html Constructs the parameters needed for a passport authorization request, specifying the bot ID, public key, nonce, and requested data scopes (e.g., address, phone number). ```csharp AuthorizationRequestParameters authReq = new AuthorizationRequestParameters( botId: 123456, // bot user ID publicKey: "...", // public key in PEM format. same as the key above. nonce: "unique nonce for this request", scope: new PassportScope { Data = [ new PassportScopeElementOne(EncryptedPassportElementType.Address), new PassportScopeElementOne(EncryptedPassportElementType.PhoneNumber) ] }); ``` -------------------------------- ### Download, Decrypt Passport File to Byte Array and Send Photo Source: https://telegrambots.github.io/book/print.html This snippet demonstrates handling a passport file as a byte array. It includes fetching file info, downloading the encrypted content, decrypting it, and then sending the resulting photo to a chat. ```csharp // fetch the info of the passport file(selfie) residing on Telegram servers TGFile encryptedFileInfo = await bot.GetFile(element.Selfie.FileId); // download the encrypted file and get its bytes byte[] encryptedContent; using (System.IO.MemoryStream stream = new System.IO.MemoryStream(encryptedFileInfo.FileSize) ) { await bot.DownloadFile(encryptedFileInfo, stream); encryptedContent = stream.ToArray(); } // decrypt the content and get bytes of the actual selfie photo byte[] selfieContent = decrypter.DecryptFile( encryptedContent, credentials.SecureData.DriverLicense.Selfie ); // send the photo to a chat using (System.IO.Stream stream = new System.IO.MemoryStream(selfieContent)) { await bot.SendPhoto( 123456, stream, "selfie with driver's license" ); } ``` -------------------------------- ### Handle Payments in Telegram Bot (C#) Source: https://telegrambots.github.io/book/print.html This C# code snippet demonstrates how to handle payment-related updates for a Telegram bot, including sending invoices, answering pre-checkout queries, and processing successful payments. Ensure you replace 'YOUR_BOT_TOKEN' with your actual bot token. ```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}: " + $ ``` -------------------------------- ### Unified Sticker Methods Source: https://telegrambots.github.io/book/print.html Methods distinguishing between animated, static, and video stickers have been replaced with a single set of sticker-related methods. Associated emojis and masks are now handled by the InputSticker type. ```csharp AddAnimatedStickerToSetAsync ``` ```csharp AddStaticStickerToSetAsync ``` ```csharp AddVideoStickerToSetAsync ``` -------------------------------- ### Answering a Shipping Query Source: https://telegrambots.github.io/book/print.html Respond to a ShippingQuery with a list of shipping options or an error. This is used for physical goods with flexible pricing. ```csharp var shippingOptions = new List(); shippingOptions.Add(new() { Title = "DHL Express", Id = "dhl-express", Prices = [("Shipping", 1200)] }); shippingOptions.Add(new() { Title = "FedEx Fragile", Id = "fedex-fragile", Prices = [("Packaging", 500), ("Shipping", 1800)] }); await bot.AnswerShippingQuery(shippingQuery.Id, shippingOptions); ``` -------------------------------- ### Download and Decrypt Passport File (Reverse Side) in Two Steps Source: https://telegrambots.github.io/book/4/passport/files-docs.html Downloads and decrypts the reverse side of a passport file in two distinct operations: first fetching and downloading to memory, then decrypting to a file stream. This provides more control than the single-step method. ```csharp File encryptedFileInfo; using (System.IO.Stream encryptedContent = new System.IO.MemoryStream(element.ReverseSide.FileSize), decryptedFile = System.IO.File.OpenWrite("/path/to/reverse-side.jpg") ) { // fetch the encrypted file info and download it to memory encryptedFileInfo = await bot.GetInfoAndDownloadFile( element.ReverseSide.FileId, // file_id of passport file for reverse side encryptedContent // stream to copy the encrypted file into ); // ensure memory stream is at the beginning before reading from it encryptedContent.Position = 0; // decrypt the file and write it to disk await decrypter.DecryptFileAsync( encryptedContent, credentials.SecureData.DriverLicense.ReverseSide, // reverse side FileCredentials decryptedFile // destination stream for writing the JPEG content to ); } ```