Skip to content

ankit-chaubey/ferogram

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

ferogram

Async Rust library for Telegram's MTProto protocol.

Crates.io docs.rs License TL Layer Telegram Channel Telegram Chat

Built by Ankit Chaubey

Note

ferogram is still in development but already covers major use cases for production. Check CHANGELOG before upgrading.

What it is

ferogram is an MTProto client library for Rust. It works for both user accounts and bots, and talks to Telegram directly over MTProto with no Bot API HTTP proxy in between.

The goal is to eventually support multiple languages from the same Rust core, so you can write your bot in whatever language you prefer. Python is already live as a working example of that via ferogram-py on PyPI.

Installation

[dependencies]
ferogram = "0.4.0"
tokio    = { version = "1", features = ["full"] }

Get api_id and api_hash from my.telegram.org. For optional features see the ferogram crate.

Quick start: bot

use ferogram::{Client, update::Update};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let (client, _) = 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?;

    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, SignInError};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let (client, _) = Client::builder()
        .api_id(std::env::var("API_ID")?.parse()?)
        .api_hash(std::env::var("API_HASH")?)
        .session("my.session")
        .connect().await?;

    if !client.is_authorized().await? {
        let token = client.request_login_code("+1234567890").await?;
        match client.sign_in(&token, &read_line()).await {
            Ok(_) => {}
            Err(SignInError::PasswordRequired(t)) => {
                client.check_password(*t, &read_line()).await?;
            }
            Err(e) => return Err(e.into()),
        }
        client.save_session().await?;
    }

    client.send_message("me", "Hello from ferogram!").await?;
    Ok(())
}

Features

Most common use cases are already covered. See FEATURES.md for the full list. Working examples are in ferogram/examples/.

If something's missing, open a feature request or send a PR. Just make sure to read the contributing guidelines before you do.

If the high-level API doesn't cover what you need, you can always fall through to the raw API with client.invoke().

Raw API

If you need to call something that isn't wrapped yet, 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?;

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 include command, private, group, channel, text, media, forwarded, reply, album, custom, and more.

FSM

use ferogram::{FsmState, fsm::MemoryStorage};
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();
});

Storage is swappable. Implement StateStorage to use Redis, a database, or anything else.

Session backends

Session is stored as a binary file by default. Switch to SQLite or libSQL with a feature flag, or use a base64 string for serverless setups where you can't write to disk. You can also bring your own backend by implementing SessionBackend. See ferogram-session for full details.

let s = client.export_session_string().await?;
let (client, _) = Client::builder().session_string(s).connect().await?;

Language bindings

Python support is live via ferogram-py. Install it with pip and you're good to go, no Rust toolchain required, wheels are pre-built for major platforms.

pip install ferogram

More language targets are planned.

Crates

Most users only need the ferogram crate. If you need something lower-level like just the MTProto layer, crypto primitives, or the TL type generator on its own, see the workspace crates overview.

Testing

cargo test --workspace
cargo test --workspace --all-features

Community

Contributing

Read CONTRIBUTING.md before opening a PR. Run cargo fmt --all, cargo test --workspace and cargo clippy --workspace first. Security issues: see SECURITY.md.

Author

Ankit Chaubey

I built ferogram because I was already using other MTProto libraries but kept running into cases where I needed things to work a bit differently than they allowed. So I wrote my own.

It covers the major use cases and that was the primary goal. If something's missing for you, feel free to drop by t.me/FerogramChat and say hi. I genuinely like hearing what people are building with it. Just keeping it real though, every new feature is more to maintain, so I'm a bit selective. But I still love to hear from you.

If ferogram has been useful, a star or fork means a lot. And if you want to contribute, even better.

Acknowledgments

Big shoutout to Lonami for grammers. It was genuinely one of the most helpful references while building ferogram, and honestly grammers and Telethon are two of my all-time favorites that I've been using for years. Love those projects.

Protocol behavior references from Telegram Desktop and TDLib.

License

MIT OR Apache-2.0. See LICENSE-MIT and LICENSE-APACHE.

Usage must comply with Telegram's API Terms of Service.

About

⚡ High-performance Telegram MTProto framework written in Rust for building powerful Telegram clients, apps, and bots.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages