Skip to main content

shirabe_core/
app.rs

1use crate::{
2    adapter::Adapter,
3    bot::Bot,
4    context::{Context, state::EventSystemSharedState},
5    error::FrameworkResult,
6    plugin::Plugin,
7};
8use shirabe_utils::log;
9use std::sync::{Arc, RwLock};
10use tokio::runtime::Runtime;
11
12// 事件应用主结构
13pub struct App {
14    config: config::Config,
15    adapters: Vec<Arc<dyn Adapter>>,
16    plugins: Vec<Box<dyn Plugin>>,
17    shared_state: Arc<RwLock<EventSystemSharedState>>,
18}
19
20impl App {
21    pub fn new() -> Self {
22        App {
23            config: config::Config::default(),
24            adapters: Vec::new(),
25            plugins: Vec::new(),
26            shared_state: Arc::new(RwLock::new(EventSystemSharedState::default())),
27        }
28    }
29
30    /// 获取根事件上下文
31    pub fn context(&self) -> Context {
32        Context::new_root(Arc::clone(&self.shared_state))
33    }
34
35    /// 加载适配器
36    pub fn load_adapter(&mut self, adapter: impl Adapter + 'static) -> &mut Self {
37        self.adapters.push(Arc::new(adapter));
38        self
39    }
40
41    /// 加载插件
42    pub fn load_plugin(&mut self, plugin: impl Plugin + 'static) -> &mut Self {
43        self.plugins.push(Box::new(plugin));
44        self
45    }
46
47    /// 启动应用
48    pub fn run(&mut self) -> FrameworkResult<()> {
49        log::init_logger();
50        tracing::info!("启动应用……");
51
52        let rt = Runtime::new().unwrap();
53        // 加载配置文件
54        self.config = config::Config::builder()
55            .add_source(config::File::new("config", config::FileFormat::Toml))
56            .build()?;
57
58        // 获取应用根上下文
59        let app_root_context = Arc::new(self.context());
60        rt.block_on(async {
61            // --- 插件加载 ---
62            if !self.plugins.is_empty() {
63                tracing::info!("开始加载插件 (on_load)...");
64                for plugin in &self.plugins {
65                    let ctx_clone = Arc::clone(&app_root_context);
66                    tracing::debug!("调用插件 '{}' 的 on_load 方法", plugin.name());
67                    if let Err(e) = plugin.on_load().await {
68                        tracing::error!("插件 '{}' 的 on_load 方法执行失败: {}", plugin.name(), e);
69                    }
70                    match plugin.apply(ctx_clone).await {
71                        Ok(_) => {}
72                        Err(e) => {
73                            tracing::error!("插件{}启动失败: {:?}", plugin.name(), e)
74                        }
75                    }
76                }
77                tracing::debug!("所有插件启动完成。");
78            }
79            // --- 插件加载结束 ---
80
81            // --- 从adapters中加载适配器并启动bots ---
82            let mut bot_handlers = vec![];
83            if self.adapters.is_empty() {
84                tracing::warn!("没有加载任何适配器。应用将不会启动任何 Bot 或处理事件。");
85            }
86
87            for adapter_arc in &self.adapters {
88                let bot_context = Arc::clone(&app_root_context); // 每个 bot 共享根应用上下文的某些部分
89                let current_adapter_instance = Arc::clone(adapter_arc);
90
91                // 创建 Bot 实例
92                let bot = Arc::new(Bot::new(bot_context, current_adapter_instance));
93
94                // 将 Bot 实例注册到应用上下文中
95                // 这样插件或其他服务可以通过应用上下文访问到所有 Bot 实例
96                {
97                    let bots_arc_mutex = Arc::clone(&app_root_context.bots);
98                    let mut bots_guard = bots_arc_mutex.lock().unwrap();
99                    bots_guard.push(Arc::clone(&bot));
100                }
101
102                let bot_for_task = Arc::clone(&bot);
103                let platform = bot_for_task.platform.clone();
104                tracing::info!(
105                    "使用 {} 适配器启动机器人 (Platform: {})",
106                    adapter_arc.get_name(),
107                    platform
108                );
109
110                // 为每个 Bot 启动一个异步任务
111                let handle = tokio::spawn(async move {
112                    if let Err(e) = bot_for_task.start().await {
113                        tracing::error!("Bot {} 启动失败:{}", platform, e);
114                    } else {
115                        tracing::info!("Bot {} 已停止", platform);
116                    }
117                });
118                bot_handlers.push(handle);
119            }
120
121            // 等待所有 Bot 任务完成
122            if !bot_handlers.is_empty() {
123                tracing::info!("所有 Bot 任务已派生,应用正在运行。等待 Bot 任务完成...");
124                for handle in bot_handlers {
125                    if let Err(e) = handle.await {
126                        tracing::error!("一个 Bot 任务执行时发生错误: {:?}", e);
127                    }
128                }
129                tracing::info!("所有 Bot 任务已完成。");
130            } else if self.adapters.is_empty() {
131                tracing::info!("由于没有加载适配器,所以没有 Bot 启动。");
132            } else {
133                tracing::info!("适配器已加载,但没有 Bot 任务被创建或成功启动。");
134            }
135        });
136
137        tracing::info!("应用已关闭");
138
139        Ok(())
140    }
141}
142
143impl Default for App {
144    fn default() -> Self {
145        Self::new()
146    }
147}