Teleflutter

pub package Dart SDK License: MIT

A pure-Dart implementation of the Telegram MTProto protocol, heavily inspired by Telethon. Works on Flutter (Android, iOS, Web, Desktop) and plain Dart.

Status: The MTProto transport layer (connection, encryption, auth-key exchange, send/recv loops, session persistence) is fully implemented. High-level API methods (sendMessage, getDialogs, etc.) require the generated TL schema to be wired up — contributions welcome.


Features

  • 🔐 MTProto 2.0 — full AES-IGE encryption, SHA-256 key derivation, DH key exchange
  • 🔌 Multiple transports — TCP Full, TCP Intermediate, TCP Abridged
  • 💾 Session managementMemorySession and StringSession (serialisable, copy-pasteable)
  • 📦 Core TL objectsRpcResult, MessageContainer, GzipPacked, TLMessage
  • 📝 Markdown & HTML parsers — parse/unparse Telegram formatting entities
  • 🔄 Event system — subscribe to NewMessage, MessageEdited, ChatAction, etc.
  • 🔁 Auto-reconnect — configurable retries and back-off
  • 🪵 Structured logging — via the logging package

Getting started

Add to your pubspec.yaml:

dependencies:
  teleflutter: ^1.42.0

Then run:

dart pub get
# or
flutter pub get

Usage

import 'package:teleflutter/teleflutter.dart';

void main() async {
  // Use ':memory:' for a temporary session, or a StringSession string to resume.
  final client = TelegramClient(
    ':memory:',   // session
    12345,        // your api_id from https://my.telegram.org
    'your_api_hash',
  );

  await client.connect();
  print('Connected: ${client.isConnected}');

  // Listen for incoming messages
  client.on(NewMessage(incoming: true), (event) {
    final msg = event as NewMessageEvent;
    print('Message: ${msg.text}');
  });

  // Keep running until you call disconnect()
  // await client.disconnect();
}

Session persistence

// Save session to a string (survives restarts)
final session = StringSession();
final client = TelegramClient(session, apiId, apiHash);
await client.connect();
final saved = session.encode(); // store this somewhere safe

// Restore later
final client2 = TelegramClient(StringSession(saved), apiId, apiHash);

Markdown parsing

import 'package:teleflutter/src/extensions/markdown.dart';

final (text, entities) = parseMarkdown('**bold** and __italic__ with `code`');
// text     → 'bold and italic with code'
// entities → [MessageEntityBold, MessageEntityItalic, MessageEntityCode]

// Round-trip back to markdown
final markdown = unparseMarkdown(text, entities);
// → '**bold** and __italic__ with `code`'

Architecture

lib/src/
├── client/          # TelegramClient — public-facing API
├── crypto/          # AES-IGE, RSA, AuthKey, Diffie-Hellman
├── network/         # MTProtoSender, MTProtoState, connections
│   └── connection/  # TCP Full / Intermediate / Abridged transports
├── sessions/        # MemorySession, StringSession
├── events/          # NewMessage, MessageEdited, ChatAction, Raw, …
├── extensions/      # BinaryReader/Writer, Markdown parser, HTML parser
├── tl/              # TL object base classes and core objects
│   └── core/        # RpcResult, MessageContainer, GzipPacked, TLMessage
└── errors/          # Typed error hierarchy (RpcError, FloodWaitError, …)

Error handling

Teleflutter throws typed exceptions so you can handle Telegram-specific errors precisely:

try {
  await client.sendMessage(peer, 'Hello!');
} on FloodWaitError catch (e) {
  print('Rate limited — wait ${e.seconds}s');
} on PhoneMigrateError catch (e) {
  print('Account is on DC ${e.dcId}');
} on RpcError catch (e) {
  print('Telegram error ${e.errorCode}: ${e.errorMessage}');
}

Contributing

  1. Fork and clone the repo.
  2. Make your changes — run dart analyze and dart test before submitting.
  3. Open a pull request describing what you changed and why.

Bug reports and feature requests are welcome via GitHub Issues.


License

MIT — see LICENSE.

Teleflutter is an independent project and is not affiliated with or endorsed by Telegram.

Libraries

teleflutter