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
12pub 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 pub fn context(&self) -> Context {
32 Context::new_root(Arc::clone(&self.shared_state))
33 }
34
35 pub fn load_adapter(&mut self, adapter: impl Adapter + 'static) -> &mut Self {
37 self.adapters.push(Arc::new(adapter));
38 self
39 }
40
41 pub fn load_plugin(&mut self, plugin: impl Plugin + 'static) -> &mut Self {
43 self.plugins.push(Box::new(plugin));
44 self
45 }
46
47 pub fn run(&mut self) -> FrameworkResult<()> {
49 log::init_logger();
50 tracing::info!("启动应用……");
51
52 let rt = Runtime::new().unwrap();
53 self.config = config::Config::builder()
55 .add_source(config::File::new("config", config::FileFormat::Toml))
56 .build()?;
57
58 let app_root_context = Arc::new(self.context());
60 rt.block_on(async {
61 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 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); let current_adapter_instance = Arc::clone(adapter_arc);
90
91 let bot = Arc::new(Bot::new(bot_context, current_adapter_instance));
93
94 {
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 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 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}