群聊成员获取
This commit is contained in:
parent
6bf4a79e60
commit
0090309f27
1
clients/rust/wcferry/Cargo.toml
vendored
1
clients/rust/wcferry/Cargo.toml
vendored
@ -12,6 +12,7 @@ nng = "1.0.1"
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
log = "0.4.17"
|
||||
hex = "0.4"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.8.4"
|
||||
|
2
clients/rust/wcferry/build.rs
vendored
2
clients/rust/wcferry/build.rs
vendored
@ -3,7 +3,7 @@
|
||||
.build_client(true)
|
||||
.build_server(false)
|
||||
.out_dir("src/proto")
|
||||
.compile(&["proto/wcf.proto"], &["."])
|
||||
.compile(&["proto/wcf.proto", "proto/roomdata.proto"], &["."])
|
||||
.expect("failed to compile protos");
|
||||
Ok(())
|
||||
}
|
||||
|
21
clients/rust/wcferry/proto/roomdata.proto
vendored
Normal file
21
clients/rust/wcferry/proto/roomdata.proto
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
syntax = "proto3";
|
||||
package roomdata;
|
||||
|
||||
message RoomData {
|
||||
|
||||
message RoomMember {
|
||||
string wxid = 1;
|
||||
string name = 2;
|
||||
int32 state = 3;
|
||||
}
|
||||
|
||||
repeated RoomMember members = 1;
|
||||
|
||||
int32 field_2 = 2;
|
||||
int32 field_3 = 3;
|
||||
int32 field_4 = 4;
|
||||
int32 room_capacity = 5;
|
||||
int32 field_6 = 6;
|
||||
int64 field_7 = 7 [jstype = JS_STRING];
|
||||
int64 field_8 = 8 [jstype = JS_STRING];
|
||||
}
|
33
clients/rust/wcferry/src/proto/roomdata.rs
vendored
Normal file
33
clients/rust/wcferry/src/proto/roomdata.rs
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct RoomData {
|
||||
#[prost(message, repeated, tag = "1")]
|
||||
pub members: ::prost::alloc::vec::Vec<room_data::RoomMember>,
|
||||
#[prost(int32, tag = "2")]
|
||||
pub field_2: i32,
|
||||
#[prost(int32, tag = "3")]
|
||||
pub field_3: i32,
|
||||
#[prost(int32, tag = "4")]
|
||||
pub field_4: i32,
|
||||
#[prost(int32, tag = "5")]
|
||||
pub room_capacity: i32,
|
||||
#[prost(int32, tag = "6")]
|
||||
pub field_6: i32,
|
||||
#[prost(int64, tag = "7")]
|
||||
pub field_7: i64,
|
||||
#[prost(int64, tag = "8")]
|
||||
pub field_8: i64,
|
||||
}
|
||||
/// Nested message and enum types in `RoomData`.
|
||||
pub mod room_data {
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct RoomMember {
|
||||
#[prost(string, tag = "1")]
|
||||
pub wxid: ::prost::alloc::string::String,
|
||||
#[prost(string, tag = "2")]
|
||||
pub name: ::prost::alloc::string::String,
|
||||
#[prost(int32, tag = "3")]
|
||||
pub state: i32,
|
||||
}
|
||||
}
|
426
clients/rust/wcferry/src/wechat.rs
vendored
426
clients/rust/wcferry/src/wechat.rs
vendored
@ -12,6 +12,10 @@ pub mod wcf {
|
||||
include!("proto/wcf.rs");
|
||||
}
|
||||
|
||||
pub mod roomdata {
|
||||
include!("proto/roomdata.rs");
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WeChat {
|
||||
pub url: String,
|
||||
@ -30,6 +34,46 @@ pub struct UserInfo {
|
||||
pub home: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ChatRoom {
|
||||
/// 群聊ID
|
||||
pub room_id: String,
|
||||
/// 群聊成员
|
||||
pub room_data: roomdata::RoomData,
|
||||
/// 群聊头像
|
||||
pub room_head_img_url: Option<String>,
|
||||
/// 公告
|
||||
pub room_announcement: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ContactInfo {
|
||||
/// 微信ID
|
||||
pub wxid: String,
|
||||
/// 微信号
|
||||
pub alias: Option<String>,
|
||||
/// 删除标记
|
||||
pub del_flag: u8,
|
||||
/// 类型
|
||||
pub contact_type: u8,
|
||||
/// 备注
|
||||
pub remark: Option<String>,
|
||||
/// 昵称
|
||||
pub nick_name: Option<String>,
|
||||
/// 昵称拼音首字符
|
||||
pub py_initial: Option<String>,
|
||||
/// 昵称全拼
|
||||
pub quan_pin: Option<String>,
|
||||
/// 备注拼音首字母
|
||||
pub remark_py_initial: Option<String>,
|
||||
/// 备注全拼
|
||||
pub remark_quan_pin: Option<String>,
|
||||
/// 小头像
|
||||
pub small_head_url: Option<String>,
|
||||
/// 大头像
|
||||
pub big_head_url: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for WeChat {
|
||||
fn default() -> Self {
|
||||
WeChat::new(false)
|
||||
@ -268,6 +312,218 @@ pub fn get_contacts(
|
||||
};
|
||||
}
|
||||
|
||||
pub fn query_all_contact_info(
|
||||
wechat: &mut WeChat,
|
||||
) -> Result<Vec<ContactInfo>, Box<dyn std::error::Error>> {
|
||||
let contacts = crate::wechat::exec_db_query(
|
||||
wechat,
|
||||
String::from("MicroMsg.db"),
|
||||
String::from("select * from Contact"),
|
||||
)
|
||||
.unwrap();
|
||||
if contacts.len() == 0 {
|
||||
return Ok(vec![]);
|
||||
} else {
|
||||
let mut contact_list: Vec<ContactInfo> = vec![];
|
||||
for contact in contacts.into_iter() {
|
||||
let mut contact_info = ContactInfo::default();
|
||||
let fields = &contact.fields;
|
||||
for field in fields.into_iter() {
|
||||
if field.column.eq("UserName") {
|
||||
contact_info.wxid = String::from_utf8(field.content.clone()).unwrap();
|
||||
} else if field.column.eq("Alias") {
|
||||
contact_info.alias = Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("DelFlag") {
|
||||
contact_info.del_flag = *field.content.get(0).unwrap();
|
||||
} else if field.column.eq("Type") {
|
||||
contact_info.contact_type = *field.content.get(0).unwrap();
|
||||
} else if field.column.eq("Remark") {
|
||||
contact_info.remark = Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("NickName") {
|
||||
contact_info.nick_name =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("PYInitial") {
|
||||
contact_info.py_initial =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("QuanPin") {
|
||||
contact_info.quan_pin = Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("RemarkPYInitial") {
|
||||
contact_info.remark_py_initial =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("RemarkQuanPin") {
|
||||
contact_info.remark_quan_pin =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
}
|
||||
}
|
||||
if !contact_info.wxid.is_empty() {
|
||||
let contact_heads = crate::wechat::exec_db_query(
|
||||
wechat,
|
||||
String::from("MicroMsg.db"),
|
||||
String::from(format!(
|
||||
"select * from ContactHeadImgUrl where usrName = '{}'",
|
||||
contact_info.wxid
|
||||
)),
|
||||
)
|
||||
.unwrap();
|
||||
if contact_heads.len() > 0 {
|
||||
let contact_head = contact_heads.get(0).unwrap();
|
||||
let head_fields = &contact_head.fields;
|
||||
for field in head_fields.into_iter() {
|
||||
if field.column.eq("smallHeadImgUrl") {
|
||||
contact_info.small_head_url =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("bigHeadImgUrl") {
|
||||
contact_info.big_head_url =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
contact_list.push(contact_info);
|
||||
}
|
||||
|
||||
Ok(contact_list)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn query_contact_info(
|
||||
wechat: &mut WeChat,
|
||||
wxid: String,
|
||||
) -> Result<Option<ContactInfo>, Box<dyn std::error::Error>> {
|
||||
let contacts = crate::wechat::exec_db_query(
|
||||
wechat,
|
||||
String::from("MicroMsg.db"),
|
||||
String::from(format!(
|
||||
"select * from Contact where UserName = '{}'",
|
||||
wxid.clone()
|
||||
)),
|
||||
)
|
||||
.unwrap();
|
||||
if contacts.len() == 0 {
|
||||
return Ok(None);
|
||||
} else {
|
||||
let contact = contacts.get(0).unwrap();
|
||||
let mut contact_info = ContactInfo::default();
|
||||
let fields = &contact.fields;
|
||||
for field in fields.into_iter() {
|
||||
if field.column.eq("UserName") {
|
||||
contact_info.wxid = String::from_utf8(field.content.clone()).unwrap();
|
||||
} else if field.column.eq("Alias") {
|
||||
contact_info.alias = Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("DelFlag") {
|
||||
contact_info.del_flag = *field.content.get(0).unwrap();
|
||||
} else if field.column.eq("Type") {
|
||||
contact_info.contact_type = *field.content.get(0).unwrap();
|
||||
} else if field.column.eq("Remark") {
|
||||
contact_info.remark = Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("NickName") {
|
||||
contact_info.nick_name = Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("PYInitial") {
|
||||
contact_info.py_initial = Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("QuanPin") {
|
||||
contact_info.quan_pin = Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("RemarkPYInitial") {
|
||||
contact_info.remark_py_initial =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("RemarkQuanPin") {
|
||||
contact_info.remark_quan_pin =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
}
|
||||
}
|
||||
let contact_heads = crate::wechat::exec_db_query(
|
||||
wechat,
|
||||
String::from("MicroMsg.db"),
|
||||
String::from(format!(
|
||||
"select * from ContactHeadImgUrl where usrName = '{}'",
|
||||
wxid
|
||||
)),
|
||||
)
|
||||
.unwrap();
|
||||
if contact_heads.len() > 0 {
|
||||
let contact_head = contact_heads.get(0).unwrap();
|
||||
let head_fields = &contact_head.fields;
|
||||
for field in head_fields.into_iter() {
|
||||
if field.column.eq("smallHeadImgUrl") {
|
||||
contact_info.small_head_url =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
} else if field.column.eq("bigHeadImgUrl") {
|
||||
contact_info.big_head_url =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Some(contact_info))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn query_chat_room_info(
|
||||
wechat: &mut WeChat,
|
||||
wxid: String,
|
||||
) -> Result<Option<ChatRoom>, Box<dyn std::error::Error>> {
|
||||
let contacts = crate::wechat::exec_db_query(
|
||||
wechat,
|
||||
String::from("MicroMsg.db"),
|
||||
String::from(format!(
|
||||
"select * from ChatRoom where ChatRoomName = '{}'",
|
||||
wxid.clone()
|
||||
)),
|
||||
)
|
||||
.unwrap();
|
||||
if contacts.len() == 0 {
|
||||
return Ok(None);
|
||||
} else {
|
||||
let contact = contacts.get(0).unwrap();
|
||||
let mut chat_room = ChatRoom::default();
|
||||
let fields = &contact.fields;
|
||||
for field in fields.into_iter() {
|
||||
if field.column.eq("ChatRoomName") {
|
||||
chat_room.room_id = String::from_utf8(field.content.clone()).unwrap();
|
||||
} else if field.column.eq("RoomData") {
|
||||
chat_room.room_data = roomdata::RoomData::decode(field.content.as_slice()).unwrap();
|
||||
}
|
||||
}
|
||||
let contact_heads = crate::wechat::exec_db_query(
|
||||
wechat,
|
||||
String::from("MicroMsg.db"),
|
||||
String::from(format!(
|
||||
"select * from ContactHeadImgUrl where usrName = '{}'",
|
||||
wxid
|
||||
)),
|
||||
)
|
||||
.unwrap();
|
||||
if contact_heads.len() > 0 {
|
||||
let contact_head = contact_heads.get(0).unwrap();
|
||||
let head_fields = &contact_head.fields;
|
||||
for field in head_fields.into_iter() {
|
||||
if field.column.eq("smallHeadImgUrl") {
|
||||
chat_room.room_head_img_url =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
let contact_heads = crate::wechat::exec_db_query(
|
||||
wechat,
|
||||
String::from("MicroMsg.db"),
|
||||
String::from(format!(
|
||||
"select * from ChatRoomInfo where ChatRoomName = '{}'",
|
||||
wxid
|
||||
)),
|
||||
)
|
||||
.unwrap();
|
||||
if contact_heads.len() > 0 {
|
||||
let contact_head = contact_heads.get(0).unwrap();
|
||||
let head_fields = &contact_head.fields;
|
||||
for field in head_fields.into_iter() {
|
||||
if field.column.eq("Announcement") {
|
||||
chat_room.room_announcement =
|
||||
Some(String::from_utf8(field.content.clone()).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Some(chat_room))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_db_names(wechat: &mut WeChat) -> Result<Vec<String>, Box<dyn std::error::Error>> {
|
||||
let req = wcf::Request {
|
||||
func: wcf::Functions::FuncGetDbNames.into(),
|
||||
@ -1064,6 +1320,170 @@ mod test {
|
||||
println!("IsLogin: {}", is_login);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_db_names() {
|
||||
let mut wechat = crate::wechat::WeChat::default();
|
||||
let dbs = crate::wechat::get_db_names(&mut wechat).unwrap();
|
||||
println!("dbs: {:?}", dbs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_db_tables() {
|
||||
let mut wechat = crate::wechat::WeChat::default();
|
||||
let tables: Vec<crate::wechat::wcf::DbTable> =
|
||||
crate::wechat::get_db_tables(&mut wechat, String::from("MicroMsg.db")).unwrap();
|
||||
println!("tables: {:?}", tables);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exec_db_query_contact() {
|
||||
use hex;
|
||||
pub mod roomdata {
|
||||
include!("proto/roomdata.rs");
|
||||
}
|
||||
|
||||
let mut wechat = crate::wechat::WeChat::default();
|
||||
let chat_rooms = crate::wechat::exec_db_query(
|
||||
&mut wechat,
|
||||
String::from("MicroMsg.db"),
|
||||
String::from("select * from Contact"),
|
||||
)
|
||||
.unwrap();
|
||||
for item in chat_rooms.into_iter() {
|
||||
let fields = item.fields;
|
||||
println!("-------分割线-------");
|
||||
for field in fields.into_iter() {
|
||||
if field.column.eq("Reserved7") || field.column.eq("ExtraBuf") {
|
||||
let c = hex::encode(&field.content);
|
||||
print!("{}: {:?}, ", field.column, c);
|
||||
} else {
|
||||
print!(
|
||||
"{}: {}, ",
|
||||
field.column,
|
||||
String::from_utf8(field.content).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exec_db_query_chatroom() {
|
||||
pub mod roomdata {
|
||||
include!("proto/roomdata.rs");
|
||||
}
|
||||
use prost::Message;
|
||||
|
||||
let mut wechat = crate::wechat::WeChat::default();
|
||||
let chat_rooms = crate::wechat::exec_db_query(
|
||||
&mut wechat,
|
||||
String::from("MicroMsg.db"),
|
||||
String::from("select * from ChatRoom where ChatRoomName = '21262247140@chatroom'"),
|
||||
)
|
||||
.unwrap();
|
||||
for item in chat_rooms.into_iter() {
|
||||
let fields = item.fields;
|
||||
for field in fields.into_iter() {
|
||||
if field.column.eq("RoomData") {
|
||||
let c = roomdata::RoomData::decode(field.content.as_slice()).unwrap();
|
||||
println!("{}: {:?}", field.column, c);
|
||||
} else {
|
||||
println!(
|
||||
"{}: {}",
|
||||
field.column,
|
||||
String::from_utf8(field.content).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_query_chat_room_info() {
|
||||
let mut wechat = crate::wechat::WeChat::default();
|
||||
let chat_room =
|
||||
crate::wechat::query_chat_room_info(&mut wechat, String::from("48585852775@chatroom"))
|
||||
.unwrap();
|
||||
print!("chat_room: {:?}", chat_room);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exec_db_query_chatroom_info() {
|
||||
pub mod roomdata {
|
||||
include!("proto/roomdata.rs");
|
||||
}
|
||||
use prost::Message;
|
||||
|
||||
let mut wechat = crate::wechat::WeChat::default();
|
||||
let chat_rooms = crate::wechat::exec_db_query(
|
||||
&mut wechat,
|
||||
String::from("MicroMsg.db"),
|
||||
String::from("select * from ChatRoomInfo where ChatRoomName = '21262247140@chatroom'"),
|
||||
)
|
||||
.unwrap();
|
||||
for item in chat_rooms.into_iter() {
|
||||
let fields = item.fields;
|
||||
for field in fields.into_iter() {
|
||||
if field.column.eq("RoomData") {
|
||||
let c = roomdata::RoomData::decode(field.content.as_slice()).unwrap();
|
||||
println!("{}: {:?}", field.column, c);
|
||||
} else {
|
||||
println!(
|
||||
"{}: {}",
|
||||
field.column,
|
||||
String::from_utf8(field.content).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exec_db_query_contact_head_img_url() {
|
||||
pub mod roomdata {
|
||||
include!("proto/roomdata.rs");
|
||||
}
|
||||
use prost::Message;
|
||||
|
||||
let mut wechat = crate::wechat::WeChat::default();
|
||||
let chat_rooms = crate::wechat::exec_db_query(
|
||||
&mut wechat,
|
||||
String::from("MicroMsg.db"),
|
||||
String::from(
|
||||
"select * from ContactHeadImgUrl where usrName = '25984981691552386@openim'",
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
for item in chat_rooms.into_iter() {
|
||||
println!("-------分割线-------");
|
||||
let fields = item.fields;
|
||||
for field in fields.into_iter() {
|
||||
if field.column.eq("RoomData") {
|
||||
let c = roomdata::RoomData::decode(field.content.as_slice()).unwrap();
|
||||
println!("{}: {:?}", field.column, c);
|
||||
} else {
|
||||
println!(
|
||||
"{}: {}",
|
||||
field.column,
|
||||
String::from_utf8(field.content).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_query_contact_info() {
|
||||
let mut wechat = crate::wechat::WeChat::default();
|
||||
let contact_info = crate::wechat::query_contact_info(
|
||||
&mut wechat,
|
||||
String::from("25984981691552386@openim"),
|
||||
)
|
||||
.unwrap();
|
||||
println!("contact_info: {:?}", contact_info);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_self_wx_id() {
|
||||
let mut wechat = crate::wechat::WeChat::default();
|
||||
@ -1083,9 +1503,9 @@ mod test {
|
||||
let mut wechat = crate::wechat::WeChat::default();
|
||||
let status = crate::wechat::send_text(
|
||||
&mut wechat,
|
||||
String::from("Hello, wcferry!"),
|
||||
String::from("filehelper"),
|
||||
String::from(""),
|
||||
String::from("艾特测试"),
|
||||
String::from("21262247140@chatroom"),
|
||||
String::from("@jingmo0614"),
|
||||
)
|
||||
.unwrap();
|
||||
println!("Success: {}", status);
|
||||
|
Loading…
Reference in New Issue
Block a user