1use std::{cell::UnsafeCell, sync::Arc};
2
3use anyhow::Result;
4use state::TypeMap;
5
6use crate::{entry::Entry, event::Event, handler::Handler, plugin::AionPlugin, types::SetupFn};
7
8#[derive(Default)]
9pub struct StateManager(pub(crate) TypeMap!(Send + Sync));
10
11impl StateManager {
12 pub fn new() -> Self {
13 StateManager(<TypeMap![Send + Sync]>::new())
14 }
15
16 pub fn set<T: Send + Sync + 'static>(&self, state: T) {
17 self.0.set::<T>(state);
18 }
19
20 pub fn get<T: Send + Sync + 'static>(&self) -> &T {
21 self.0.get::<T>()
22 }
23
24 pub fn try_get<T: Send + Sync + 'static>(&self) -> Option<&T> {
25 self.0.try_get::<T>()
26 }
27
28 pub fn get_owned<T: Clone + Send + Sync + 'static>(&self) -> T {
29 self.0.get::<T>().to_owned()
30 }
31}
32
33pub struct Builder<R: Runtime + Default> {
34 handler: UnsafeCell<Handler>,
35 runtime: R,
36 state: Arc<StateManager>,
37 setup: Option<SetupFn<R>>,
38}
39
40impl<R> Builder<R>
41where
42 R: Runtime + Default + Send,
43{
44 pub fn setup(&mut self, setup: SetupFn<R>) {
45 self.setup = Some(setup);
46 }
47
48 pub fn invoke_handler<E: IntoIterator<Item = Entry>>(mut self, entries: E) -> Self {
49 self.handler.get_mut().extend(entries);
50 self
51 }
52
53 pub fn plugin(self, plugin: AionPlugin) -> Self {
54 self.invoke_handler(plugin.entries().to_vec())
55 }
56
57 pub fn manage<T: Send + Sync + 'static>(self, state: T) -> Self {
58 self.state.set(state);
59 self
60 }
61
62 async fn prepare(&mut self) -> Result<()> {
63 log::debug!("Preparing for runtime...");
64 self.runtime.prepare().await?;
65 if let Some(setup) = self.setup.take() {
66 log::debug!("Setting up runtime...");
67 self.runtime.setup(setup);
68 }
69 log::debug!("Finalizing runtime...");
70 self.runtime.finalize().await?;
71 Ok(())
72 }
73
74 pub async fn run(&mut self) -> Result<()> {
75 self.prepare().await?;
76
77 loop {
78 match self.runtime.run().await? {
79 RuntimeStatus::Exit => break,
80 RuntimeStatus::Next => {}
81 RuntimeStatus::Restart => {
82 log::info!("Restarting bot runtime...");
83 self.runtime.prepare().await?;
84 }
85 RuntimeStatus::Event(event) => {
86 let handler = unsafe { self.handler.get().as_mut() }.unwrap();
87 tokio::spawn(async move {
88 if let Err(e) = handler.input(Arc::new(event)).await {
89 log::error!("Error handling event: {}", e);
90 };
91 });
92 }
93 }
94 }
95 Ok(())
96 }
97}
98
99impl<R> Default for Builder<R>
100where
101 R: Runtime + Default + Send + 'static,
102{
103 fn default() -> Self {
104 let manager = Arc::new(StateManager::new());
105 let runtime = R::default().set_manager(manager.clone());
106 Self {
107 handler: UnsafeCell::new(Handler::empty()),
108 runtime,
109 state: Arc::clone(&manager),
110 setup: None,
111 }
112 }
113}
114
115pub trait Runtime {
116 #[must_use]
117 fn set_manager(self, manager: Arc<StateManager>) -> Self;
118
119 fn manager(&self) -> &StateManager;
120
121 fn prepare(&mut self) -> impl std::future::Future<Output = Result<()>> + Send {
122 async move { Ok(()) }
123 }
124
125 fn setup(&mut self, setup: SetupFn<Self>) {
126 setup(self)
127 }
128
129 fn finalize(&mut self) -> impl std::future::Future<Output = Result<()>> + Send {
130 async move { Ok(()) }
131 }
132
133 fn run(&mut self) -> impl std::future::Future<Output = Result<RuntimeStatus>> + Send;
134}
135
136pub enum RuntimeStatus {
137 Next,
138 Exit,
139 Restart,
140 Event(Box<dyn Event>),
141}