Crate telegram_bot2
source ·Expand description
Telegram bot
This crate provides an easy to use framework to build telegram bots. It is still in developpement, you may report bugs or request features on the project repo.
Workflow
The idea behind this framework is similar to rocket webservers. There is a main function that builds a bot using the BotBuilder
. Updates are fetched via long polling, then passed to handlers.
Building the bot
The recommended way to build the bot is to create a function annotated with #[bot]
, returning a BotBuilder
.
For more information, see BotBuilder
and #[bot]
#[bot]
async fn bot() -> _ {
BotBuilder::new()
.interval(Duration::from_secs(0))
.timeout(5)
.handler(handlers![handler])
.commands(commands![soup])
}
Note: The function does not need an explicit return type, as it is handled by the #[bot]
macro
Handlers
Handlers are async functions returning a Result<(), E> where E: Debug
(returning an Err will result in the program termination). They may take as many parameters as needed, but they all need to implement the FromUpdate
trait (a bunch of implementations is already provided). Specific handlers may take additional parameters
Generic handler
A generic handler is annotated with the #[handler]
attribute, and has no specific parameters.
The parameters of the functions are parsed using the FromUpdate
trait. If the parsing of any arguments fails, the next handler is tried, until one is successfully parsed.
The macro takes the following parameters:
rank
(usize): Defaults to 0. The priority of this handler, 0 being the highest (i.e. the first handler the be executed)restrict
(list ofUpdateType
): Defaults to all. The updates that may be passed to the handler
#[handler(rank = 1)]
async fn handler(message: &Message, bot: &Bot) -> Result<(), ()> {
bot.send_message(SendMessageBuilder::new(ChatId::from(message.chat.id), message.text.clone().unwrap()).build()).await.unwrap();
Ok(())
}
Command handler
A command handler is annotated with the #[command]
macro. It take as parameters the dynamic arguments of the command (see the syntax), and any type implementing FromUpdate
The function’s arguments are either extracted from the call (according to the syntax), or parsed with FromUpdate
The macro takes the following parameters:
- (String): Mandatory. the syntax of the command, as follows:
"/command_name [static|<dynamic>]*"
. Static parameters are constants, while dynamic parameters are parsed from the command and given to the handler withFromStr
#[command("/soup get <id>")]
async fn soup(bot: &Bot, chat: ChatId, id: i64) -> Result<(), ()> {
bot.send_message(SendMessageBuilder::new(chat, format!("Soup {} requested", id)).build()).await.unwrap();
Ok(())
}
In this example, the id parameter is parsed from the message, and has to be an i64. A valid call would be "/soup get 10"
, while "/soup get hi"
would not be parsed successfully
Daemons
You can setup daemons that are periodically called in background and can access the BotState. Daemon function are annotated with #[daemon]
and require an interval
parameter, which specifies the time between two calls (in seconds).
The interval time is the time between calls, it does not starts at the end of the last call. For example, if the interval is set to 60s and the daemon takes 5s to complete, the next call will proceeds 55s after the first one ends. The same daemon cannot be started if it is already running (i.e. a 5s daemon with interval of 1s will start as soon as it ends). The timer is precise at a millisecond order.
The parameters of the function are parsed by the FromDaemon
trait, at each call
The macro takes the following parameters:
interval
(usize): Mandatory. The time (in seconds) between two calls
#[daemon(interval = 5)]
async fn hello(state: &BotState<Mutex<usize>>) {
let mut lock = state.lock().unwrap();
*lock += 1;
println!("Increasing counter to {}", lock);
}
Re-exports
pub use log;