Zaiets.TelegramBot.Lite
1.0.0
dotnet add package Zaiets.TelegramBot.Lite --version 1.0.0
NuGet\Install-Package Zaiets.TelegramBot.Lite -Version 1.0.0
<PackageReference Include="Zaiets.TelegramBot.Lite" Version="1.0.0" />
<PackageVersion Include="Zaiets.TelegramBot.Lite" Version="1.0.0" />
<PackageReference Include="Zaiets.TelegramBot.Lite" />
paket add Zaiets.TelegramBot.Lite --version 1.0.0
#r "nuget: Zaiets.TelegramBot.Lite, 1.0.0"
#:package Zaiets.TelegramBot.Lite@1.0.0
#addin nuget:?package=Zaiets.TelegramBot.Lite&version=1.0.0
#tool nuget:?package=Zaiets.TelegramBot.Lite&version=1.0.0
Zaiets.TelegramBot.Lite
Lightweight Telegram Bot API client for .NET 10 — send messages, build keyboards, handle webhooks and file uploads with minimal dependencies and a clean fluent API.
Author: Vladyslav Zaiets — CTO & Software Architect
Website: sarmkadan.com
Repository: github.com/Sarmkadan/Zaiets.TelegramBot.Lite
Installation
dotnet add package Zaiets.TelegramBot.Lite
Quick Start
ASP.NET Core / Generic Host (Recommended)
// Program.cs
builder.Services.AddTelegramBotClient("YOUR_BOT_TOKEN");
// Or bind from appsettings.json:
// builder.Services.AddTelegramBotClientFromConfiguration();
// appsettings.json
{
"Telegram": {
"Token": "123456789:AABBCCDDaabbccdd",
"DefaultParseMode": "HTML",
"HttpTimeout": "00:00:30"
}
}
Inject and use:
public class NotificationService(ITelegramBotClient bot)
{
public Task SendAsync(long chatId, string text, CancellationToken ct) =>
bot.SendMessageAsync(chatId, text, ct: ct);
}
Standalone (no DI)
var services = new ServiceCollection();
services.AddTelegramBotClient("YOUR_BOT_TOKEN");
var provider = services.BuildServiceProvider();
var bot = provider.GetRequiredService<ITelegramBotClient>();
var me = await bot.GetMeAsync();
Console.WriteLine($"Running as @{me.Username}");
Sending Messages
// Plain text
await bot.SendMessageAsync(chatId, "Hello!");
// HTML-formatted
await bot.SendMessageAsync(chatId, "<b>Bold</b> and <i>italic</i>", parseMode: "HTML");
// Disable notifications
await bot.SendMessageAsync(chatId, "Silent update", disableNotification: true);
// Reply to a message
await bot.SendMessageAsync(chatId, "Got it!", replyToMessageId: originalMessageId);
MessageBuilder — HTML helper
var text = MessageBuilder.Create()
.Bold("Order Confirmed")
.NewLine(2)
.Text("Reference: ")
.Code("ORD-20250501-001")
.NewLine()
.Text("Total: ")
.Bold("$49.99")
.NewLine(2)
.Link("View details", "https://example.com/orders/1")
.Build();
await bot.SendMessageAsync(chatId, text);
Keyboards
Inline Keyboard
var keyboard = InlineKeyboard.Create()
.AddRow()
.AddButton("Approve ✅", "action:approve")
.AddButton("Reject ❌", "action:reject")
.AddRow()
.AddUrlButton("Open Dashboard", "https://example.com/dashboard")
.Build();
await bot.SendMessageAsync(chatId, "Review request:", replyMarkup: keyboard);
Reply Keyboard
var keyboard = ReplyKeyboard.Create()
.AddRow("📦 Orders", "👤 Profile")
.AddRow("⚙️ Settings", "❓ Help")
.ResizeKeyboard()
.WithPlaceholder("Choose an option…")
.Build();
await bot.SendMessageAsync(chatId, "Main menu:", replyMarkup: keyboard);
Remove Keyboard
var remove = ReplyKeyboardRemoveMarkup.Create();
await bot.SendMessageAsync(chatId, "Keyboard dismissed.", replyMarkup: remove);
Handling Callback Queries
// Inside your update handler:
if (update.CallbackQuery is { } query)
{
await bot.AnswerCallbackQueryAsync(query.Id, "Processing…");
// ... handle query.Data
await bot.EditMessageTextAsync(
query.Message!.Chat.Id,
query.Message.MessageId,
"Done!");
}
File Uploads
// Upload a photo from a stream
await using var stream = File.OpenRead("report.png");
await bot.SendPhotoAsync(chatId, stream, "report.png", caption: "Monthly report");
// Upload a document
await using var pdf = File.OpenRead("invoice.pdf");
await bot.SendDocumentAsync(chatId, pdf, "invoice.pdf", caption: "Invoice #42");
// Re-use an existing file_id (no re-upload)
await bot.SendPhotoAsync(chatId, existingFileId, caption: "Cached photo");
Downloading Files
var fileInfo = await bot.GetFileAsync(fileId);
await using var dest = File.Create("download.jpg");
await bot.DownloadFileAsync(fileInfo.FilePath!, dest);
Webhooks
// Register webhook
await bot.SetWebhookAsync("https://yourdomain.com/bot/webhook", new SetWebhookParameters
{
MaxConnections = 40,
AllowedUpdates = [UpdateTypes.Message, UpdateTypes.CallbackQuery],
SecretToken = "my-secret-token",
DropPendingUpdates = true
});
// Check status
var info = await bot.GetWebhookInfoAsync();
Console.WriteLine($"Pending: {info.PendingUpdateCount}, Active: {info.IsActive}");
// Remove webhook (switch to long-polling)
await bot.DeleteWebhookAsync(dropPendingUpdates: true);
Minimal API webhook endpoint
app.MapPost("/bot/webhook", async (
TelegramUpdate update,
ITelegramBotClient bot,
CancellationToken ct) =>
{
if (update.Message?.Text is { } text)
await bot.SendMessageAsync(update.Message.Chat.Id, $"Echo: {text}", ct: ct);
return Results.Ok();
});
Long-Polling with UpdateDispatcher
var dispatcher = new UpdateDispatcher(bot, loggerFactory.CreateLogger<UpdateDispatcher>());
dispatcher.OnMessage += async (msg, ct) =>
{
if (msg.Text == "/start")
await bot.SendMessageAsync(msg.Chat.Id, "Welcome!", ct: ct);
};
dispatcher.OnCallbackQuery += async (query, ct) =>
{
await bot.AnswerCallbackQueryAsync(query.Id, $"You pressed: {query.Data}", ct: ct);
};
dispatcher.OnError += (ex, _) =>
{
Console.Error.WriteLine($"Handler error: {ex.Message}");
return Task.CompletedTask;
};
await dispatcher.StartAsync(cancellationToken);
Chat Actions
// Show "typing…" indicator while processing
await bot.SendChatActionAsync(chatId, "typing");
Supported actions: typing, upload_photo, record_video, upload_video, record_voice, upload_voice, upload_document, choose_sticker, find_location, record_video_note, upload_video_note.
Error Handling
All API errors throw TelegramBotException:
try
{
await bot.SendMessageAsync(chatId, text);
}
catch (TelegramBotException ex) when (ex.IsRateLimited)
{
var delay = ex.RetryAfter ?? 5;
await Task.Delay(TimeSpan.FromSeconds(delay));
// retry…
}
catch (TelegramBotException ex) when (ex.IsForbidden)
{
// User blocked the bot — remove from your DB
}
catch (TelegramBotException ex)
{
logger.LogError("Telegram error {Code}: {Message}", ex.ErrorCode, ex.Message);
}
API Reference
| Method | Description |
|---|---|
GetMeAsync |
Fetch bot identity |
SendMessageAsync |
Send a text message |
EditMessageTextAsync |
Edit a previously sent message |
DeleteMessageAsync |
Delete a message |
ForwardMessageAsync |
Forward a message between chats |
SendPhotoAsync |
Send a photo (stream or file_id/URL) |
SendDocumentAsync |
Send a file (stream or file_id/URL) |
SendChatActionAsync |
Show typing/uploading indicator |
AnswerCallbackQueryAsync |
Answer inline keyboard callbacks |
GetUpdatesAsync |
Long-poll for updates |
SetWebhookAsync |
Register a webhook URL |
DeleteWebhookAsync |
Remove the webhook |
GetWebhookInfoAsync |
Get webhook status |
GetFileAsync |
Get file metadata for download |
DownloadFileAsync |
Stream a file to a local Stream |
License
MIT © 2025 Vladyslav Zaiets — sarmkadan.com
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Http (>= 10.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Options (>= 10.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 100 | 5/3/2026 |