I built ferogram because I kept hitting walls with other MTProto libraries. Things that should have been straightforward weren't, and I kept needing the library to behave slightly differently than it would let me. So I wrote my own.
It talks to Telegram directly over MTProto, no Bot API proxy in between. It works for both bots and user accounts from the same API and the same client builder.
The major use cases are covered: messaging, media, inline keyboards, CDN downloads, FSM for multi-step conversations, FakeTLS and MTProxy for censored networks, and a raw invoke() escape hatch for anything the high-level API doesn't wrap yet.
If you want the Bot API instead, take a look at ferobot.
Ferogram is also available for Python as ferogram-py on PyPI, pre-built wheels, no Rust toolchain needed.
Note
ferogram is still in active development. It covers major use cases and runs in production, but the API may still shift.
[dependencies]
ferogram = "0.6.4"
tokio = { version = "1", features = ["full"] }Development on GitHub moves faster than crates.io. Releases are pushed to crates.io when there's a patch or a proper release, so there may be fixes and features on main or dev that aren't published yet. If you need something from main, you can point directly to a specific commit:
ferogram = { git = "https://github.com/ankit-chaubey/ferogram", rev = "COMMIT_SHA" }Otherwise, stable from crates.io is the safe default.
use ferogram::{Client, update::Update};
const API_ID: i32 = 0;
const API_HASH: &str = "";
#[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(())
}use ferogram::Client;
const API_ID: i32 = 0;
const API_HASH: &str = "";
#[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(())
}Ferogram includes a powerful dispatcher with composable filters (&, |, !), a flexible FSM with pluggable state storage, session backends, media transfer utilities, and much more.
For detailed usage examples and API documentation, check the README files and documentation of the dedicated crates in this workspace.
When the high-level API doesn't cover something, client.invoke() takes any TL function directly:
use ferogram::tl;
let req = tl::functions::bots::SetBotCommands {
scope: tl::enums::BotCommandScope::Default(tl::types::BotCommandScopeDefault {}),
lang_code: "en".into(),
commands: vec![tl::enums::BotCommand::BotCommand(tl::types::BotCommand {
command: "start".into(),
description: "Start the bot".into(),
})],
};
client.invoke(&req).await?;
client.invoke_on_dc(2, &req).await?;By default the session is a binary file on disk. Switch to SQLite, LibSQL (Turso), or a base64 string for serverless setups. You can also bring your own by implementing SessionBackend.
See This for the quick list with method signatures. Runnable examples are in ferogram/examples/.
If something is missing, open a feature request or drop by t.me/FerogramChat. If the high-level API isn't enough, the raw API is always there.
Secret Chats (end-to-end encrypted) are fully implemented but not published to crates.io yet. The plan is to release once there is enough community demand for it.
Group audio, video and P2P calling are now fully implemented. To get started, check out the tgcalls crate and its examples in tgcalls repository. It provides seamless integration between Ferogram and the official ntgcalls Rust bindings for building Telegram voice and video calling applications.
- Channel (releases, announcements): t.me/Ferogram
- Chat (questions, discussion): t.me/FerogramChat
- API docs: docs.rs/ferogram
Read contribution guide before opening a PR and as well Security issues: see security.md.
Big shoutout to Lonami for grammers. It was one of the most helpful references while building ferogram initially.
Protocol behavior references from Telegram Desktop and TDLib.
MIT OR Apache-2.0. See LICENSE-MIT and LICENSE-APACHE.
Usage must comply with Telegram's API Terms of Service.