Skip to main content

ferogram_fsm/
key.rs

1/*
2 * Copyright (c) 2026 Ankit Chaubey <ankitchaubey.dev@gmail.com>
3 * https://github.com/ankit-chaubey
4 *
5 * Project: ferogram
6 * Website: https://ferogram.dev
7 *
8 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
9 * https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
10 * <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
11 * This file may not be copied, modified, or distributed except according
12 * to those terms.
13 */
14
15/// Minimal view of an incoming message needed to build a [`StateKey`].
16///
17/// Implement this for your message type in the consumer crate so that
18/// `StateKey::from_message` can work without a direct dependency on
19/// `ferogram` itself.
20pub trait MessageLike {
21    fn sender_user_id(&self) -> Option<i64>;
22    fn chat_id(&self) -> i64;
23}
24
25/// Identifies which conversation slot to read/write state for.
26///
27/// The canonical strategy is per-user-per-chat so that the same user can
28/// have independent sessions in different chats simultaneously.
29#[derive(Debug, Clone, PartialEq, Eq, Hash)]
30pub struct StateKey {
31    /// The Telegram user ID, if applicable.
32    pub user_id: Option<i64>,
33    /// The Telegram chat ID.
34    pub chat_id: i64,
35}
36
37impl StateKey {
38    /// Construct a key from an incoming message using the given strategy.
39    pub fn from_message(msg: &impl MessageLike, strategy: StateKeyStrategy) -> Self {
40        match strategy {
41            StateKeyStrategy::PerUserPerChat => Self {
42                user_id: msg.sender_user_id(),
43                chat_id: msg.chat_id(),
44            },
45            StateKeyStrategy::PerUser => Self {
46                user_id: msg.sender_user_id(),
47                chat_id: 0,
48            },
49            StateKeyStrategy::PerChat => Self {
50                user_id: None,
51                chat_id: msg.chat_id(),
52            },
53        }
54    }
55}
56
57/// How the FSM key is composed from an incoming message.
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
59pub enum StateKeyStrategy {
60    /// Track state per user per chat (recommended for most bots). Default.
61    #[default]
62    PerUserPerChat,
63    /// Track state per user across all chats (global user session).
64    PerUser,
65    /// Track state per chat, regardless of sender (e.g. group games).
66    PerChat,
67}