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] ```rust

[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. They may take as many parameters as needed, but they all need to implement the [FromUpdate][crate::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 macro may take those parameters: - rank(usize): the priority of this handler, 0 being the lowest - restrict (list of [UpdateType][crate::models::UpdateType]): the updates that may be passed to the handler ```rust

[handler]

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 #[bot_command] macro. It take as parameters the dynamic arguments of the command (see the syntax), and any type implementing [FromUpdate][crate::FromUpdate]

The #[bot_command] require a string literal as parameter, to specify the command's syntax. It must be as follow: "/command_name [static|<dynamic>]*", static parameters are constants, while dynamic parameters are parsed from the command and given to the handler ```rust

[bot_command("/soup get ")]

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"`.

Daemons

You can setup daemons that are periodically called in background and can access the BotState. Daemon function are annotated with [#[daemon]][macros::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][crate::FromDaemon] trait, at each call ```rust

[daemon(interval = 5)]

async fn hello(state: &BotState>) { let mut lock = state.lock().unwrap(); *lock += 1; println!("Increasing counter to {}", lock); } ```