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}