layer 0.4.4

Ergonomic Telegram MTProto library โ€” auto-generated TL types, raw API access, session management
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
<div align="center">

# โšก layer

**A modular, production-grade async Rust implementation of the Telegram MTProto protocol.**

[![Crates.io](https://img.shields.io/crates/v/layer-client?color=fc8d62&label=layer-client)](https://crates.io/crates/layer-client)
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license)
[![Rust](https://img.shields.io/badge/rust-2024_edition-f74c00)](https://www.rust-lang.org/)
[![TL Layer](https://img.shields.io/badge/TL%20Layer-224-8b5cf6)](https://core.telegram.org/schema)
[![Build](https://img.shields.io/badge/build-passing-brightgreen)](#)
[![Docs](https://img.shields.io/badge/docs-online-5865F2?style=flat-square&logo=mdbook)](https://github.ankitchaubey.in/layer/)
[![Channel](https://img.shields.io/badge/Telegram-@layer__rs-2CA5E0?logo=telegram)](https://t.me/layer_rs)
[![Chat](https://img.shields.io/badge/Telegram%20Chat-@layer__chat-2CA5E0?logo=telegram)](https://t.me/layer_chat)

*Written from the ground up to understand Telegram's internals at the lowest level.*

</div>

---

## ๐Ÿงฉ What is layer?

**layer** is a hand-crafted, bottom-up async Rust implementation of the
[Telegram MTProto](https://core.telegram.org/mtproto) protocol โ€” built not to
reinvent the wheel, but to *understand* it.

The core protocol pieces โ€” the `.tl` schema parser, the AES-IGE cipher, the
Diffie-Hellman key exchange, the MTProto session, the async update stream โ€” are
all written from scratch. The async runtime and a handful of well-known utilities
(`tokio`, `flate2`, `getrandom`) are borrowed from the ecosystem, because that's
just good engineering. The architecture draws inspiration from the excellent
[grammers](https://codeberg.org/Lonami/grammers) library.

The goal was never "yet another Telegram SDK." It was: *what happens if you sit
down and build every piece yourself, and actually understand why it works?*

> **๐ŸŽ“ Personal use & learning project** โ€” layer was built as a personal exploration:
> *learning by building*. The goal is to deeply understand Telegram's protocol by
> implementing every layer from scratch, not to ship a polished production SDK.
> Feel free to explore, learn from it, or hack on it!

> **โš ๏ธ Pre-production (0.x.x)** โ€” This library is still in early development.
> APIs **will** change without notice. **Not production-ready โ€” use at your own risk!**

---

## ๐Ÿ’ฌ Community

| | Link |
|---|---|
| ๐Ÿ“ข **Channel** (updates & releases) | [@layer_rs]https://t.me/layer_rs |
| ๐Ÿ’ฌ **Chat** (questions & discussion) | [@layer_chat]https://t.me/layer_chat |

---

## ๐Ÿ—๏ธ Crate Overview

| Crate | Description |
|---|---|
| [`layer-tl-parser`]./layer-tl-parser | Parses `.tl` schema text into an AST |
| [`layer-tl-gen`]./layer-tl-gen | Generates Rust code from the AST at build time |
| [`layer-tl-types`]./layer-tl-types | All Layer **224** constructors, functions and enums |
| [`layer-crypto`]./layer-crypto | AES-IGE, RSA, SHA, DH key derivation |
| [`layer-mtproto`]./layer-mtproto | MTProto session, DH exchange, message framing |
| [`layer-client`]./layer-client | High-level async client โ€” auth, bots, updates, 2FA, media |
| `layer-app` | Interactive demo binary (not published) |
| `layer-connect` | Raw DH connection demo (not published) |

```
layer/
โ”œโ”€โ”€ layer-tl-parser/   โ”€โ”€ Parses .tl schema text โ†’ AST
โ”œโ”€โ”€ layer-tl-gen/      โ”€โ”€ AST โ†’ Rust source (build-time)
โ”œโ”€โ”€ layer-tl-types/    โ”€โ”€ Auto-generated types, functions & enums (Layer 224)
โ”œโ”€โ”€ layer-crypto/      โ”€โ”€ AES-IGE, RSA, SHA, auth key derivation
โ”œโ”€โ”€ layer-mtproto/     โ”€โ”€ MTProto session, DH, framing, transport
โ”œโ”€โ”€ layer-client/      โ”€โ”€ High-level async Client API
โ”œโ”€โ”€ layer-connect/     โ”€โ”€ Demo: raw DH + getConfig
โ””โ”€โ”€ layer-app/         โ”€โ”€ Demo: interactive login + update stream
```

---

## ๐Ÿ†• What's New in v0.4.4

### Session Backends
- **`StringSessionBackend`** โ€” portable base64-encoded session. Store it in an env var, a DB column, or anywhere โ€” then restore it on the next run:
  ```rust
  // Export
  let s = client.export_session_string().await?;
  // Restore
  let (client, _shutdown) = Client::with_string_session(&s).await?;
  ```
- **`export_session_string()`** โ€” serialises the live session (auth key + DC + peer cache) to a printable string
- **`LibSqlBackend`** โ€” session backend for libsql/Turso databases (`features = ["libsql-session"]`)

### New Update Variants
- **`Update::ChatAction(ChatActionUpdate)`** โ€” fires when a user starts/stops typing, uploading, recording, etc.
- **`Update::UserStatus(UserStatusUpdate)`** โ€” fires when a contact's online status changes

### New Client Method
- **`sync_update_state()`** โ€” forces an immediate `updates.getState` round-trip to reconcile pts/seq after long disconnects

### Bug Fixes (7)
- `iter_participants` no longer silently truncates at 200 members โ€” pagination now correct for large channels/groups
- `GlobalSearchBuilder::fetch` no longer returns duplicate results across page boundaries
- `DownloadIter` last-chunk zero-padding fixed โ€” chunk trimmed to exact file size
- `send_chat_action` with `top_msg_id` (forum topic) no longer panics when used on a basic group
- `answer_inline_query` with an empty result list no longer triggers RPC `400 RESULTS_TOO_MUCH`
- `PossibleGapBuffer` memory leak fixed โ€” buffered updates now released after gap is resolved via `getDifference`
- `ban_participant` with a temporary unix timestamp no longer overflows on 32-bit targets

### Comprehensive Docs Rewrite
- All 25+ documentation pages audited, corrected, and expanded for 0.4.4
- New pages: **Session Backends**, **Search**, **Reactions**, **Admin & Ban Rights**, **Typing Guard**
- `SUMMARY.md` updated with all new sections

> See the full [CHANGELOG]CHANGELOG.md for complete history including v0.4.0's major additions (MTProto fixes, update engine, search, reactions, admin rights, and more).

---

## ๐Ÿš€ Quick Start

Add to your `Cargo.toml`:

```toml
[dependencies]
layer-client = "0.4.4"
tokio = { version = "1", features = ["full"] }
```

### ๐Ÿ‘ค User Account

```rust
use layer_client::{Client, Config, SignInError};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let (client, _shutdown) = Client::connect(Config {
        session_path: "my.session".into(),
        api_id:       12345,          // https://my.telegram.org
        api_hash:     "abc123".into(),
        ..Default::default()
    }).await?;

    if !client.is_authorized().await? {
        let token = client.request_login_code("+1234567890").await?;
        let code  = "12345"; // read from stdin

        match client.sign_in(&token, code).await {
            Ok(name) => println!("Welcome, {name}!"),
            Err(SignInError::PasswordRequired(t)) => {
                client.check_password(*t, "my_2fa_password").await?;
            }
            Err(e) => return Err(e.into()),
        }
        client.save_session().await?;
    }

    client.send_message("me", "Hello from layer! ๐Ÿ‘‹").await?;
    Ok(())
}
```

### ๐Ÿค– Bot

```rust
use layer_client::{Client, Config, update::Update};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let (client, _shutdown) = Client::connect(Config {
        session_path: "bot.session".into(),
        api_id:       12345,
        api_hash:     "abc123".into(),
        ..Default::default()
    }).await?;

    client.bot_sign_in("1234567890:ABCdef...").await?;
    client.save_session().await?;

    let mut updates = client.stream_updates();
    while let Some(update) = updates.next().await {
        match update {
            Update::NewMessage(msg) if !msg.outgoing() => {
                if let Some(peer) = msg.peer_id() {
                    client.send_message_to_peer(
                        peer.clone(),
                        &format!("Echo: {}", msg.text().unwrap_or("")),
                    ).await?;
                }
            }
            Update::CallbackQuery(cb) => {
                client.answer_callback_query(cb.query_id, Some("Done!"), false).await?;
            }
            _ => {}
        }
    }
    Ok(())
}
```

---

## โœ… What Is Supported

### ๐Ÿ” Cryptography
- AES-IGE encryption / decryption (MTProto 2.0)
- RSA encryption with Telegram's public keys
- SHA-1 and SHA-256 hashing
- Auth key derivation from DH nonce material
- PQ factorization (Pollard's rho)
- Diffie-Hellman shared secret computation

### ๐Ÿ“ก MTProto
- Full 3-step DH key exchange handshake
- MTProto 2.0 encrypted sessions
- Proper message framing (salt, session_id, msg_id, seq_no)
- `msg_container` (multi-message) unpacking
- gzip-packed response decompression
- Server salt tracking, pong, `bad_server_salt` handling
- `bad_msg_notification` handling
- Reconnect with exponential backoff + ยฑ20% jitter
- Network hint channel (`signal_network_restored()`) to skip backoff immediately

### ๐Ÿš‚ Transports
- **Abridged** โ€” default, single-byte length prefix (lowest overhead)
- **Intermediate** โ€” 4-byte LE length prefix, better proxy compat
- **Obfuscated2** โ€” XOR stream cipher over Abridged, bypasses DPI / MTProxy

### ๐Ÿ“ฆ TL Type System
- Full `.tl` schema parser
- Build-time Rust code generation
- All **Layer 224** constructors โ€” **2,329** definitions
- `Serializable` / `Deserializable` traits for all types
- `RemoteCall` trait for all RPC functions
- Optional: `Debug`, `serde`, `name_for_id(u32)`

### ๐Ÿ‘ค Auth
- Phone code login (`request_login_code` โ†’ `sign_in`)
- 2FA SRP password (`check_password`)
- Bot token login (`bot_sign_in`)
- Sign out (`sign_out`)
- DC migration โ€” `PHONE_MIGRATE_*`, `USER_MIGRATE_*`, `NETWORK_MIGRATE_*`
- FLOOD_WAIT auto-retry with configurable policy (`RetryPolicy` trait)
- Configurable I/O error retry treated as a flood-equivalent delay

### ๐Ÿ’ฌ Messaging
- Send text message by username/peer (`send_message`, `send_message_to_peer`)
- Send with full options โ€” reply_to, silent, schedule, no_webpage, entities, markup via `InputMessage` builder
- Send to Saved Messages (`send_to_self`)
- Edit message (`edit_message`)
- Edit inline bot message (`edit_inline_message`)
- Forward messages (`forward_messages`)
- Delete messages (`delete_messages`)
- Get messages by ID (`get_messages_by_id`)
- Get / delete scheduled messages
- Pin / unpin message, unpin all messages
- Get pinned message
- Send chat action / typing indicator (`send_chat_action`)
- `TypingGuard` โ€” RAII wrapper, keeps typing alive on an interval, auto-cancels on drop
- Send reactions (`send_reaction`)
- Mark as read, clear mentions

### ๐Ÿ“Ž Media
- Upload file from bytes โ€” sequential (`upload_file`) and concurrent parallel-parts (`upload_file_concurrent`)
- Upload from async `AsyncRead` stream (`upload_stream`)
- Send file as document or photo (`send_file`)
- Send multiple media in one album (`send_multi_media`)
- Download media to file (`download_media_to_file`)
- Chunked streaming download (`DownloadIter`)
- `Photo`, `Document`, `Sticker` ergonomic wrappers with accessors
- `Downloadable` trait for generic media location handling

### โŒจ๏ธ Keyboards & Reply Markup
- `InlineKeyboard` row builder
- Button types: callback, url, url_auth, switch_inline, switch_elsewhere, webview, simple_webview, request_phone, request_geo, request_poll, request_quiz, game, buy, copy_text
- Reply keyboard (standard keyboard) builder
- Answer callback query, answer inline query

### ๐Ÿ“‹ Text Parsing
- Markdown parser โ†’ `(plain_text, Vec<MessageEntity>)`
- HTML parser โ†’ `(plain_text, Vec<MessageEntity>)` (feature `html`)
- spec-compliant html5ever tokenizer replacing `parse_html` (feature `html5ever`)
- HTML generator (`generate_html`) always available, hand-rolled

### ๐Ÿ‘ฅ Participants & Chat Management
- Get participants, kick, ban with `BanRights` builder, promote with `AdminRightsBuilder`
- Get profile photos
- Search peer members
- Join chat / accept invite link
- Delete dialog

### ๐Ÿ” Search
- Search messages in a peer (`SearchBuilder`)
- Global search across all chats (`GlobalSearchBuilder`)

### ๐Ÿ“œ Dialogs & Iteration
- List dialogs (`get_dialogs`)
- Lazy dialog iterator (`iter_dialogs`)
- Lazy message iterator per peer (`iter_messages`)

### ๐Ÿ”— Peer Resolution
- Resolve username โ†’ peer (`resolve_username`)
- Resolve peer string (username, phone, `"me"`) โ†’ `InputPeer` (`resolve_peer`)
- Access-hash cache, restored from session across restarts

### ๐Ÿ’พ Session Persistence
- Binary file session (`BinaryFileBackend`) โ€” default
- In-memory session (`InMemoryBackend`) โ€” testing / ephemeral bots
- SQLite session (`SqliteBackend`) โ€” feature `sqlite`
- `SessionBackend` trait โ€” plug in any custom backend
- Catch-up mode (`Config::catch_up`) โ€” replay missed updates via `getDifference` on reconnect

### ๐ŸŒ Networking
- SOCKS5 proxy (`Config::socks5`, optional username/password auth)
- Multi-DC pool โ€” auth keys stored per DC, connections created on demand
- `invoke_on_dc` โ€” send a request to a specific DC
- Raw escape hatch: `client.invoke::<R>()` for any Layer 224 method not yet wrapped

### ๐Ÿ”” Updates
- Typed update stream (`stream_updates()`)
- `Update::NewMessage` / `MessageEdited` / `MessageDeleted`
- `Update::CallbackQuery` / `InlineQuery` / `InlineSend`
- `Update::Raw` โ€” unmapped TL update passthrough
- PTS / QTS / seq / date gap detection and fill via `getDifference`
- Per-channel PTS tracking

### ๐Ÿ›‘ Shutdown
- `ShutdownToken` returned from `Client::connect` โ€” call `.cancel()` to begin graceful shutdown
- `client.disconnect()` โ€” disconnect without token

---

## โŒ What Is NOT Supported

These are high level gaps, not planned omissions, just not built yet.
Use `client.invoke::<R>()` with raw TL types as a workaround for any of these.

| Feature | Notes |
|---|---|
| **Secret chats (E2E)** | MTProto layer-2 secret chats not implemented |
| **Voice / video calls** | No call signalling or media transport |
| **Payments** | `SentCode::PaymentRequired` returns an error; payment flow not implemented |
| **Group / channel creation** | `createChat`, `createChannel` not wrapped |
| **Channel admin tooling** | No channel creation, migration, linking, or statistics โ€” admin/ban rights are supported via `set_admin_rights` / `set_banned_rights` |
| **Sticker set management** | No `getStickerSet`, `uploadStickerFile`, etc. |
| **Account settings** | No profile update, privacy settings, notification preferences |
| **Contact management** | No `importContacts`, `deleteContacts` |
| **Poll / quiz creation** | No `InputMediaPoll` wrapper |
| **Live location** | Not wrapped |
| **Bot menu / command registration** | `setMyCommands`, `setBotInfo` not wrapped |
| **IPv6** | Config flag exists (`allow_ipv6: false`) but not tested |
| **MTProxy with proxy secret** | Obfuscated2 transport works; MTProxy secret mode untested |

---

## ๐Ÿ”ง Feature Flags

### `layer-tl-types`

| Feature | Default | Description |
|---|---|---|
| `tl-api` | โœ… | High-level Telegram API schema |
| `tl-mtproto` | โŒ | Low-level MTProto schema |
| `impl-debug` | โœ… | `#[derive(Debug)]` on generated types |
| `impl-from-type` | โœ… | `From<types::T> for enums::E` |
| `impl-from-enum` | โœ… | `TryFrom<enums::E> for types::T` |
| `name-for-id` | โŒ | `name_for_id(u32) -> Option<&'static str>` |
| `impl-serde` | โŒ | `serde::Serialize` / `Deserialize` |

### `layer-client`

| Feature | Default | Description |
|---|---|---|
| `html` | โŒ | Built-in hand-rolled HTML parser (`parse_html`, `generate_html`) |
| `html5ever` | โŒ | spec-compliant html5ever tokenizer replaces `parse_html` |
| `sqlite` | โŒ | SQLite session backend (`SqliteBackend`) |

---

## ๐Ÿ“ Updating to a New TL Layer

```bash
# 1. Replace the schema
cp new-api.tl layer-tl-types/tl/api.tl

# 2. Build โ€” types regenerate automatically
cargo build
```

---

## ๐Ÿงช Tests

```bash
cargo test --workspace
```

---

## ๐Ÿ“„ License

Licensed under either of, at your option:

- **MIT License** โ€” see [LICENSE-MIT]LICENSE-MIT
- **Apache License, Version 2.0** โ€” see [LICENSE-APACHE]LICENSE-APACHE

---

## ๐Ÿ‘ค Author

<div align="center">

### Ankit Chaubey

*Built with curiosity, caffeine, and a lot of Rust compiler errors. ๐Ÿฆ€*

| | |
|:---:|:---|
| ๐Ÿ™ **GitHub** | [github.com/ankit-chaubey]https://github.com/ankit-chaubey |
| ๐ŸŒ **Website** | [ankitchaubey.in]https://ankitchaubey.in |
| ๐Ÿ“ฌ **Email** | [ankitchaubey.dev@gmail.com]mailto:ankitchaubey.dev@gmail.com |
| ๐Ÿ“ฆ **Project** | [github.com/ankit-chaubey/layer]https://github.com/ankit-chaubey/layer |
| ๐Ÿ“ข **Channel** | [@layer_rs]https://t.me/layer_rs |
| ๐Ÿ’ฌ **Chat** | [@layer_chat]https://t.me/layer_chat |

</div>

---

## ๐Ÿ™ Acknowledgements

- [**Lonami**]https://codeberg.org/Lonami for
  [**grammers**]https://codeberg.org/Lonami/grammers.
  Portions of this project include code derived from the grammers project,
  which is dual-licensed under the MIT or Apache-2.0 licenses. The architecture,
  design decisions, SRP math, and session handling are deeply inspired by grammers.
  It's a fantastic library and an even better learning resource. Thank you for
  making it open source! ๐ŸŽ‰

- [**Telegram**]https://core.telegram.org/mtproto for the detailed MTProto specification.

- The Rust async ecosystem โ€” `tokio`, `getrandom`, `flate2`, and friends.

- ๐Ÿค– AI tools used for clearer documentation and better comments across the repo
  (2026 is a good year to use AI).  
  Even regrets ๐Ÿ˜ after making these docs through AI. iykyk.
  Too lazy to revert and type again, so it stays as is!

---

## โš ๏ธ Telegram Terms of Service

As with any third-party Telegram library, please ensure that your usage
complies with [Telegram's Terms of Service](https://core.telegram.org/api/terms).
Misuse or abuse of the Telegram API may result in temporary limitations or
permanent bans of Telegram accounts.

---

<div align="center">

*layer.. because sometimes you have to build it yourself to truly understand it.*

</div>