Telegram.Bot.Mediator
1.0.17
dotnet add package Telegram.Bot.Mediator --version 1.0.17
NuGet\Install-Package Telegram.Bot.Mediator -Version 1.0.17
<PackageReference Include="Telegram.Bot.Mediator" Version="1.0.17" />
<PackageVersion Include="Telegram.Bot.Mediator" Version="1.0.17" />
<PackageReference Include="Telegram.Bot.Mediator" />
paket add Telegram.Bot.Mediator --version 1.0.17
#r "nuget: Telegram.Bot.Mediator, 1.0.17"
#:package Telegram.Bot.Mediator@1.0.17
#addin nuget:?package=Telegram.Bot.Mediator&version=1.0.17
#tool nuget:?package=Telegram.Bot.Mediator&version=1.0.17
🤖 Telegram.Bot.Mediator
A lightweight, state-based update routing framework for Telegram bots built on .NET. It simplifies bot architecture by organizing message handling logic into separate controllers and routing updates based on user states using a Finite State Machine (FSM).
📦 What's Inside
Controllers
Independent, scoped classes inheriting from BotControllerBase that encapsulate message handling logic. Each controller has immediate, thread-safe access to the request context (such as ChatId, UserId, and the raw Update object).
State-Based Routing
Declarative routing using attributes (BotCommand, BotTextMessage, BotCallback) that direct incoming messages to specific controller actions based on the user's active state in the Finite State Machine.
Automatic Discovery
Seamless registration using assembly scanning. The framework automatically discovers all classes implementing IBotController and registers them with a Scoped lifetime, allowing safe injection of database contexts (like EF Core DbContext) or other scoped services.
Hosted Update Loop
A default background service utilizing long polling to quickly bootstrap development, allowing your bot to handle updates with minimal boilerplate configuration.
Table of Contents
Installation
Install the package via .NET CLI:
dotnet add package Telegram.Bot.Mediator
Quick Start
1. Define User States (Enum)
Create an enum that represents the conversational steps or states of your user:
public enum UserState
{
Idle,
EnteringName,
EnteringAge
}
2. Create a Controller
All controllers must inherit from BotControllerBase. Use attributes to define the routing conditions for each method.
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegram.Bot.Mediator.Mediator.Abstractions;
using Telegram.Bot.Mediator.Mediator.Attributes;
using Telegram.Bot.Mediator.Mediator.State;
public class RegistrationController : BotControllerBase
{
private readonly IUserStateStorage<UserState> _stateStorage;
public RegistrationController(IUserStateStorage<UserState> stateStorage)
{
_stateStorage = stateStorage;
}
// Handles the /start command only if the user is in the Idle state
[BotCommand("/start", UserState.Idle)]
public async Task StartCommand(ITelegramBotClient bot, CancellationToken ct)
{
// ChatId and UserId are properties inherited from BotControllerBase
await bot.SendTextMessageAsync(ChatId, "Hello! Please enter your name:", cancellationToken: ct);
// Transition user to the next state
await _stateStorage.SetStateAsync(UserId, UserState.EnteringName, ct);
}
// Handles any text input while the user is in the EnteringName state
[BotTextMessage(UserState.EnteringName)]
public async Task HandleName(ITelegramBotClient bot, Message message, CancellationToken ct)
{
string name = message.Text ?? string.Empty;
await bot.SendTextMessageAsync(ChatId, $"Thank you, {name}! Now, please enter your age:", cancellationToken: ct);
await _stateStorage.SetStateAsync(UserId, UserState.EnteringAge, ct);
}
// Handles callback queries starting with "confirm_" while in the EnteringAge state
[BotCallback("confirm_", UserState.EnteringAge)]
public async Task HandleConfirmation(ITelegramBotClient bot, CallbackQuery callback, string parameter, CancellationToken ct)
{
// 'parameter' contains the callback data trailing after the prefix "confirm_"
await bot.SendTextMessageAsync(ChatId, $"Registration complete! Parameter received: {parameter}", cancellationToken: ct);
await _stateStorage.ClearStateAsync(UserId, ct);
}
}
3. Register Services in Program.cs
Configure the DI container using the provided extension methods. This registers the mediator, controller instances, and the polling background service.
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Telegram.Bot;
using Telegram.Bot.Mediator.Extensions;
var builder = Host.CreateApplicationBuilder(args);
// 1. Register the standard TelegramBotClient
builder.Services.AddSingleton<ITelegramBotClient>(provider =>
new TelegramBotClient("YOUR_TELEGRAM_BOT_TOKEN"));
// 2. Register mediator, in-memory state storage, and auto-discover controllers
builder.Services.AddTelegramMediator<UserState>();
// 3. Register the default polling service (handles Message and CallbackQuery updates by default)
builder.Services.AddTelegramBotHostedService<UserState>();
var host = builder.Build();
await host.RunAsync();
Advanced Concepts
Accessing Request Context
When inheriting from BotControllerBase, the following context properties are automatically resolved for each incoming update:
ChatId- The ID of the chat where the event occurred.UserId- The Telegram user ID who initiated the interaction.Update- The original rawUpdateobject received from the Telegram API.
This avoids writing repetitive boilerplate code to manually parse updates inside controller actions.
Custom State Storage
By default, AddTelegramMediator<TState> registers InMemoryStateStorage<TState>, which stores states in volatile memory. If your application restarts, active user states will be lost.
To persist states in a database (such as PostgreSQL, SQL Server, or Redis), implement the IUserStateStorage<TState> interface:
using Telegram.Bot.Mediator.Mediator.State;
public class MyDatabaseStateStorage : IUserStateStorage<UserState>
{
// Inject your DbContext, Redis multiplexer, or cache client here
public MyDatabaseStateStorage() { }
public async Task<UserState> GetStateAsync(long userId, CancellationToken ct = default)
{
// Fetch and return the state from your persistent store.
// Return default state (e.g. UserState.Idle) if no record is found.
return UserState.Idle;
}
public async Task SetStateAsync(long userId, UserState state, CancellationToken ct = default)
{
// Save the state associated with the given userId
}
public async Task ClearStateAsync(long userId, CancellationToken ct = default)
{
// Remove or reset the state for the given userId
}
}
Register your custom storage implementation as a singleton in Program.cs:
builder.Services.AddSingleton<IUserStateStorage<UserState>, MyDatabaseStateStorage>();
Custom Lifecycle and Update Customization
The default background service registered via AddTelegramBotHostedService<TState> polls for updates with standard configurations (restricted to UpdateType.Message and UpdateType.CallbackQuery).
If you need to support other update types, utilize Webhooks, or manage the receiver loop differently, you can omit the default background service and build your own.
To route updates manually, inject BotMediator<TState> into your custom receiver or controller, and pass incoming updates:
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegram.Bot.Mediator;
public class CustomUpdateReceiver
{
private readonly BotMediator<UserState> _mediator;
public CustomUpdateReceiver(BotMediator<UserState> mediator)
{
_mediator = mediator;
}
public async Task ProcessUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken ct)
{
// Pass the update to the mediator for routing and state-matching execution
await _mediator.HandleUpdateAsync(botClient, update, ct);
}
}
License
This project is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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.10)
- Microsoft.Extensions.Hosting (>= 10.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
- Telegram.Bot (>= 22.10.1)
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Hosting (>= 10.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
- Telegram.Bot (>= 22.10.1)
-
net9.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Hosting (>= 10.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
- Telegram.Bot (>= 22.10.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.