Televerseteleverse.

Features

Explore the powerful features that make Televerse the most advanced Telegram Bot framework in the Dart ecosystem.

🎯 Revolutionary Filter System

Televerse features a powerful filter system with 80+ built-in filters that can be combined using logical operators for expressive, type-safe update handling.

Basic Filters

Use bot.on() with any built-in filter to handle specific types of updates:

main.dart
// Simple filters
bot.on(bot.filters.photo, (ctx) async {
  await ctx.reply('Nice photo! 📸');
});

bot.on(bot.filters.video, (ctx) async {
  await ctx.reply('Cool video! 🎬');
});

bot.on(bot.filters.privateChat, (ctx) async {
  await ctx.reply('This is a private chat!');
});

Combining Filters with Operators

The real power comes from combining filters using logical operators:

  • + (OR) — Match either filter
  • * (AND) — Match both filters
  • - (NOT) — Match first but not second
main.dart
// OR operator (+) - matches photo OR video
bot.on(
  bot.filters.photo + bot.filters.video,
  (ctx) async {
    await ctx.reply('Media received!');
  },
);

// AND operator (*) - matches text AND in group
bot.on(
  bot.filters.text * bot.filters.groupChat,
  (ctx) async {
    await ctx.reply('Text message in group!');
  },
);

// NOT operator (-) - any message except commands
bot.on(
  bot.filters.anyMessage - bot.filters.command,
  (ctx) async {
    await ctx.reply('Non-command message!');
  },
);

// Complex combinations
bot.on(
  bot.filters.cmd('admin') * bot.filters.privateChat * bot.filters.user(adminId),
  adminHandler,
);

Available Filter Categories

• Media (photo, video, audio)• Chat types (private, group)• Message content (text, caption)• Entities (URL, mention, hashtag)• Service messages• Business features

🔌 Plugin Architecture

Televerse has a comprehensive plugin system with three built-in plugins and support for creating your own.

Session Plugin

Store and retrieve user-specific data across updates:

main.dart
import 'package:televerse/televerse.dart';

void main() async {
  final bot = Bot<Context>('YOUR_BOT_TOKEN');

  // Install the session plugin
  bot.plugin(SessionPlugin<Context, Map<String, dynamic>>(
    initial: () => {'visits': 0, 'preferences': {}},
    getSessionKey: (ctx) => 'user_${ctx.from?.id ?? 0}',
  ));

  // Use session in handlers
  bot.command('count', (ctx) async {
    final session = ctx.session as Map<String, dynamic>;
    session['visits'] = (session['visits'] as int) + 1;
    await ctx.reply('Visit count: ${session['visits']}');
  });

  await bot.start();
}

Conversation Plugin

Engage users in multi-step conversations with timeout handling and validation:

main.dart
// Install the conversation plugin
bot.plugin(ConversationPlugin<Context>());

// Define a conversation function
Future<void> askUserInfo(Conversation<Context> conversation, Context ctx) async {
  try {
    await ctx.reply("What's your name?");
    
    // Wait for text message with timeout
    final nameCtx = await conversation.waitFor(
      bot.filters.text.matches,
      timeout: Duration(minutes: 2),
    );
    
    await nameCtx.reply("Nice to meet you, ${nameCtx.text}!");
    
    await nameCtx.reply("How old are you?");
    
    // Wait with validation
    final ageCtx = await conversation.waitUntil(
      (ctx) => int.tryParse(ctx.text ?? '') != null,
      timeout: Duration(minutes: 1),
      otherwise: (ctx) async {
        await ctx.reply("Please send a valid number.");
      },
    );
    
    final age = int.parse(ageCtx.text!);
    await ageCtx.reply("Great! You are $age years old.");
    
  } on ConversationTimeoutException {
    await ctx.reply("Sorry, you took too long to respond.");
  }
}

// Register and use the conversation
bot.use(createConversation('userInfo', askUserInfo));

bot.command('info', (ctx) async {
  await ctx.conversation.enter('userInfo');
});

Logging Plugin

Enable detailed request/response logging with a single line:

main.dart
bot.plugin(LoggingPlugin<Context>());

🛠️ Middleware System

The middleware system provides powerful composition capabilities for processing updates:

main.dart
// Function-based middleware
bot.use((ctx, next) async {
  print('📥 Processing update ${ctx.update.updateId}');
  final start = DateTime.now();
  
  await next(); // Call next middleware
  
  final duration = DateTime.now().difference(start);
  print('✅ Processed in ${duration.inMilliseconds}ms');
});

// Conditional middleware
bot.when(
  (ctx) => ctx.isPrivateChat,
  (ctx, next) async {
    await ctx.reply('This is a private chat!');
    await next();
  },
);

// Forked middleware (runs concurrently)
bot.fork((ctx, next) async {
  await logToDatabase(ctx.update);
});

Middleware types include:

  • bot.use() — Standard middleware that runs for every update
  • bot.when() — Conditional middleware based on predicate
  • bot.fork() — Runs concurrently without blocking
  • bot.lazy() — Created on-demand based on context

🌐 Built-in Webhook Server

Start a production-ready webhook bot with just one method call. Perfect for serverless deployments and high-traffic bots:

main.dart
final bot = Bot<Context>('YOUR_BOT_TOKEN');

// Setup handlers
bot.command('start', (ctx) async {
  await ctx.reply('Hello from webhook bot! 🚀');
});

// Start webhook server - that's all you need!
await bot.startWebhook(
  webhookUrl: 'https://your-domain.com/webhook',
  port: 8080,
);

// For development with ngrok:
await bot.startWebhookDev('https://abc123.ngrok.io');

🎨 Custom Context

Extend the Context class with your own properties and methods for cleaner, more maintainable code:

main.dart
// Define your custom context
class MyContext extends Context {
  MyContext(super.update, super.api, super.me);
  
  // Add custom properties
  String get userName => from?.firstName ?? 'Unknown';
  bool get isAdmin => from?.id == 123456789;
  
  // Add custom methods
  Future<void> sendWelcome() async {
    await reply('Welcome, $userName! 🎉');
  }
}

// Use your custom context
final bot = Bot('YOUR_BOT_TOKEN', contextFactory: MyContext.new);

bot.command('start', (MyContext ctx) async {
  await ctx.sendWelcome(); // Use your custom method
  
  if (ctx.isAdmin) {
    await ctx.reply('You have admin access!');
  }
});

⌨️ Keyboard Utilities

Create reply keyboards and inline keyboards with intuitive builder classes:

main.dart
// Reply keyboard
final keyboard = Keyboard()
  ..text("Account")
  ..text("Settings")
  ..row()
  ..requestLocation("Send Location")
  ..resized()
  ..oneTime();

bot.command('menu', (ctx) async {
  await ctx.reply("Choose an option:", replyMarkup: keyboard);
});

// Inline keyboard with callbacks
final inlineKeyboard = InlineKeyboard()
  ..addButton(
    text: "Visit Website",
    url: "https://televerse.dev",
  )
  ..row()
  ..addButton(
    text: "Help",
    callbackData: "help_clicked",
  );

bot.command('links', (ctx) async {
  await ctx.reply("Useful links:", replyMarkup: inlineKeyboard);
});

// Handle callback queries
bot.callbackQuery('help_clicked', (ctx) async {
  await ctx.answer('Help is on the way!');
  await ctx.reply('Here is your help...');
});

🏠 Local Bot API Support

Host your own Bot API server for increased privacy, higher file size limits, and faster response times:

main.dart
// Use your own Bot API server
final bot = Bot.local(
  'YOUR_BOT_TOKEN',
  'http://localhost:8081',
);

// Everything works the same way!
bot.command('start', (ctx) async {
  await ctx.reply('Running on local Bot API server!');
});

await bot.start();

✨ And Much More

🛡️ Error Handling

Comprehensive error boundaries with context access for graceful error recovery.

📤 File Uploads

Easy file sending with InputFile class supporting files, URLs, and file IDs.

🔍 Inline Queries

Handle inline queries with the InlineQueryResultBuilder for all result types.

📋 Menu System

InlineMenu and KeyboardMenu classes with built-in handler registration.

Learn More

For complete API documentation and more examples, visit: