Expand description
A native, elegant MTProto framework for Rust.
ferogram talks to Telegram directly over MTProto, no Bot API proxy, and
handles auth for both bots and user accounts from the same client builder.
You get a dispatcher with composable filters, FSM for multi-step
conversations, CDN downloads, middleware, MTProxy support, and a raw
client.invoke() escape hatch for anything not wrapped yet.
Still in development but already covers major use cases for production. Check the CHANGELOG before upgrading.
§Quick start: bot
use ferogram::{Client, update::Update};
const API_ID: i32 = 0; // from https://my.telegram.org
const API_HASH: &str = ""; // from https://my.telegram.org
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let (client, _) = Client::quick_connect("bot.session", API_ID, API_HASH).await?;
let mut stream = client.stream_updates();
while let Some(upd) = stream.next().await {
if let Update::NewMessage(msg) = upd {
if !msg.outgoing() {
msg.reply(msg.text().unwrap_or_default()).await.ok();
}
}
}
Ok(())
}§Quick start: user account
use ferogram::Client;
const API_ID: i32 = 0; // from https://my.telegram.org
const API_HASH: &str = ""; // from https://my.telegram.org
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let (client, _) = Client::quick_connect("my.session", API_ID, API_HASH).await?;
client.send_message("me", "Hello from ferogram!").await?;
Ok(())
}§Dispatcher and filters
use ferogram::filters::{Dispatcher, command, private, text_contains};
let mut dp = Dispatcher::new();
dp.on_message(command("start"), |msg| async move {
msg.reply("Hello!").await.ok();
});
dp.on_message(private() & text_contains("help"), |msg| async move {
msg.reply("Type /start to begin.").await.ok();
});
while let Some(upd) = stream.next().await {
dp.dispatch(upd).await;
}Filters compose with &, |, !. Built-ins: command, private, group,
channel, text, media, photo, forwarded, reply, album, regex, and more.
§FSM
use std::sync::Arc;
#[derive(FsmState, Clone, Debug, PartialEq)]
enum Form { Name, Age }
dp.with_state_storage(Arc::new(MemoryStorage::new()));
dp.on_message_fsm(text(), Form::Name, |msg, state| async move {
state.set_data("name", msg.text().unwrap()).await.ok();
state.transition(Form::Age).await.ok();
msg.reply("How old are you?").await.ok();
});§Raw API
If something isn’t wrapped yet, you can call any TL function directly
(the current layer is exposed as tl::LAYER):
use ferogram::tl;
let req = tl::functions::messages::SendMessage {
peer: peer.into(),
message: "Hello!".into(),
random_id: ferogram::random_i64_pub(),
..Default::default()
};
client.invoke(&req).await?;§Session backends
Binary file by default. Switch to SQLite, libSQL, or a base64 string with a
feature flag. Bring your own backend by implementing SessionBackend.
// Portable string session, useful for serverless or env-var setups
let s = client.export_session_string().await?;
let (client, _) = Client::builder().session_string(s).connect().await?;
// SQLite (feature: sqlite-session)
Client::builder().session_backend(Arc::new(SqliteBackend::open("s.db")?));
// libSQL, local file or in-memory (feature: libsql-session)
Client::builder().session_backend(Arc::new(LibSqlBackend::open_local("s.db")?));
// Remote Turso, or a local file kept synced with one (feature: libsql-remote-session)
Client::builder().session_backend(Arc::new(LibSqlBackend::open_remote(url, token)?));
Client::builder().session_backend(Arc::new(LibSqlBackend::open_replica("s.db", url, token)?));§Cargo feature flags
Everything below is off by default; the default build is just login,
raw RPC (client.invoke()), and updates.
| Feature | Adds | Pulls in |
|---|---|---|
derive | #[derive(FsmState)] and other proc-macros | ferogram-derive |
sqlite-session | SQLite-backed session storage | rusqlite (bundled sqlite3, native build) |
libsql-session | libSQL-backed session storage (local/embedded replica) | libsql |
libsql-remote-session | Remote libSQL/Turso session storage with replication | libsql-session + replication |
serde | Serialize/Deserialize on session types | ferogram-session/serde |
fsm | FSM dispatcher helper (dp.on_message_fsm) | ferogram-fsm |
parsers / html | HTML/Markdown message parsing for rich text | ferogram-parsers |
html5ever | Stricter, spec-compliant HTML parsing | html5ever |
experimental | Experimental transfer APIs (resumable transfers) | mp4 |
resilient-connect | DNS-over-HTTPS + Firebase/Google config fallback for censored networks | reqwest (transitively rustls/aws-lc-rs) |
socks5 | SOCKS5 proxy support for outgoing connections | tokio-socks |
metrics | RPC/connection counters, histograms, gauges | metrics |
parser | Re-export the TL parser for custom tooling | ferogram-tl-parser |
codegen | Re-export the TL code generator for custom tooling | ferogram-tl-gen |
# Minimal: login, raw RPC, updates only
ferogram = { version = "0.6", default-features = false }
# A typical bot: rich text + FSM + SQLite sessions
ferogram = { version = "0.6", features = ["parsers", "fsm", "sqlite-session"] }Note: sqlite-session and libsql-session/libsql-remote-session are
mutually exclusive, both bundle a sqlite3 C source, and enabling both
at once fails at link time with duplicate-symbol errors. Pick one.
§What’s covered
- Rich Messaging: text, media, albums, polls, dice, games, reactions, scheduled messages
- HTML & Markdown: full parse and generate support for both formats
- Inline & Reply Keyboards: buttons, callbacks, inline mode
- CDN: transparent CDN download handling, no extra calls needed
- Proxy Support: SOCKS5 with optional auth
- MTProxy: Classic, DD, and FakeTLS transports, via link or manual config
- Transport Probing: races transports, connects via whichever is fastest
- Concurrent Transfers: parallel uploads/downloads with pause, resume, cancel, and progress tracking
- Resumable Transfers: checkpointed uploads/downloads that survive crashes
- Session Backends: file, in-memory, string, SQLite, LibSQL
- Router & Dispatcher: composable filters (
&,|,!) for expressive handlers - FSM: type-safe finite state machine for multi-step conversations
- Middleware: rate limiting, tracing, panic recovery
- TgCalls: group calls, P2P calls, conference calls, screen share/presentation, audio and video
- Raw API: full TL coverage via
client.invoke() - Python Bindings: native performance with a clean Python API
…and more features like this throughout the codebase!
Full list in FEATURES.md. Group calls, P2P calls, and screen share are handled separately by the tgcalls crate, built on top of ferogram and the official ntgcalls bindings.
If something’s missing, feel free to open a feature request or PR. Check the contributing guidelines first.
§Community
- Channel (releases, news): t.me/Ferogram
- Chat (questions, help): t.me/FerogramChat
- Docs: docs.ferogram.dev
- Website: ferogram.dev
- GitHub: ankit-chaubey/ferogram
Re-exports§
pub use media::DownloadIter;pub use builder::BuilderError;pub use builder::ClientBuilder;pub use file_info::FileInfo;pub use file_info::detect_mime;pub use file_info::file_info;pub use file_info::file_info_from_path;pub use guest_chat::GuestChatQuery;pub use keyboard::Button;pub use keyboard::InlineKeyboard;pub use keyboard::ReplyKeyboard;pub use media::Document;pub use media::DocumentThumb;pub use media::Downloadable;pub use media::MediaQuality;pub use media::Photo;pub use media::PhotoThumb;pub use media::ProfilePhoto;pub use media::RawLocation;pub use media::Sticker;pub use media::UploadedFile;pub use media::VideoQualityInfo;pub use media::video_cover;pub use participants::Participant;pub use participants::ParticipantStatus;pub use participants::ProfilePhotoIter;pub use peer_ext::OptionPeerExt;pub use peer_ext::PeerExt;pub use peer_ref::InviteHash;pub use peer_ref::PeerRef;pub use poll::PollBuilder;pub use proxy::parse_proxy_link;pub use search::GlobalSearchBuilder;pub use search::SearchBuilder;pub use transfer::TransferError;pub use transfer::TransferHandle;pub use transfer::TransferProgress;pub use transfer_limits::TransferLimits;pub use types::Channel;pub use types::ChannelKind;pub use types::Chat;pub use types::Community;pub use types::Group;pub use types::MessagePage;pub use types::User;pub use types::UserFull;pub use typing_guard::TypingGuard;pub use update::BotStoppedUpdate;pub use update::MessageReactionUpdate;pub use update::PollVoteUpdate;pub use update::ButtonFilter;pub use update::Update;pub use update::ChatActionUpdate;pub use update::JoinRequestUpdate;pub use update::ParticipantUpdate;pub use update::UserStatusUpdate;pub use update::ChatBoostUpdate;pub use update::PreCheckoutQueryUpdate;pub use update::ShippingQueryUpdate;pub use update_config::OverflowStrategy;pub use update_config::UpdateConfig;pub use ferogram_msgbox as message_box;pub use ferogram_tl_types as tl;pub use ferogram_mtproto as mtproto;pub use ferogram_crypto as crypto;pub use ferogram_tl_parser as parser;parserpub use ferogram_tl_gen as codegen;codegen
Modules§
- authentication
- MTProto authentication key generation (DH handshake steps).
- builder
- cdn_
download - Telegram CDN DC file downloads.
- conversation
- dc_
migration - dc_pool
- file_
info - File type detection and metadata extraction.
- filters
- fsm
fsm - guest_
chat - inline_
iter - keyboard
- macros
- media
- middleware
- parsers
parsers - participants
- peer_
ext - peer_
ref - persist
- poll
- proxy
- reactions
- search
- session_
backend - socks5
- string_
session - Portable string-session encoding/decoding (V1/V2 binary base64 format).
- transfer
- Transfer progress tracking, pause/resume/cancel controls, and typed transfer errors.
- transfer_
limits - User-tunable transfer concurrency: how hard Ferogram is allowed to push when uploading or downloading a file.
- types
- typing_
guard - update
- update_
config - Configuration for user-facing update buffering.
- util
Macros§
Structs§
- AuthKey
- A Telegram authorization key (256 bytes) plus pre-computed identifiers.
- Auto
Sleep - Automatically sleep on
FLOOD_WAITand retry once on transient I/O errors. - Binary
File Backend - Stores the session in a compact binary file (v2 format).
- Circuit
Breaker - A
RetryPolicythat stops retrying afterthresholdconsecutive failures and stays silent for acooldownwindow before resetting. - Client
- The main Telegram client. Cheap to clone: internally Arc-wrapped.
- Config
- Configuration for
Client::connect. - Copy
Options - Options for copying messages (forward without the “Forwarded from” attribution).
- DcEntry
- One entry in the DC address table.
- DcFlags
- Per-DC option flags.
- Dialog
- A Telegram dialog (chat, user, channel).
- Dialog
Cursor - Serializable snapshot of a
DialogIter’s position, for resuming pagination across app restarts (e.g. a chat list the user scrolled partway through, backgrounded, and reopened later). - Dialog
Filter Cursor - Serializable snapshot of a
DialogFilterIter’s position. Get one viaDialogFilterIter::cursor, resume withClient::iter_dialogs_in_filter_from. - Dialog
Filter Iter - Cursor-based iterator over dialogs in one chat folder (
DialogFilter). Created byClient::iter_dialogs_in_filter. - Dialog
Iter - Cursor-based iterator over dialogs. Created by
Client::iter_dialogs. - Dialogs
Stream - A boxed, nameable
futures::Streamover dialogs, giving access toStreamExt/TryStreamExtcombinators (.map(),.take(),.try_for_each(), etc.). Created byClient::stream_dialogs. - Experimental
Features - Opt-in experimental behaviours that deviate from strict Telegram spec.
- Exponential
Backoff - Exponential backoff with jitter.
- Finished
- The final output of a successful auth key handshake.
- Fixed
Interval - Flattened
Dialog Filter - Flattened, cheap-to-query form of a
tl::enums::DialogFilter. - Forward
Options - Options for forwarding messages.
- Full
Transport - MTProto Full transport framing.
- GetDialogs
Options - Options for
crate::Client::get_dialogs. Also used byDialogIterforexclude_pinned/folder_id(via its own builder methods -limitisn’t meaningful there,DialogIteralways pages at its own fixed size). - InMemory
Backend - Ephemeral in-process session: nothing persisted to disk.
- Input
Message - Builder for composing outgoing messages.
- Intermediate
Transport - MTProto Intermediate transport framing.
- Invoice
Options - Groups all invoice parameters for
crate::Client::send_invoice. - Login
Token - Token returned by
crate::Client::request_login_code. - Message
Iter - Cursor-based iterator over message history. Created by
Client::iter_messages. - Mini
AppSession - An active mini-app session returned by
Client::open_mini_app. - MtProxy
Config - Decoded MTProxy configuration.
- Never
Restart - NoRetries
- Never retry: propagate every error immediately.
- Obfuscated
Stream - Padded
Intermediate Transport - MTProto Padded Intermediate transport framing.
- Password
Token - 2FA challenge token returned in
SignInError::PasswordRequired. - Peer
Cache - All fields are
pubso thatsave_session/connectcan read/write them directly, and so that advanced callers can inspect the cache. - Peer
Cache Stats - Caches access hashes for users and channels so every API call carries the
correct hash without re-resolving peers.
A snapshot of what
PeerCachecurrently holds. - RaceLeg
- One leg of a transport race: transport plus its start delay.
- Retry
Context - Context passed to
RetryPolicy::should_retryon each failure. - RpcError
- An error returned by Telegram’s servers in response to an RPC call.
- Send
Code Options - Settings forwarded to Telegram’s
auth.sendCodecode_settingsfield. - SetProfile
Builder - Builder returned by
Client::set_profile. - Socks5
Config - SOCKS5 proxy configuration.
- Sqlite
Backend sqlite-session - SQLite-backed session (via
rusqlite). - String
Session Backend - Portable base64 string session backend.
- Update
Stream - Asynchronous stream of
crate::Updates.
Enums§
- Channel
Stats - Return type of
Client::stats. - Error
Kind - Invocation
Error - The error type returned from any
Clientmethod that talks to Telegram. - Link
Kind - Selects which flavour of message link
crate::Client::export_message_linkshould produce. - MiniApp
- Which kind of mini-app to open.
- Obfuscated
Framing - Framing mode for
ObfuscatedStream. - Peer
Type - Discriminates the kind of peer stored in
PeerCache::username_to_peer. - Quick
Connect Error - Errors returned by
Client::quick_connect. - Send
Code Outcome - Result of
crate::Client::request_login_code. - Sign
InError - Errors returned by
crate::Client::sign_in. - Transport
Kind - Which MTProto wire framing to use for a connection.
- Update
State Change - A single update-sequence change, applied via
SessionBackend::apply_update_state.
Constants§
- LAYER
- The API layer this code was generated from.
Traits§
- Connection
Restart Policy - FsmState
fsm - A type that can be used as an FSM state.
- Identifiable
- Every generated type has a unique 32-bit constructor ID.
- Invocation
Error Ext - Extension trait adding
.kind()and.friendly()toInvocationError. - Retry
Policy - Controls how the client reacts when an RPC call fails.
- Serializable
- Session
Backend - Synchronous snapshot backend: saves and loads the full session at once.
Functions§
- default_
transport_ race - Full vs Obfuscated. Abridged/Intermediate aren’t included since they share Full’s TCP path and framing fingerprint, so they live or die with it against DPI - racing them adds load with no extra chance of success.
- finish
- Finalise the handshake.
- random_
i64_ pub - Generate a random
i64. Used forrandom_idfields in RPC requests, where Telegram only needs uniqueness, not cryptographic strength. - step1
- Generate a
req_pq_multirequest. Returns the request + opaque state. - step2
- Process
ResPQand generatereq_DH_params. - step3
- Process
ServerDhParamsinto a reusableDhParamsForRetry+ send the firstset_client_DH_paramsrequest.
Type Aliases§
- Shutdown
Token - A token that can be used to gracefully shut down a
Client.