feat: add workflow toolkit and runtime support
This commit is contained in:
+63
-5
@@ -63,7 +63,7 @@ impl WeChatClient {
|
||||
.unwrap_or_else(|_| "https://ilinkai.weixin.qq.com".to_string())
|
||||
}
|
||||
/// 版本号编码:0x00MMNNPP
|
||||
const CLIENT_VERSION: u32 = 0x000100_00; // 1.0.0
|
||||
const CLIENT_VERSION: u32 = 0x0001_0000; // 1.0.0
|
||||
|
||||
pub fn new(base_url: Option<String>) -> Self {
|
||||
// 优先级: 显式参数 > WEIXIN_BASE_URL 环境变量 > 默认值
|
||||
@@ -363,14 +363,72 @@ impl WeChatClient {
|
||||
context_token: Option<&str>,
|
||||
) -> Result<String, String> {
|
||||
let client_id = uuid::Uuid::new_v4().to_string();
|
||||
self.send_text_with_client_id(to, text, context_token, &client_id)
|
||||
.await
|
||||
}
|
||||
|
||||
/// 发送“输入中”状态,返回用于最终完成消息的 client_id。
|
||||
pub async fn send_typing(
|
||||
&self,
|
||||
to: &str,
|
||||
context_token: Option<&str>,
|
||||
) -> Result<String, String> {
|
||||
let client_id = uuid::Uuid::new_v4().to_string();
|
||||
self.send_typing_with_client_id(to, context_token, &client_id)
|
||||
.await?;
|
||||
Ok(client_id.to_string())
|
||||
}
|
||||
|
||||
/// 用已有 client_id 刷新“输入中”状态。
|
||||
pub async fn send_typing_with_client_id(
|
||||
&self,
|
||||
to: &str,
|
||||
context_token: Option<&str>,
|
||||
client_id: &str,
|
||||
) -> Result<String, String> {
|
||||
self.send_bot_message(
|
||||
to,
|
||||
client_id,
|
||||
WeixinMessage::STATE_TYPING,
|
||||
None,
|
||||
context_token,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// 使用已有 client_id 完成文本消息。
|
||||
pub async fn send_text_with_client_id(
|
||||
&self,
|
||||
to: &str,
|
||||
text: &str,
|
||||
context_token: Option<&str>,
|
||||
client_id: &str,
|
||||
) -> Result<String, String> {
|
||||
self.send_bot_message(
|
||||
to,
|
||||
client_id,
|
||||
WeixinMessage::STATE_FINISH,
|
||||
Some(vec![MessageItem::text(text)]),
|
||||
context_token,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn send_bot_message(
|
||||
&self,
|
||||
to: &str,
|
||||
client_id: &str,
|
||||
message_state: i32,
|
||||
item_list: Option<Vec<MessageItem>>,
|
||||
context_token: Option<&str>,
|
||||
) -> Result<String, String> {
|
||||
let msg = WeixinMessage {
|
||||
from_user_id: Some(String::new()),
|
||||
to_user_id: Some(to.to_string()),
|
||||
client_id: Some(client_id.clone()),
|
||||
client_id: Some(client_id.to_string()),
|
||||
msg_type: Some(WeixinMessage::TYPE_BOT),
|
||||
message_state: Some(2), // FINISH
|
||||
item_list: Some(vec![MessageItem::text(text)]),
|
||||
message_state: Some(message_state),
|
||||
item_list,
|
||||
context_token: context_token.map(|s| s.to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
@@ -387,7 +445,7 @@ impl WeChatClient {
|
||||
.await
|
||||
.map_err(|e| format!("发送消息网络错误: {}", e))?;
|
||||
|
||||
Ok(client_id)
|
||||
Ok(client_id.to_string())
|
||||
}
|
||||
|
||||
/// 设置 auth 状态(从持久化恢复)
|
||||
|
||||
+56
-2
@@ -47,7 +47,7 @@ pub enum WeChatEvent {
|
||||
/// 收到一条微信消息。
|
||||
Message {
|
||||
account_id: String,
|
||||
message: WeixinMessage,
|
||||
message: Box<WeixinMessage>,
|
||||
updates_buf: String,
|
||||
},
|
||||
/// 某个账号的轮询发生错误。管理器会继续重试,除非任务被停止。
|
||||
@@ -145,7 +145,7 @@ impl WeChatMultiAccountManager {
|
||||
for message in resp.msgs {
|
||||
let event = WeChatEvent::Message {
|
||||
account_id: account_id.clone(),
|
||||
message,
|
||||
message: Box::new(message),
|
||||
updates_buf: updates_buf.clone(),
|
||||
};
|
||||
if event_tx.send(event).await.is_err() {
|
||||
@@ -230,6 +230,60 @@ impl WeChatMultiAccountManager {
|
||||
|
||||
runtime.client.send_text(to, text, context_token).await
|
||||
}
|
||||
|
||||
/// 使用指定账号发送输入中状态,返回后续完成消息复用的 client_id。
|
||||
pub async fn send_typing(
|
||||
&self,
|
||||
account_id: &str,
|
||||
to: &str,
|
||||
context_token: Option<&str>,
|
||||
) -> Result<String, String> {
|
||||
let runtime = self
|
||||
.accounts
|
||||
.get(account_id)
|
||||
.ok_or_else(|| format!("微信账号未启动: {}", account_id))?;
|
||||
|
||||
runtime.client.send_typing(to, context_token).await
|
||||
}
|
||||
|
||||
/// 使用指定账号刷新输入中状态。
|
||||
pub async fn send_typing_with_client_id(
|
||||
&self,
|
||||
account_id: &str,
|
||||
to: &str,
|
||||
context_token: Option<&str>,
|
||||
client_id: &str,
|
||||
) -> Result<String, String> {
|
||||
let runtime = self
|
||||
.accounts
|
||||
.get(account_id)
|
||||
.ok_or_else(|| format!("微信账号未启动: {}", account_id))?;
|
||||
|
||||
runtime
|
||||
.client
|
||||
.send_typing_with_client_id(to, context_token, client_id)
|
||||
.await
|
||||
}
|
||||
|
||||
/// 使用指定账号完成已有输入中消息。
|
||||
pub async fn send_text_with_client_id(
|
||||
&self,
|
||||
account_id: &str,
|
||||
to: &str,
|
||||
text: &str,
|
||||
context_token: Option<&str>,
|
||||
client_id: &str,
|
||||
) -> Result<String, String> {
|
||||
let runtime = self
|
||||
.accounts
|
||||
.get(account_id)
|
||||
.ok_or_else(|| format!("微信账号未启动: {}", account_id))?;
|
||||
|
||||
runtime
|
||||
.client
|
||||
.send_text_with_client_id(to, text, context_token, client_id)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WeChatMultiAccountManager {
|
||||
|
||||
@@ -30,6 +30,12 @@ impl BaseInfo {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BaseInfo {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 消息类型 ───
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -232,6 +238,8 @@ impl WeixinMessage {
|
||||
pub const TYPE_NONE: i32 = 0;
|
||||
pub const TYPE_USER: i32 = 1;
|
||||
pub const TYPE_BOT: i32 = 2;
|
||||
pub const STATE_TYPING: i32 = 1;
|
||||
pub const STATE_FINISH: i32 = 2;
|
||||
|
||||
/// 获取文本内容(如果有纯文本 item)
|
||||
pub fn text_content(&self) -> Option<&str> {
|
||||
|
||||
Reference in New Issue
Block a user