Module tbot::state::chats

source ·
Expand description

A storage of state per chat.

The Chats storage can be used to store some state for each chat separately. An example of it is a questionary bot when the bot collects some data from the user step-by-step:

enum Questionary {
    AskName,
    AskIfPraisedTheBorrowChecker {
        name: String,
    },
    Done {
        name: String,
        has_praised_the_borrow_checker: bool,
    },
}

Chats stores its states in a hash map where the key is the chat ID and the value is the state for the chat. As explained in docs for state, if you want to mutate state, you need to manually wrap it in a lock, and this applies to Chats as well. Let’s wrap our state in a Mutex:

use tbot::state::Chats;
use tokio::sync::Mutex;

let mut bot = tbot::from_env!("BOT_TOKEN")
    .stateful_event_loop(Mutex::new(Chats::new()));

Let’s start our questionary once the user starts the bot:

use tbot::prelude::*;

bot.start(|context, state| async move {
    state.lock().await.insert(&*context, Questionary::AskName);
    let call_result =
        context.send_message("Hello! What's your name?").call().await;

    if let Err(err) = call_result {
        dbg!(err);
    }
});

You can see that the insert method can figure out the chat ID from the context, but there’s still insert_by_id if you need it. In fact, Chats’s API is very similar to the API of std’s HashMap, but instead of the key you need to provide the context or use the equivalent method with the _by_id postfix.

If you need to, you can combine Chats with other state stores like this:

use tbot::state::Chats;
use tokio::sync::RwLock;

#[derive(Default)]
struct State {
    chats: RwLock<Chats<String>>,
    some_other_state: SomeOtherState,
}

let mut bot = tbot::from_env!("BOT_TOKEN")
    .stateful_event_loop(State::default());

Structs

A storage of state per chat. See the module’s docs to learn how to use it.
An iterator over the entries of Chats.
A mutable iterator over the entries of Chats.