We've worked hard during the last two weeks, and prepared two big features, a few smaller ones, аnd, of course, we didn't forget about Bot API 4.7. What's even better is that all the new features don't break compatibility, so we're releasing them in version 0.5.2!
Bot API 4.7 (#33)
Let's start with Bot API 4.7 first. Recently, Telegram released a feature everyone's been asking for years — rolling dice in chats. We can't help but support it in tbot
, so we've implemented the SendDice
method and the dice
handler on EventLoop
. Telegram now lets bots see and modify the list of their commands, and you can do it with the GetMyCommands
and SetMyCommands
methods. Lastly, bots now can create animated sticker sets, and the CreateNewStickerSet
and AddStickerToSet
methods have been updated accordingly.
tbot::state
, the stateful event loop (!173)
The next feature is amazing and you might've really wanted it. The new module tbot::state
introduces StatefulEventLoop
, as well as a couple state stores you'll likely need. To create a stateful event loop, call Bot::stateful_event_loop
instead of Bot::event_loop
:
let mut bot = tbot::from_env!("BOT_TOKEN").stateful_event_loop(initial_state);
The initial state can be absolutely anything (that you can share between threads), and all handlers will receive the state wrapped in an Arc
as their second argument:
use tokio::sync::Mutex;
let mut bot = tbot::from_env!("BOT_TOKEN")
.stateful_event_loop(Mutex::new(0));
bot.text(|context, counter| async move {
counter.lock().await += 1;
});
Each method that sets a handler has a corresponding method with the _if
postfix, that take a predicate and run the handler if the predicate returns true
:
let is_on_second_stage = |context, state| async move {
state.chats.get(&*context).await.stage == 2
};
bot.text_if(is_on_second_stage, |context, state| async move { .. });
The rest of StatefulEventLoop
's API is pretty much the same as the stateless's one, excepts for methods that go from a stateless to a stateful event loop and back or switch the state.
The last thing about state is two state stores tbot
provides out of the box: Chats
and Messages
, which store some state per each chat and message respectively. If you want to learn more, go check out tbot::state
's docs. Don't forget to take a look at our new two examples: a questionary (warning: zealotry!) and an anonymous messenger.
tbot::markup
, easy and fearless work with markup (!180)
If you ever worked with markup manually, you know it's pretty hard to escape all user input correctly so that it won't break your markup. tbot::markup
comes to the rescue, simplifying working with markup and making it fearless. It contains basic formatters like bold
and italic
, which you then pass to a markup formatter — markdown_v2
or html
— which does all the work applying formatters and escaping strings when turned into a string:
use tbot::markup::{bold, italic, markdown_v2};
let message = markdown_v2(bold((
"*This is <b>old, ",
italic("and this is bold and italic!"),
))).to_string();
println!("{}", message); // *\*This is <b\>old, _and this is bold and italic\!_*
To learn more, visit tbot::markup
's docs.
Miscellaneous
- Due to how the
ChatMethods
trait and its methods were defined, you couldn't write a generic handler with the context's trait bound includingChatMethods
. because when you'd call a method, the compiler would error saying that the method's input arguments need to live longer than the context. We fixed the lifetimes on the methods (this doesn't break anything, as it shortens inputs' lifetime, you can't use lifetimes on methods and the traits are sealed), but for compatibility we left the lifetime onChatsMethods
and other context traits. (!181) - Due to how Cargo handles features, when we introduced the
rustls
feature,hyper-proxy
was downloaded despite theproxy
feature being disabled. Instead of using ugly hacks, we decided to make proxy available without enabling theproxy
feature. (!183) - If you ever need to trace through
tbot
when debugging something,tbot
now logs all method calls and how the event loop handles updates usingtracing
. To see it, enabletbot
's logs on the trace level, seetracing
's Readme to learn how to do it. (!176) - Previously,
tbot
's webhook server accepted updates only on/
and ignored updates coming to all other URLs. Now, the URL on whichtbot
accepts updates can be configured withWebhook::accept_updates_on
. (!179) - We clarified the docs regarding commands with a bot's username (
/command@username
). Astbot
needs to know the bot's username to properly handle such commands in all circumstances, the username needs to be configured explicitly using eitherEventLoop::username
orEventLoop::fetch_username
. Now the docs ofcommand
and similar handler setters hint to these methods. (#34) - If Telegram returns
retry_after
whentbot
polls for updates,tbot
will now respect it. (!177)
It's a lot of features for a single update. Stay home and write bots in Rust with tbot
!