Skip to main content

teamtalk/bot/
runtime.rs

1use super::router::HandlerResult;
2use super::{MemoryStateStore, Router, Scheduler, StateStore};
3use crate::client::Client;
4use crate::events::Result;
5use std::sync::Arc;
6use std::sync::atomic::{AtomicBool, Ordering};
7
8#[derive(Debug, Clone, Copy)]
9pub struct BotConfig {
10    pub poll_timeout_ms: i32,
11}
12
13impl Default for BotConfig {
14    fn default() -> Self {
15        Self {
16            poll_timeout_ms: 100,
17        }
18    }
19}
20
21impl BotConfig {
22    pub fn new() -> Self {
23        Self::default()
24    }
25
26    pub fn poll_timeout_ms(mut self, timeout_ms: i32) -> Self {
27        self.poll_timeout_ms = timeout_ms;
28        self
29    }
30}
31
32pub struct Bot {
33    client: Client,
34    router: Router,
35    scheduler: Scheduler,
36    state: Box<dyn StateStore>,
37    stop: Arc<AtomicBool>,
38    config: BotConfig,
39}
40
41pub struct BotBuilder {
42    client: Client,
43    router: Router,
44    scheduler: Scheduler,
45    state: Box<dyn StateStore>,
46    config: BotConfig,
47}
48
49impl BotBuilder {
50    pub fn new(client: Client) -> Self {
51        Self {
52            client,
53            router: Router::new(),
54            scheduler: Scheduler::new(),
55            state: Box::new(MemoryStateStore::new()),
56            config: BotConfig::default(),
57        }
58    }
59
60    pub fn with_router(mut self, router: Router) -> Self {
61        self.router = router;
62        self
63    }
64
65    pub fn with_scheduler(mut self, scheduler: Scheduler) -> Self {
66        self.scheduler = scheduler;
67        self
68    }
69
70    pub fn with_state_store(mut self, store: impl StateStore + 'static) -> Self {
71        self.state = Box::new(store);
72        self
73    }
74
75    pub fn with_boxed_state_store(mut self, store: Box<dyn StateStore>) -> Self {
76        self.state = store;
77        self
78    }
79
80    pub fn with_config(mut self, config: BotConfig) -> Self {
81        self.config = config;
82        self
83    }
84
85    pub fn build(self) -> Bot {
86        Bot {
87            client: self.client,
88            router: self.router,
89            scheduler: self.scheduler,
90            state: self.state,
91            stop: Arc::new(AtomicBool::new(false)),
92            config: self.config,
93        }
94    }
95}
96
97impl Bot {
98    pub fn builder(client: Client) -> BotBuilder {
99        BotBuilder::new(client)
100    }
101
102    pub fn stop_handle(&self) -> Arc<AtomicBool> {
103        Arc::clone(&self.stop)
104    }
105
106    pub fn request_stop(&self) {
107        self.stop.store(true, Ordering::Relaxed);
108    }
109
110    pub fn run(&mut self) -> Result<()> {
111        while !self.stop.load(Ordering::Relaxed) {
112            if let Some((event, message)) = self.client.poll(self.config.poll_timeout_ms) {
113                let outcome =
114                    self.router
115                        .dispatch(&self.client, event, &message, self.state.as_mut())?;
116                if matches!(outcome, HandlerResult::Stop) {
117                    self.request_stop();
118                }
119            }
120            self.scheduler.tick(&self.client, self.state.as_mut())?;
121        }
122        Ok(())
123    }
124
125    pub fn router_mut(&mut self) -> &mut Router {
126        &mut self.router
127    }
128
129    pub fn scheduler_mut(&mut self) -> &mut Scheduler {
130        &mut self.scheduler
131    }
132
133    pub fn state_mut(&mut self) -> &mut dyn StateStore {
134        self.state.as_mut()
135    }
136
137    pub fn client(&self) -> &Client {
138        &self.client
139    }
140}