Note
Pre-production: APIs may change between minor versions. See CHANGELOG before upgrading.
Most users only need ferogram.
| Crate | Description |
|---|---|
ferogram |
High-level async client: auth, messaging, media, bots |
ferogram-session |
Session persistence types and storage backends |
ferogram-parsers |
Telegram Markdown and HTML entity parsers |
ferogram-tl-types |
Layer types, functions, enums (definitions) |
ferogram-mtproto |
MTProto session, DH exchange, framing, transports |
ferogram-crypto |
AES-IGE, RSA, SHA, Diffie-Hellman, auth key derivation |
ferogram-tl-gen |
Build-time code generator from the TL AST |
ferogram-tl-parser |
Parses .tl schema into an AST |
[dependencies]
ferogram = "0.3.0"
tokio = { version = "1", features = ["full"] }Get your api_id and api_hash from my.telegram.org.
Optional features:
ferogram = { version = "0.3.0", features = ["sqlite-session"] } # SQLite session
ferogram = { version = "0.3.0", features = ["libsql-session"] } # libsql / Turso
ferogram = { version = "0.3.0", features = ["html"] } # HTML parser
ferogram = { version = "0.3.0", features = ["html5ever"] } # html5ever parserferogram re-exports ferogram_tl_types as ferogram::tl.
use ferogram::{Client, update::Update};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let (client, _shutdown) = Client::builder()
.api_id(std::env::var("API_ID")?.parse()?)
.api_hash(std::env::var("API_HASH")?)
.session("bot.session")
.connect()
.await?;
client.bot_sign_in(&std::env::var("BOT_TOKEN")?).await?;
client.save_session().await?;
let mut stream = client.stream_updates();
while let Some(upd) = stream.next().await {
if let Update::NewMessage(msg) = upd {
if !msg.outgoing() {
if let Some(peer) = msg.peer_id() {
client.send_message_to_peer(peer.clone(), msg.text().unwrap_or("")).await?;
}
}
}
}
Ok(())
}use ferogram::{Client, SignInError};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (client, _shutdown) = Client::builder()
.api_id(12345)
.api_hash("your_api_hash")
.session("my.session")
.connect()
.await?;
if !client.is_authorized().await? {
let token = client.request_login_code("+1234567890").await?;
let code = read_line();
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 ferogram!").await?;
Ok(())
}| Backend | Flag | Notes |
|---|---|---|
BinaryFileBackend |
default | Single-process bots, scripts |
InMemoryBackend |
default | Tests, ephemeral tasks |
StringSessionBackend |
default | Serverless, env-var storage |
SqliteBackend |
sqlite-session |
Multi-session local apps |
LibSqlBackend |
libsql-session |
Turso / distributed storage |
| Custom | - | Implement SessionBackend |
let s = client.export_session_string().await?;
let (client, _) = Client::builder().session_string(s).connect().await?;Every Telegram API method is accessible via client.invoke():
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?;
// Target a specific DC
client.invoke_on_dc(2, &req).await?;cargo test --workspace
cargo test --workspace --all-featuresIntegration tests in ferogram/tests/integration.rs use InMemoryBackend and don't need real credentials.
- Channel: t.me/Ferogram
- Chat: t.me/FerogramChat
- Guide: ferogram.ankitchaubey.in
- API docs: docs.rs/ferogram
Read CONTRIBUTING.md before opening a PR. Run cargo test --workspace and cargo clippy --workspace locally. Security issues: see SECURITY.md.
Developed by Ankit Chaubey out of curiosity to explore.
ferogram is developed as part of exploration, learning, and experimentation with the Telegram MTProto protocol. Use it at your own risk. Its future and stability are not yet guaranteed.
Thanks to Lonami and the grammers project for early learning and inspiration in understanding MTProto structure.
Thanks to Telegram Desktop and TDLib for serving as references when implementing MTProto behavior.
Licensed under either of, at your option:
- MIT License: see LICENSE-MIT
- Apache License, Version 2.0: see LICENSE-APACHE
Unless you explicitly state otherwise, any contribution submitted for inclusion shall be dual-licensed as above, without any additional terms or conditions.
Ensure your usage complies with Telegram's Terms of Service and API Terms of Service. Misuse of the Telegram API, including spam, mass scraping, or automation of normal user accounts, may result in account limitations or permanent bans.