Declarative design. teloxide is based upon [dptree
], a functional-style [chain of responsibility] pattern that allows you to express pipelines of message processing in a highly declarative and extensible style.
Dialogues management subsystem. Our dialogues management subsystem is simple and easy-to-use, and, furthermore, is agnostic of how/where dialogues are stored. For example, you can just replace a one line to achieve [persistence]. Out-of-the-box storages include [Redis] and [Sqlite].
Strongly typed commands. You can describe bot commands as enumerations, and then they'll be automatically constructed from strings — just like JSON structures in [serde-json
] and command-line arguments in [structopt
].
123456789:blablabla
.TELOXIDE_TOKEN
environmental variable to your token:
```bash
$ export TELOXIDE_TOKEN=
$ set TELOXIDE_TOKEN=
$ $env:TELOXIDE_TOKEN=
4. Make sure that your Rust compiler is up to date:
bash
$ rustup update stable $ rustup override set stable
$ rustup update nightly $ rustup override set nightly ```
cargo new my_bot
, enter the directory and put these lines into your Cargo.toml
:
toml
[dependencies]
teloxide = { version = "0.7", features = ["macros", "auto-send"] }
log = "0.4"
pretty_env_logger = "0.4.0"
tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] }
This bot replies with a dice throw to each received message:
(Full)
```rust,no_run use teloxide::prelude2::*;
async fn main() { teloxide::enablelogging!(); log::info!("Starting dicesbot...");
let bot = Bot::from_env().auto_send();
teloxide::repls2::repl(bot, |message: Message, bot: AutoSend<Bot>| async move {
bot.send_dice(message.chat.id).await?;
respond(())
})
.await;
} ```
Commands are strongly typed and defined declaratively, similar to how we define CLI using [structopt] and JSON structures in [serde-json]. The following bot accepts these commands:
/username <your username>
/usernameandage <your username> <your age>
/help
(Full)
```rust,no_run use teloxide::{prelude2::*, utils::command::BotCommand};
use std::error::Error;
enum Command { #[command(description = "display this text.")] Help, #[command(description = "handle a username.")] Username(String), #[command(description = "handle a username and an age.", parse_with = "split")] UsernameAndAge { username: String, age: u8 }, }
async fn answer(
bot: AutoSend
Ok(())
}
async fn main() { teloxide::enablelogging!(); log::info!("Starting simplecommands_bot...");
let bot = Bot::from_env().auto_send();
teloxide::repls2::commands_repl(bot, answer, Command::ty()).await;
} ```
A dialogue is typically described by an enumeration where each variant is one of possible dialogue's states. There are also state handler functions, which may turn a dialogue from one state to another, thereby forming an [FSM].
Below is a bot that asks you three questions and then sends the answers back to you:
(Full)
```rust,ignore use teloxide::{dispatching2::dialogue::InMemStorage, macros::DialogueState, prelude2::*};
type MyDialogue = Dialogue
pub enum State { #[handler(handle_start)] Start,
#[handler(handle_receive_full_name)]
ReceiveFullName,
#[handler(handle_receive_age)]
ReceiveAge { full_name: String },
#[handler(handle_receive_location)]
ReceiveLocation { full_name: String, age: u8 },
}
impl Default for State { fn default() -> Self { Self::Start } }
async fn main() { teloxide::enablelogging!(); log::info!("Starting dialoguebot...");
let bot = Bot::from_env().auto_send();
Dispatcher::builder(
bot,
Update::filter_message()
.enter_dialogue::<Message, InMemStorage<State>, State>()
.dispatch_by::<State>(),
)
.dependencies(dptree::deps![InMemStorage::<State>::new()])
.build()
.setup_ctrlc_handler()
.dispatch()
.await;
}
async fn handlestart(
bot: AutoSend
async fn handlereceivefullname(
bot: AutoSend
Ok(())
}
async fn handlereceiveage(
bot: AutoSendState::ReceiveAge
.
) -> anyhow::Result<()> {
match msg.text().map(|text| text.parse::
Ok(())
}
async fn handlereceivelocation(
bot: AutoSendState::ReceiveLocation
.
) -> anyhow::Result<()> {
match msg.text() {
Some(location) => {
let message = format!("Full name: {}\nAge: {}\nLocation: {}", fullname, age, location);
bot.sendmessage(msg.chat.id, message).await?;
dialogue.exit().await?;
}
None => {
bot.sendmessage(msg.chat.id, "Send me plain text.").await?;
}
}
Ok(())
} ```
Q: Where I can ask questions?
A:
Q: Do you support the Telegram API for clients?
A: No, only the bots API.
Q: Can I use webhooks?
A: teloxide doesn't provide special API for working with webhooks due to their nature with lots of subtle settings. Instead, you should setup your webhook by yourself, as shown in examples/ngrok_ping_pong_bot
and examples/heroku_ping_pong_bot
.
Associated links: - Marvin's Marvellous Guide to All Things Webhook - Using self-signed certificates
Q: Can I use different loggers?
A: Yes. You can setup any logger, for example, [fern], e.g. teloxide has no specific requirements as it depends only on [log]. Remember that [enable_logging!
] and [enable_logging_with_filter!
] are just optional utilities.
Feel free to propose your own bot to our collection!
:help
for Vim in Telegram.See CONRIBUTING.md
.