Televerseteleverse.

Transformers

Intercept, modify, and handle Telegram Bot API requests with the powerful Transformer system.

Overview

Transformers are a powerful feature in Televerse that allow you to intercept and modify outgoing API requests before they are sent to the Telegram servers.

Think of Transformers as middleware for API calls. While normal middleware handles incoming updates (from Telegram to your bot), Transformers handle outgoing requests (from your bot to Telegram).

Transformers vs Middleware

  • Middleware: Intercepts incoming updates (e.g. messages, callback queries).
  • Transformers: Intercepts outgoing API calls (e.g. sendMessage, editMessageText).

How It Works

Transformers form a chain around the raw API caller. When you make an API call (like ctx.reply or bot.api.sendMessage), the request passes through all registered transformers in order.

Each transformer can:

  • Modify the request: Change parameters, headers, or the API method itself.
  • Perform side effects: Log the request, update metrics, or trigger other actions.
  • Intercept the response: Modify the data returned by Telegram before it reaches your code.
  • Handle errors: Catch exceptions and retry the request or return a fallback value.
  • Cancel the request: Prevent the call from ever reaching the network.

Using Transformers

To use a transformer, you simply attach it to the bot.api instance using the use method.

// Create a transformer (example)
class MyTransformer extends Transformer {
  
  Future<Map<String, dynamic>> transform(
    APICaller call, 
    APIMethod method, 
    [Payload? payload]
  ) async {
    print("Calling method: ${method.name}");
    return await call(method, payload);
  }
}

// Attach it to your bot
bot.api.use(MyTransformer());

Creating a Custom Transformer

To create a custom transformer, extend the Transformer abstract class and implement the transform method.

The transform method receives:

  • call: A function representing the next step in the chain (either another transformer or the actual network request).
  • method: The API method being called (e.g., APIMethod.sendMessage).
  • payload: The data payload (parameters and files) for the request.

Example: Logging Transformer

Here is a simple transformer that logs the time taken for each API call.

class PerformanceLogger extends Transformer {
  
  Future<Map<String, dynamic>> transform(
    APICaller call, 
    APIMethod method, 
    [Payload? payload]
  ) async {
    final stopwatch = Stopwatch()..start();
    
    try {
      // Continue the chain
      final result = await call(method, payload);
      
      print('✅ ${method.name} took ${stopwatch.elapsedMilliseconds}ms');
      return result;
    } catch (e) {
      print('❌ ${method.name} failed after ${stopwatch.elapsedMilliseconds}ms');
      rethrow;
    }
  }
}

Example: Auto-Retry Transformer

Transformers are excellent for implementing reliability logic like automatic retries. We have a dedicated plugin for this called auto_retry.

Check out the auto_retry package on pub.dev for a production-ready implementation.

import 'package:auto_retry/auto_retry.dart';

// Use the AutoRetry plugin
bot.plugin(AutoRetryPlugin(
  maxRetryAttempts: 5,
  rethrowInternalServerErrors: true,
  enableLogs: true,
));

Transformer Plugins

If you are building a reusable package or just want to organize your code better, you can use the TransformerPlugin interface. This allows users to install your transformer using the standard bot.use or bot.install (if it's a plugin).

class MyPlugin extends TransformerPlugin {
  
  Transformer get transformer => MyTransformer();
  
  
  String get name => 'my-plugin';
  
  
  void install(Bot bot) {
    // Automatically attaches the transformer
    super.install(bot); 
    // You can also add more initialization logic here
  }
}

// Usage
bot.install(MyPlugin());

Under The Hood

Deep down, the RawAPI class maintains a TransformerManager. When you call bot.api.transformers, you can see the list of active transformers.

You can also remove transformers if needed:

// Remove a specific transformer instance
bot.api.removeTransformer(myTransformer);

// Remove all transformers of a specific type
bot.api.removeTransformersOfType<LoggingTransformer>();

// Clear all transformers
bot.api.clearTransformers();