Skip to content

Commit

Permalink
0.6.1
Browse files Browse the repository at this point in the history
  • Loading branch information
owent committed Aug 23, 2019
1 parent fa6e706 commit e096232
Show file tree
Hide file tree
Showing 6 changed files with 544 additions and 422 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
CHANGELOG
============

v0.6.1
----------

1. 更新依赖库
2. 修复有未知字段时解析提前中断的问题
3. 增加对消息的 **ChatType** 参数解析和 **WXWORK_ROBOT_CHAT_TYPE** 环境变量

v0.6.0
----------

Expand Down
670 changes: 358 additions & 312 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wxwork_robotd"
version = "0.6.0"
version = "0.6.1"
description = "Robot service for WXWork"
authors = ["owent <[email protected]>"]
documentation = "https://github.com/owt5008137/wxwork_robotd"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
* WXWORK_ROBOT_MSG_ID : 消息ID(版本>=0.3.6)
* WXWORK_ROBOT_GET_CHAT_INFO_URL : 可以用于获取消息信息的URL(版本>=0.3.9),有效期为5分钟,调用一次后失效
* WXWORK_ROBOT_CHAT_ID : chat id(版本>=0.3.9),用于区分聊天群,如果机器人被添加到多个群,可以用这个指定主动发消息到哪个群
* WXWORK_ROBOT_CHAT_TYPE : chat type(版本>=0.6.1),对应企业微信机器人消息的ChatType字段
* WXWORK_ROBOT_HTTP_RESPONSE : HTTP回包(仅 ```type``` 为 http 时的echo字段可用)


Expand Down
2 changes: 2 additions & 0 deletions src/handles/robot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ fn dispatch_robot_message(
serde_json::Value::String(msg_ntf.get_chat_info_url.clone());
cmd_match_res.mut_json()["WXWORK_ROBOT_CHAT_ID"] =
serde_json::Value::String(msg_ntf.chat_id.clone());
cmd_match_res.mut_json()["WXWORK_ROBOT_CHAT_TYPE"] =
serde_json::Value::String(msg_ntf.chat_type.clone());

// 填充模板参数json
let template_vars = proj_obj.generate_template_vars(&cmd_match_res);
Expand Down
284 changes: 175 additions & 109 deletions src/wxwork_robot/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub struct WXWorkMessageNtf {
pub content: String,
pub msg_id: String,
pub chat_id: String,
pub chat_type: String,
pub get_chat_info_url: String,
}

Expand Down Expand Up @@ -118,6 +119,7 @@ enum WXWorkMsgField {
MsgId,
GetChatInfoUrl,
ChatId,
ChatType,
}

pub fn get_msg_from_str(input: &str) -> Option<WXWorkMessageNtf> {
Expand All @@ -129,6 +131,7 @@ pub fn get_msg_from_str(input: &str) -> Option<WXWorkMessageNtf> {
let mut content = String::default();
let mut msg_id = String::default();
let mut chat_id = String::default();
let mut chat_type = String::default();
let mut get_chat_info_url = String::default();
let mut is_in_from = false;
let mut field_mode = WXWorkMsgField::NONE;
Expand All @@ -139,62 +142,69 @@ pub fn get_msg_from_str(input: &str) -> Option<WXWorkMessageNtf> {
let mut buf = Vec::new();
loop {
match reader.read_event(&mut buf) {
Ok(Event::Start(ref e)) => match e.name() {
b"WebhookUrl" => {
field_mode = WXWorkMsgField::WebHookUrl;
debug!("Parse get ready for WebhookUrl");
}
b"From" => {
is_in_from = true;
debug!("Parse get ready for From");
}
b"UserId" => {
if is_in_from {
field_mode = WXWorkMsgField::FromUserId;
debug!("Parse get ready for From.UserId");
Ok(Event::Start(ref e)) => {
let tag_name = e.name();
match tag_name {
b"WebhookUrl" => {
field_mode = WXWorkMsgField::WebHookUrl;
debug!("Parse get ready for WebhookUrl");
}
}
b"Name" => {
if is_in_from {
field_mode = WXWorkMsgField::FromName;
debug!("Parse get ready for From.Name");
b"From" => {
is_in_from = true;
debug!("Parse get ready for From");
}
}
b"Alias" => {
if is_in_from {
field_mode = WXWorkMsgField::FromAlias;
debug!("Parse get ready for From.Alias");
b"UserId" => {
if is_in_from {
field_mode = WXWorkMsgField::FromUserId;
debug!("Parse get ready for From.UserId");
}
}
}
b"MsgType" => {
field_mode = WXWorkMsgField::MsgType;
debug!("Parse get ready for MsgType");
}
b"Text" | b"Markdown" => {
field_mode = WXWorkMsgField::Content;
debug!("Parse get ready for Content");
}
b"MsgId" => {
field_mode = WXWorkMsgField::MsgId;
debug!("Parse get ready for MsgId");
}
b"GetChatInfoUrl" => {
field_mode = WXWorkMsgField::GetChatInfoUrl;
debug!("Parse get ready for GetChatInfoUrl");
}
b"ChatId" => {
field_mode = WXWorkMsgField::ChatId;
debug!("Parse get ready for ChatId");
}
any => {
debug!(
"Ignore start label for {}",
if let Ok(x) = String::from_utf8(any.to_vec()) {
x
} else {
String::from("UNKNOWN")
b"Name" => {
if is_in_from {
field_mode = WXWorkMsgField::FromName;
debug!("Parse get ready for From.Name");
}
);
}
b"Alias" => {
if is_in_from {
field_mode = WXWorkMsgField::FromAlias;
debug!("Parse get ready for From.Alias");
}
}
b"MsgType" => {
field_mode = WXWorkMsgField::MsgType;
debug!("Parse get ready for MsgType");
}
b"Text" | b"Markdown" => {
field_mode = WXWorkMsgField::Content;
debug!("Parse get ready for Content");
}
b"MsgId" => {
field_mode = WXWorkMsgField::MsgId;
debug!("Parse get ready for MsgId");
}
b"GetChatInfoUrl" => {
field_mode = WXWorkMsgField::GetChatInfoUrl;
debug!("Parse get ready for GetChatInfoUrl");
}
b"ChatId" => {
field_mode = WXWorkMsgField::ChatId;
debug!("Parse get ready for ChatId");
}
b"ChatType" => {
field_mode = WXWorkMsgField::ChatType;
debug!("Parse get ready for ChatType");
}
any => {
debug!(
"Ignore start label for {}",
if let Ok(x) = String::from_utf8(any.to_vec()) {
x
} else {
String::from("UNKNOWN")
}
);
}
}
},
Ok(Event::End(ref e)) => match e.name() {
Expand Down Expand Up @@ -262,6 +272,12 @@ pub fn get_msg_from_str(input: &str) -> Option<WXWorkMessageNtf> {
debug!("Parse close for ChatId");
}
}
b"ChatType" => {
if let WXWorkMsgField::ChatType = field_mode {
field_mode = WXWorkMsgField::NONE;
debug!("Parse close for ChatType");
}
}
any => {
debug!(
"Ignore close label for {}",
Expand All @@ -274,68 +290,76 @@ pub fn get_msg_from_str(input: &str) -> Option<WXWorkMessageNtf> {
}
},
Ok(Event::CData(data)) | Ok(Event::Text(data)) => {
if let WXWorkMsgField::NONE = field_mode {
break;
}
loop {
if let WXWorkMsgField::NONE = field_mode {
break;
}

let data_str_opt = if let Ok(x) = data.unescaped() {
match String::from_utf8(Vec::from(x)) {
Ok(s) => Some(s),
Err(e) => {
error!("decode Encrypt as utf8 failed, {:?}", e);
None
let data_str_opt = if let Ok(x) = data.unescaped() {
match String::from_utf8(Vec::from(x)) {
Ok(s) => Some(s),
Err(e) => {
error!("decode Encrypt as utf8 failed, {:?}", e);
None
}
}
} else {
None
};

let data_str = if let Some(x) = data_str_opt {
x
} else {
break;
};

match field_mode {
WXWorkMsgField::WebHookUrl => {
web_hook_url = data_str;
debug!("Parse data for WebhookUrl");
}
WXWorkMsgField::FromUserId => {
from_user_id = data_str;
debug!("Parse data for From.UserId");
}
WXWorkMsgField::FromName => {
from_name = data_str;
debug!("Parse data for From.Name");
}
WXWorkMsgField::FromAlias => {
from_alias = data_str;
debug!("Parse data for From.Alias");
}
WXWorkMsgField::MsgType => {
msg_type = data_str;
debug!("Parse data for MsgType");
}
WXWorkMsgField::Content => {
content = data_str;
debug!("Parse data for Content");
}
WXWorkMsgField::MsgId => {
msg_id = data_str;
debug!("Parse data for MsgId");
}
WXWorkMsgField::GetChatInfoUrl => {
get_chat_info_url = data_str;
debug!("Parse data for GetChatInfoUrl");
}
WXWorkMsgField::ChatId => {
chat_id = data_str;
debug!("Parse data for ChatId");
}
WXWorkMsgField::ChatType => {
chat_type = data_str;
debug!("Parse data for ChatId");
}
_ => {
debug!("Ignore data {}", data_str);
}
}
} else {
None
};

let data_str = if let Some(x) = data_str_opt {
x
} else {
break;
};

match field_mode {
WXWorkMsgField::WebHookUrl => {
web_hook_url = data_str;
debug!("Parse data for WebhookUrl");
}
WXWorkMsgField::FromUserId => {
from_user_id = data_str;
debug!("Parse data for From.UserId");
}
WXWorkMsgField::FromName => {
from_name = data_str;
debug!("Parse data for From.Name");
}
WXWorkMsgField::FromAlias => {
from_alias = data_str;
debug!("Parse data for From.Alias");
}
WXWorkMsgField::MsgType => {
msg_type = data_str;
debug!("Parse data for MsgType");
}
WXWorkMsgField::Content => {
content = data_str;
debug!("Parse data for Content");
}
WXWorkMsgField::MsgId => {
msg_id = data_str;
debug!("Parse data for MsgId");
}
WXWorkMsgField::GetChatInfoUrl => {
get_chat_info_url = data_str;
debug!("Parse data for GetChatInfoUrl");
}
WXWorkMsgField::ChatId => {
chat_id = data_str;
debug!("Parse data for ChatId");
}
_ => {
debug!("Ignore data {}", data_str);
}
}
}
Err(e) => error!("Error at position {}: {:?}", reader.buffer_position(), e),
Expand Down Expand Up @@ -371,6 +395,7 @@ pub fn get_msg_from_str(input: &str) -> Option<WXWorkMessageNtf> {
content: content,
msg_id: msg_id,
chat_id: chat_id,
chat_type: chat_type,
get_chat_info_url: get_chat_info_url,
})
}
Expand Down Expand Up @@ -607,3 +632,44 @@ pub fn make_robot_not_found_response(msg: String) -> HttpResponse {
make_robot_not_found_response_content(msg.as_str())
}


#[cfg(test)]
mod tests {

use super::*;

const WXWORKROBOT_TEST_MSG: &str = "<xml><From><UserId><![CDATA[T56650002A]]></UserId><Name><![CDATA[欧文韬]]></Name><Alias><![CDATA[owentou]]></Alias></From><WebhookUrl><![CDATA[http://in.qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxxxxxx]]></WebhookUrl><ChatId><![CDATA[fakechatid]]></ChatId><GetChatInfoUrl><![CDATA[http://in.qyapi.weixin.qq.com/cgi-bin/webhook/get_chat_info?code=VcgjNN2bHMhatXwG8aZbHvj_RZmLF0OSS5_sVGxYUGk]]></GetChatInfoUrl><MsgId><![CDATA[CIGABBCOgP3qBRiR4vm7goCAAyAY]]></MsgId><ChatType><![CDATA[group]]></ChatType><MsgType><![CDATA[text]]></MsgType><Text><Content><![CDATA[@fa机器人 help]]></Content></Text></xml>";
const WXWORKROBOT_TEST_MSG_WITH_KNOWN_DATA: &str = "<xml><unknown_field1><![CDATA[blablabla]]></unknown_field1><From><UserId><![CDATA[T56650002A]]></UserId><Name><![CDATA[欧文韬]]></Name><Alias><![CDATA[owentou]]></Alias></From><WebhookUrl><![CDATA[http://in.qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxxxxxx]]></WebhookUrl><ChatId><![CDATA[fakechatid]]></ChatId><unknown_field2>test_message</unknown_field2><GetChatInfoUrl><![CDATA[http://in.qyapi.weixin.qq.com/cgi-bin/webhook/get_chat_info?code=VcgjNN2bHMhatXwG8aZbHvj_RZmLF0OSS5_sVGxYUGk]]></GetChatInfoUrl><MsgId><![CDATA[CIGABBCOgP3qBRiR4vm7goCAAyAY]]></MsgId><ChatType><![CDATA[group]]></ChatType><MsgType><![CDATA[text]]></MsgType><Text><Content><![CDATA[@fa机器人 help]]></Content></Text></xml>";

#[test]
fn decode_wxwork_robot_msg() {
let decode_res = get_msg_from_str(WXWORKROBOT_TEST_MSG);
assert!(decode_res.is_some());
if let Some(msg) = decode_res {
assert_eq!(msg.content, "@fa机器人 help");
assert_eq!(msg.from.user_id, "T56650002A");
assert_eq!(msg.from.name, "欧文韬");
assert_eq!(msg.from.alias, "owentou");
assert_eq!(msg.msg_id, "CIGABBCOgP3qBRiR4vm7goCAAyAY");
assert_eq!(msg.msg_type, "text");
assert_eq!(msg.chat_id, "fakechatid");
assert_eq!(msg.chat_type, "group");
}
}

#[test]
fn decode_wxwork_robot_msg_with_known_fields() {
let decode_res = get_msg_from_str(WXWORKROBOT_TEST_MSG_WITH_KNOWN_DATA);
assert!(decode_res.is_some());
if let Some(msg) = decode_res {
assert_eq!(msg.content, "@fa机器人 help");
assert_eq!(msg.from.user_id, "T56650002A");
assert_eq!(msg.from.name, "欧文韬");
assert_eq!(msg.from.alias, "owentou");
assert_eq!(msg.msg_id, "CIGABBCOgP3qBRiR4vm7goCAAyAY");
assert_eq!(msg.msg_type, "text");
assert_eq!(msg.chat_id, "fakechatid");
assert_eq!(msg.chat_type, "group");
}
}
}

0 comments on commit e096232

Please sign in to comment.