# Walle-core ![OneBot11](https://img.shields.io/badge/OneBot-11-black?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAMAAADxPgR5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRF////29vbr6+vAAAAk1hCcwAAAAR0Uk5T////AEAqqfQAAAKcSURBVHja7NrbctswDATQXfD//zlpO7FlmwAWIOnOtNaTM5JwDMa8E+PNFz7g3waJ24fviyDPgfhz8fHP39cBcBL9KoJbQUxjA2iYqHL3FAnvzhL4GtVNUcoSZe6eSHizBcK5LL7dBr2AUZlev1ARRHCljzRALIEog6H3U6bCIyqIZdAT0eBuJYaGiJaHSjmkYIZd+qSGWAQnIaz2OArVnX6vrItQvbhZJtVGB5qX9wKqCMkb9W7aexfCO/rwQRBzsDIsYx4AOz0nhAtWu7bqkEQBO0Pr+Ftjt5fFCUEbm0Sbgdu8WSgJ5NgH2iu46R/o1UcBXJsFusWF/QUaz3RwJMEgngfaGGdSxJkE/Yg4lOBryBiMwvAhZrVMUUvwqU7F05b5WLaUIN4M4hRocQQRnEedgsn7TZB3UCpRrIJwQfqvGwsg18EnI2uSVNC8t+0QmMXogvbPg/xk+Mnw/6kW/rraUlvqgmFreAA09xW5t0AFlHrQZ3CsgvZm0FbHNKyBmheBKIF2cCA8A600aHPmFtRB1XvMsJAiza7LpPog0UJwccKdzw8rdf8MyN2ePYF896LC5hTzdZqxb6VNXInaupARLDNBWgI8spq4T0Qb5H4vWfPmHo8OyB1ito+AysNNz0oglj1U955sjUN9d41LnrX2D/u7eRwxyOaOpfyevCWbTgDEoilsOnu7zsKhjRCsnD/QzhdkYLBLXjiK4f3UWmcx2M7PO21CKVTH84638NTplt6JIQH0ZwCNuiWAfvuLhdrcOYPVO9eW3A67l7hZtgaY9GZo9AFc6cryjoeFBIWeU+npnk/nLE0OxCHL1eQsc1IciehjpJv5mqCsjeopaH6r15/MrxNnVhu7tmcslay2gO2Z1QfcfX0JMACG41/u0RrI9QAAAABJRU5ErkJggg==) ![OneBot12](https://img.shields.io/badge/OneBot-12-black?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAMAAADxPgR5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRF////29vbr6+vAAAAk1hCcwAAAAR0Uk5T////AEAqqfQAAAKcSURBVHja7NrbctswDATQXfD//zlpO7FlmwAWIOnOtNaTM5JwDMa8E+PNFz7g3waJ24fviyDPgfhz8fHP39cBcBL9KoJbQUxjA2iYqHL3FAnvzhL4GtVNUcoSZe6eSHizBcK5LL7dBr2AUZlev1ARRHCljzRALIEog6H3U6bCIyqIZdAT0eBuJYaGiJaHSjmkYIZd+qSGWAQnIaz2OArVnX6vrItQvbhZJtVGB5qX9wKqCMkb9W7aexfCO/rwQRBzsDIsYx4AOz0nhAtWu7bqkEQBO0Pr+Ftjt5fFCUEbm0Sbgdu8WSgJ5NgH2iu46R/o1UcBXJsFusWF/QUaz3RwJMEgngfaGGdSxJkE/Yg4lOBryBiMwvAhZrVMUUvwqU7F05b5WLaUIN4M4hRocQQRnEedgsn7TZB3UCpRrIJwQfqvGwsg18EnI2uSVNC8t+0QmMXogvbPg/xk+Mnw/6kW/rraUlvqgmFreAA09xW5t0AFlHrQZ3CsgvZm0FbHNKyBmheBKIF2cCA8A600aHPmFtRB1XvMsJAiza7LpPog0UJwccKdzw8rdf8MyN2ePYF896LC5hTzdZqxb6VNXInaupARLDNBWgI8spq4T0Qb5H4vWfPmHo8OyB1ito+AysNNz0oglj1U955sjUN9d41LnrX2D/u7eRwxyOaOpfyevCWbTgDEoilsOnu7zsKhjRCsnD/QzhdkYLBLXjiK4f3UWmcx2M7PO21CKVTH84638NTplt6JIQH0ZwCNuiWAfvuLhdrcOYPVO9eW3A67l7hZtgaY9GZo9AFc6cryjoeFBIWeU+npnk/nLE0OxCHL1eQsc1IciehjpJv5mqCsjeopaH6r15/MrxNnVhu7tmcslay2gO2Z1QfcfX0JMACG41/u0RrI9QAAAABJRU5ErkJggg==) license Walle-core 是一个 Rust OneBot Lib ( 不同于 libonebot 他同样可以应用于 OneBot 应用端 ) Walle 的名字来源于机械总动员的 WALL-E ( A Rusty Bot ) ## 功能 - 提供 OneBot v12 标准 Event、Action、ActionResp 序列化与反序列化功能,并支持自定义扩展 - 提供 OneBot v12 实现端标准网络通讯协议 - 提供 OneBot v12 应用端标准网络通讯协议(Http HttpWebhook 未支持) ## features - http: 启用 Http 与 HttpWebhook 通讯协议 - websocket: 启用正向 WebSocket 与反向 WebSocket 通讯协议 - impl-obc: 启用实现端 obc - app-obc: 启用应用端 obc - alt: 启用 ColoredAlt trait 着色输出纯文本 alt - full: 启用所有 features ## How to use 仅展示最小实例 ### Implementation ```rust use std::sync::Arc; use walle_core::action::Action; use walle_core::alt::TracingHandler; use walle_core::config::ImplConfig; use walle_core::event::Event; use walle_core::obc::ImplOBC; use walle_core::resp::Resp; use walle_core::OneBot; #[tokio::main] async fn main() { tracing_subscriber::fmt::init(); let ob = Arc::new(OneBot::new( TracingHandler::::default(), ImplOBC::new("impl".to_string()), )); let tasks = ob.start((), ImplConfig::default(), true).await.unwrap(); for task in tasks { task.await.unwrap() } } ``` ### Application ```rust use std::sync::Arc; use walle_core::action::Action; use walle_core::alt::TracingHandler; use walle_core::config::AppConfig; use walle_core::event::Event; use walle_core::obc::AppOBC; use walle_core::resp::Resp; use walle_core::OneBot; #[tokio::main] async fn main() { tracing_subscriber::fmt::init(); let ob = Arc::new(OneBot::new( AppOBC::new(), TracingHandler::::default(), )); let tasks = ob.start(AppConfig::default(), (), true).await.unwrap(); for task in tasks { task.await.unwrap() } } ``` ### Event walle_core::event::Event 为序列化使用标准类型,该模型仅确保 event 基础模型各字段。 walle_core::event::BaseEvent\ 为扩展模型,其中五个泛型依次为 type detail_type sub_type platform impl 五个层级的扩展字段 需要实现 Event -> BaseEvent 转化时,扩展字段需要 impl `TryFromEvent` trait ,通常在应用端使用 需要实现 BaseEvent -> Event 转化时,扩展字段需要 impl `PushtoValueMap` 和 `ToEvent` trait ,通常在协议端使用 > 其中 T 标识不同扩展级别,分别为 `TypeLevel` | `DetailTypeLevel` | `SubTypeLevel` | `PlatformLevel` | `ImplLevel` 或者直接使用本 crate 提供的派生宏 定义一个 type 级别扩展字段( ob12 理论上不支持该级别扩展): ```rust use walle_core::prelude::{PushToValueMap, ToEvent, TryFromEvent}; #[derive(ToEvent, PushToValueMap, TryFromEvent)] #[event(type)] pub struct Message { pub message_id: String, pub message: crate::message::Message, pub alt_message: String, pub user_id: String, } ``` 或者定义一个 detail_type 级别扩展字段 ```rust #[derive(PushToValueMap, TryFromEvent, ToEvent)] #[event(detail_type = "group")] pub struct Group_ { pub group_id: String, } // TryFromEvent 支持 enum 类型的扩展 #[derive(TryFromEvent)] #[event(detail_type)] pub enum Details { Group(Group), // Group 应 impl TryFromValue Private, } ``` ### Action walle_core::action::Action 为序列化使用标准类型,该模型仅确保 action 与 params 字段存在且类型正确 实现 Action -> BaseAction 或 Action -> T 转化时,扩展字段需要 impl `TryFromAction` trait 实现 BaseAction -> Action 或 T -> Action 转化时,扩展字段需要 impl `PushtoValueMap` 和 `ToAction` trait 或者直接使用本 crate 提供的派生宏 ```rust #[derive(ToAction, PushToValueMap, TryFromAction)] pub struct GetFile { pub file_id: String, pub ty: String, } ``` 或者 ```rust #[derive(ToAction, TryFromAction, PushToValueMap)] #[action("upload_file")] pub struct UploadFile_ { pub ty: String, pub name: String, pub url: Option, pub headers: Option>, pub path: Option, pub data: Option, pub sha256: Option, } ``` 想要同时支持多种 Action ? 没问题! ```rust #[derive(TryFromAction)] pub enum MyAction { GetUserInfo(GetUserInfo), // GetUserInfo 应 impl TryFromValue GetGroupInfo { group_id: String }, } ``` ### Resp (Value) walle_core::resp::Resp 为序列化使用标准类型 同时本库还提供了 RespError 用于构造失败的 Resp,可以使用 \.as_result() 实现 Value -> T 转化时,需要 impl `TryFromValue` trait 实现 T -> Value 转化时,需要 impl `PushToValueMap` trait (仅支持 struct ) 当然还是可以使用宏 ```rust #[derive(PushToValueMap, TryFromValue)] pub struct Status { pub good: bool, pub online: bool, } ``` 同时实现了 Value 的结构体可以作为其他宏的字段使用。 ### MessageSegment 基本与 Action 模型相同,唯一的不同是序列化使用的模型是 walle_core::message::MessageSegment,该模型同时也是一个 Value ,因此可以从 Event 或 Action 中获取。 ```rust #[derive(PushToValueMap, TryFromMsgSegment, ToMsgSegment)] pub struct Text { pub text: String, } ``` ### Notice 由于与 Rust 保留字冲突,宏将会对以下字段自动转义: - `"type"` -> `ty` - `"impl"` -> `implt` - `"selft"` -> `self`