Skip to main content

botkit_matrix/
action.rs

1use std::time::Duration;
2
3use botkit_core::BotError;
4use botkit_core::action::{ChatAction, ChatActionFutureBounds, ChatActionSender};
5use matrix_sdk::Room;
6
7/// Matrix chat action sender
8///
9/// Sends typing notifications to Matrix rooms.
10#[derive(Clone)]
11pub struct MatrixActionSender {
12    room: Room,
13}
14
15impl MatrixActionSender {
16    /// Create a new Matrix action sender for the given room
17    pub fn new(room: Room) -> Self {
18        Self { room }
19    }
20}
21
22impl ChatActionSender for MatrixActionSender {
23    fn send_action(
24        &self,
25        action: ChatAction,
26    ) -> impl ChatActionFutureBounds<Output = Result<(), BotError>> + '_ {
27        async move {
28            // Matrix only supports typing indicators
29            if action == ChatAction::Typing {
30                self.room
31                    .typing_notice(true)
32                    .await
33                    .map_err(|e| BotError::Api(e.to_string()))?;
34            }
35            // Other actions are silently ignored - Matrix doesn't support them
36            Ok(())
37        }
38    }
39
40    fn action_expiry(&self) -> Duration {
41        // matrix-sdk sends a 4 second typing timeout and internally coalesces
42        // refreshes, so the core 80% renewal logic re-sends before expiry.
43        Duration::from_secs(4)
44    }
45
46    fn clear_action(&self) -> impl ChatActionFutureBounds<Output = Result<(), BotError>> + '_ {
47        // Unlike Discord and Telegram, a Matrix typing notice stays up until
48        // it is retracted or its timeout lapses, so retract it eagerly.
49        async move {
50            self.room
51                .typing_notice(false)
52                .await
53                .map_err(|e| BotError::Api(e.to_string()))
54        }
55    }
56}