Middleware
Build powerful, modular bot logic with the Middleware system.
Middleware is the backbone of any complex Televerse bot. It allows you to intercept, process, and modify updates before they reach your final command handlers. Think of it as a pipeline where each update flows through a series of functions.
Developer Note: Mastering middleware is key to building scalable bots. It lets you separate concerns like logging, authentication, and error handling from your business logic.
Basic Usage
The use method is the simplest way to add middleware. It takes a function receiving the context and a next function. Calling next() passes control to the next middleware in the chain.
// Basic logging middleware
bot.use((ctx, next) async {
final startTime = DateTime.now();
await next();
final duration = DateTime.now().difference(startTime);
print('Update processed in ${duration.inMilliseconds}ms');
});Advanced Composition
Televerse provides specialized methods to compose middleware in powerful ways. These help you organize your bot's logic cleanly and efficiently.
Named Middleware
Use useNamed to attach a name to your middleware. This is invaluable when debugging, as stack traces or logs can refer to the middleware by name instead of an anonymous function.
// Named middleware helps with debugging
bot.useNamed('logger', (ctx, next) async {
print('Processing update: ${ctx.update.updateId}');
await next();
});Conditional Execution
The when method executes middleware only if a specific condition (predicate) is met. This is great for filtering updates, like applying logic only to private chats or specific users.
// Only runs for private chats
bot.when(
(ctx) => ctx.chat?.type == ChatType.private,
(ctx, next) async {
await ctx.reply('This is a private chat!');
await next();
},
);Concurrent Execution (Fork)
Sometimes you want to run a task without delaying the bot's response, like analytics or database logging.fork runs the middleware appropriately without awaiting it in the main flow.
// Runs concurrently without blocking the main flow
bot.fork((ctx) async {
await database.logUpdate(ctx.update);
// No need to call next() in forked middleware
});Branching Logic
branch lets you split your middleware flow into two paths. Use this for things like separate logic for admins vs. regular users, or handling different types of updates distinctly.
// Branch execution based on a condition
bot.branch(
(ctx) => ctx.command == 'admin',
(ctx, next) async {
await ctx.reply('Welcome, Admin!');
// Admin middleware chain...
},
(ctx, next) async {
await ctx.reply('Access Denied');
},
);Dynamic Middleware (Lazy)
With lazy, you can generate middleware on the fly for each update. This is useful when the middleware logic depends on values available only in the context, like user settings or database states.
// Create middleware dynamically based on context
bot.lazy((ctx) {
if (ctx.from?.isPremium == true) {
return (ctx, next) async {
print('Update from a premium user');
await next();
};
}
return (ctx, next) => next();
});Why use Middleware?
Using these tools makes your code:
- Modular: Break down complex logic into small, reusable functions.
- Clean: Keep your main handlers focused on their specific task.
- Robust: Handle global concerns like errors and logging in one place.
- Efficient: Use
forkto keep your bot responsive even during heavy background tasks.