feat: 群功能

This commit is contained in:
hugy 2023-07-10 20:26:25 +08:00
parent 23fc28d011
commit d33df9391e
6 changed files with 426 additions and 83 deletions

View File

@ -514,3 +514,131 @@ enableHttp=0时使用ipport的tcp服务回传消息。
``` javascript ``` javascript
{"code":345686720,"msg":"success","data":null} {"code":345686720,"msg":"success","data":null}
``` ```
#### 9.获取群详情**
###### 接口功能
> 获取群详情
###### 接口地址
> [/api/getChatRoomDetailInfo](/api/getChatRoomDetailInfo)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 群id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|群详细内容|
|  chatRoomId|string|群id|
|  notice|string|公告通知|
|  admin|string|群管理|
|  xml|string|xml信息|
###### 接口示例
入参:
``` javascript
{
"chatRoomId": "12222@chatroom"
}
```
响应:
``` javascript
{"code":345686720,"msg":"success","data":{
"chatRoomId":"12222@chatroom",
"notice":"test",
"admin":"wxid_122333",
"xml":"",
}}
```
#### 10.添加群成员**
###### 接口功能
> 获取群详情
###### 接口地址
> [/api/addMemberToChatRoom](/api/addMemberToChatRoom)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 群id |
|memberIds |true |string| 成员id多个用,分隔 |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功,负数失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"21363231004@chatroom",
"memberIds":"wxid_oyb662qhop4422"
}
```
响应:
``` javascript
{"code":1,"msg":"success","data":null}
```
#### 11.修改群昵称**
###### 接口功能
> 修改群昵称
###### 接口地址
> [/api/modifyNickname](/api/modifyNickname)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 群id |
|wxid |true |string| 自己的wxid |
|nickName |true |string| 昵称 |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"31004@chatroom",
"wxid":"wxid_2721221512",
"nickName":"1221"
}
```
响应:
``` javascript
{"code":1,"msg":"success","data":null}
```

View File

@ -29,6 +29,14 @@ std::wstring GetWStringParam(nlohmann::json data, std::string key) {
return wxhelper::Utils::UTF8ToWstring(data[key].get<std::string>()); return wxhelper::Utils::UTF8ToWstring(data[key].get<std::string>());
} }
std::vector<std::wstring> GetArrayParam(nlohmann::json data, std::string key) {
std::vector<std::wstring> result;
std::wstring param = GetWStringParam(data, key);
result = wxhelper::Utils::split(param, L',');
return result;
}
void StartHttpServer(wxhelper::HttpServer *server) { void StartHttpServer(wxhelper::HttpServer *server) {
int port = server->GetPort(); int port = server->GetPort();
std::string lsten_addr = "http://0.0.0.0:" + std::to_string(port); std::string lsten_addr = "http://0.0.0.0:" + std::to_string(port);
@ -123,7 +131,8 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
return ret; return ret;
} else if (mg_http_match_uri(hm, "/api/userInfo")) { } else if (mg_http_match_uri(hm, "/api/userInfo")) {
common::SelfInfoInner self_info; common::SelfInfoInner self_info;
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->GetSelfInfo(self_info); INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetSelfInfo(self_info);
nlohmann::json ret_data = { nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}}; {"code", success}, {"data", {}}, {"msg", "success"}};
if (success) { if (success) {
@ -148,13 +157,15 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
} else if (mg_http_match_uri(hm, "/api/sendTextMsg")) { } else if (mg_http_match_uri(hm, "/api/sendTextMsg")) {
std::wstring wxid = GetWStringParam(j_param, "wxid"); std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring msg = GetWStringParam(j_param, "msg"); std::wstring msg = GetWStringParam(j_param, "msg");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->SendTextMsg(wxid, msg); INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->SendTextMsg(wxid, msg);
nlohmann::json ret_data = { nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}}; {"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump(); ret = ret_data.dump();
return ret; return ret;
} else if (mg_http_match_uri(hm, "/api/hookSyncMsg")) { } else if (mg_http_match_uri(hm, "/api/hookSyncMsg")) {
INT64 success = wxhelper::hooks::HookSyncMsg("127.0.0.1",19099,"",3000,false); INT64 success =
wxhelper::hooks::HookSyncMsg("127.0.0.1", 19099, "", 3000, false);
nlohmann::json ret_data = { nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}}; {"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump(); ret = ret_data.dump();
@ -162,7 +173,8 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
} else if (mg_http_match_uri(hm, "/api/sendImagesMsg")) { } else if (mg_http_match_uri(hm, "/api/sendImagesMsg")) {
std::wstring wxid = GetWStringParam(j_param, "wxid"); std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring path = GetWStringParam(j_param, "imagePath"); std::wstring path = GetWStringParam(j_param, "imagePath");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->SendImageMsg(wxid, path); INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->SendImageMsg(wxid, path);
nlohmann::json ret_data = { nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}}; {"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump(); ret = ret_data.dump();
@ -170,14 +182,16 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
} else if (mg_http_match_uri(hm, "/api/sendFileMsg")) { } else if (mg_http_match_uri(hm, "/api/sendFileMsg")) {
std::wstring wxid = GetWStringParam(j_param, "wxid"); std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring path = GetWStringParam(j_param, "filePath"); std::wstring path = GetWStringParam(j_param, "filePath");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->SendFileMsg(wxid, path); INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->SendFileMsg(wxid, path);
nlohmann::json ret_data = { nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}}; {"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump(); ret = ret_data.dump();
return ret; return ret;
} else if (mg_http_match_uri(hm, "/api/getContactList")) { } else if (mg_http_match_uri(hm, "/api/getContactList")) {
std::vector<common::ContactInner> vec; std::vector<common::ContactInner> vec;
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->GetContacts(vec); INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetContacts(vec);
nlohmann::json ret_data = { nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}}; {"code", success}, {"data", {}}, {"msg", "success"}};
for (unsigned int i = 0; i < vec.size(); i++) { for (unsigned int i = 0; i < vec.size(); i++) {
@ -231,9 +245,11 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
UINT64 db_handle = GetINT64Param(j_param, "dbHandle"); UINT64 db_handle = GetINT64Param(j_param, "dbHandle");
std::string sql = GetStringParam(j_param, "sql"); std::string sql = GetStringParam(j_param, "sql");
std::vector<std::vector<std::string>> items; std::vector<std::vector<std::string>> items;
int success = wxhelper::DB::GetInstance().Select(db_handle, sql.c_str(), items); int success =
nlohmann::json ret_data = { wxhelper::DB::GetInstance().Select(db_handle, sql.c_str(), items);
{"data", nlohmann::json::array()}, {"code", success}, {"msg", "success"}}; nlohmann::json ret_data = {{"data", nlohmann::json::array()},
{"code", success},
{"msg", "success"}};
if (success == 0) { if (success == 0) {
ret_data["msg"] = "no data"; ret_data["msg"] = "no data";
ret = ret_data.dump(); ret = ret_data.dump();
@ -248,6 +264,49 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
} }
ret = ret_data.dump(); ret = ret_data.dump();
return ret; return ret;
} else if (mg_http_match_uri(hm, "/api/getChatRoomDetailInfo")) {
std::wstring chat_room_id = GetWStringParam(j_param, "chatRoomId");
common::ChatRoomInfoInner chat_room_detail;
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetChatRoomDetailInfo(
chat_room_id, chat_room_detail);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
nlohmann::json detail = {
{"chatRoomId", chat_room_detail.chat_room_id},
{"notice", chat_room_detail.notice},
{"admin", chat_room_detail.admin},
{"xml", chat_room_detail.xml},
};
ret_data["data"] = detail;
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/addMemberToChatRoom")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
std::vector<std::wstring> wxids = GetArrayParam(j_param, "memberIds");
std::vector<std::wstring> wxid_list;
for (unsigned int i = 0; i < wxids.size(); i++) {
wxid_list.push_back(wxids[i]);
}
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->AddMemberToChatRoom(
room_id, wxid_list);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/modifyNickname")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring nickName = GetWStringParam(j_param, "nickName");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->ModChatRoomMemberNickName(
room_id, wxid, nickName);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else { } else {
nlohmann::json ret_data = { nlohmann::json ret_data = {
{"code", 200}, {"data", {}}, {"msg", "not support url"}}; {"code", 200}, {"data", {}}, {"msg", "not support url"}};

View File

@ -10,6 +10,20 @@ namespace func = wxhelper::V3_9_5_81::function;
namespace wxhelper { namespace wxhelper {
prototype::WeChatString * BuildWechatString(const std::wstring &ws){
prototype::WeChatString *p = Utils::WxHeapAlloc<prototype::WeChatString>(
sizeof(prototype::WeChatString));
wchar_t *p_chat_room_id = Utils::WxHeapAlloc<wchar_t>((ws.size() + 1) * 2);
wmemcpy(p_chat_room_id, ws.c_str(), ws.size() + 1);
p->ptr = p_chat_room_id;
p->length = static_cast<DWORD>(ws.size());
p->max_length = static_cast<DWORD>(ws.size());
p->c_len = 0;
p->c_ptr = 0;
return p;
}
Manager::Manager(UINT64 base) : base_addr_(base) {} Manager::Manager(UINT64 base) : base_addr_(base) {}
Manager::~Manager() {} Manager::~Manager() {}
INT64 Manager::CheckLogin() { INT64 Manager::CheckLogin() {
@ -342,4 +356,92 @@ INT64 Manager::GetContacts(std::vector<common::ContactInner> &vec) {
} }
return success; return success;
} }
INT64 Manager::GetChatRoomDetailInfo(const std::wstring &room_id,
common::ChatRoomInfoInner &room_info) {
INT64 success = -1;
UINT64 get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
UINT64 get_chat_room_detail_addr =
base_addr_ + offset::kGetChatRoomDetailInfo;
UINT64 new_chat_room_info_addr = base_addr_ + offset::kNewChatRoomInfo;
UINT64 free_chat_room_info_addr = base_addr_ + offset::kFreeChatRoomInfo;
func::__GetChatRoomMgr get_chat_room_mgr =
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
func::__GetChatRoomDetailInfo get_chat_room_detail =
(func::__GetChatRoomDetailInfo)get_chat_room_detail_addr;
func::__NewChatRoomInfo new_chat_room_info =
(func::__NewChatRoomInfo)new_chat_room_info_addr;
func::__FreeChatRoomInfo free_chat_room_info =
(func::__FreeChatRoomInfo)free_chat_room_info_addr;
prototype::WeChatString chat_room_id(room_id);
char chat_room_info[0x148] = {0};
UINT64 p_chat_room_info =
new_chat_room_info(reinterpret_cast<UINT64>(&chat_room_info));
UINT64 mgr = get_chat_room_mgr();
success = get_chat_room_detail(mgr, reinterpret_cast<UINT64>(&chat_room_id),
p_chat_room_info, 1);
room_info.admin = Utils::ReadWstringThenConvert(p_chat_room_info + 0x48);
room_info.chat_room_id =
Utils::ReadWstringThenConvert(p_chat_room_info + 0x8);
room_info.notice = Utils::ReadWstringThenConvert(p_chat_room_info + 0x28);
room_info.xml = Utils::ReadWstringThenConvert(p_chat_room_info + 0x78);
free_chat_room_info(p_chat_room_info);
return success;
}
INT64 Manager::AddMemberToChatRoom(const std::wstring &room_id,
const std::vector<std::wstring> &members) {
INT64 success = -1;
UINT64 get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
UINT64 add_members_addr = base_addr_ + offset::kDoAddMemberToChatRoom;
func::__GetChatRoomMgr get_chat_room_mgr =
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
func::__DoAddMemberToChatRoom add_members =
(func::__DoAddMemberToChatRoom)add_members_addr;
prototype::WeChatString *chat_room_id = (prototype::WeChatString *)HeapAlloc(
GetProcessHeap(), 0, sizeof(prototype::WeChatString));
wchar_t *p_chat_room_id =
(wchar_t *)HeapAlloc(GetProcessHeap(), 0, (room_id.size() + 1) * 2);
wmemcpy(p_chat_room_id, room_id.c_str(), room_id.size() + 1);
chat_room_id->ptr = p_chat_room_id;
chat_room_id->length = static_cast<DWORD>(room_id.size());
chat_room_id->max_length = static_cast<DWORD>(room_id.size());
chat_room_id->c_len = 0;
chat_room_id->c_ptr = 0;
std::vector<prototype::WeChatString> member_list;
UINT64 temp[2] = {0};
common::VectorInner *list = (common::VectorInner *)&member_list;
INT64 members_ptr = (INT64)&list->start;
for (int i = 0; i < members.size(); i++) {
prototype::WeChatString member(members[i]);
member_list.push_back(member);
}
UINT64 mgr = get_chat_room_mgr();
success =
add_members(mgr, members_ptr, reinterpret_cast<UINT64>(chat_room_id),
reinterpret_cast<UINT64>(&temp));
return success;
}
INT64 Manager::ModChatRoomMemberNickName(const std::wstring &room_id,
const std::wstring &wxid,
const std::wstring &nickname) {
INT64 success = -1;
UINT64 mod_addr = base_addr_ + offset::kDoModChatRoomMemberNickName;
func::__DoModChatRoomMemberNickName modify =
(func::__DoModChatRoomMemberNickName)mod_addr;
const wchar_t *p = room_id.c_str();
prototype::WeChatString *chat_room_id = BuildWechatString(room_id);
prototype::WeChatString *self_id = BuildWechatString(wxid);
prototype::WeChatString *name = BuildWechatString(nickname);
success = modify(
reinterpret_cast<UINT64>(p), reinterpret_cast<UINT64>(chat_room_id),
reinterpret_cast<UINT64>(self_id), reinterpret_cast<UINT64>(name));
return success;
}
} // namespace wxhelper` } // namespace wxhelper`

View File

@ -13,6 +13,15 @@ class Manager {
INT64 SendImageMsg(const std::wstring& wxid, const std::wstring& image_path); INT64 SendImageMsg(const std::wstring& wxid, const std::wstring& image_path);
INT64 SendFileMsg(const std::wstring& wxid, const std::wstring& file_path); INT64 SendFileMsg(const std::wstring& wxid, const std::wstring& file_path);
INT64 GetContacts(std::vector<common::ContactInner> &vec); INT64 GetContacts(std::vector<common::ContactInner> &vec);
INT64 GetChatRoomDetailInfo(const std::wstring& room_id,
common::ChatRoomInfoInner& room_info);
INT64 AddMemberToChatRoom(const std::wstring& room_id,
const std::vector<std::wstring>& members);
INT64 ModChatRoomMemberNickName(const std::wstring& room_id,
const std::wstring& wxid,
const std::wstring& nickname);
private: private:
UINT64 base_addr_; UINT64 base_addr_;
}; };

View File

@ -57,6 +57,7 @@ class Utils {
static std::string ImageXor(std::string buf); static std::string ImageXor(std::string buf);
static std::wstring ReadWstring(INT64 addr); static std::wstring ReadWstring(INT64 addr);
static std::string ReadWstringThenConvert(INT64 addr); static std::string ReadWstringThenConvert(INT64 addr);
template <typename T1, typename T2> template <typename T1, typename T2>
static std::vector<T1> split(T1 str, T2 letter) { static std::vector<T1> split(T1 str, T2 letter) {
std::vector<T1> arr; std::vector<T1> arr;
@ -82,6 +83,12 @@ class Utils {
temp += v_arr[v_arr.size() - 1]; temp += v_arr[v_arr.size() - 1];
return temp; return temp;
} }
template <typename T>
static T *WxHeapAlloc(size_t n) {
return (T *)HeapAlloc(GetProcessHeap(), 0, n);
}
}; };
} // namespace wxhelper } // namespace wxhelper
#endif #endif

View File

@ -161,6 +161,29 @@ struct ContactInner {
} }
}; };
struct ChatRoomInfoInner {
std::string chat_room_id;
std::string notice;
std::string admin;
std::string xml;
ChatRoomInfoInner(){
chat_room_id = "";
notice = "";
admin = "";
xml = "";
}
};
struct VectorInner {
#ifdef _DEBUG
INT64 head;
#endif
INT64 start;
INT64 finsh;
INT64 end;
};
} // namespace common } // namespace common
namespace V3_9_5_81 { namespace V3_9_5_81 {
namespace function { namespace function {
@ -184,6 +207,15 @@ typedef UINT64(*__Free)();
typedef UINT64 (*__GetContactMgr)(); typedef UINT64 (*__GetContactMgr)();
typedef UINT64 (*__GetContactList)(UINT64,UINT64); typedef UINT64 (*__GetContactList)(UINT64,UINT64);
typedef UINT64 (*__GetChatRoomMgr)();
typedef UINT64 (*__NewChatRoomInfo)(UINT64);
typedef UINT64 (*__FreeChatRoomInfo)(UINT64);
typedef UINT64 (*__GetChatRoomDetailInfo)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__DoAddMemberToChatRoom)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__DoModChatRoomMemberNickName)(UINT64,UINT64,UINT64,UINT64);
} // namespace function } // namespace function
namespace prototype { namespace prototype {
@ -269,6 +301,12 @@ const UINT64 kMultiDBMgr= 0x3acfb68;
const UINT64 kPublicMsgMgr = 0x3acc268; const UINT64 kPublicMsgMgr = 0x3acc268;
const UINT64 kFavoriteStorageMgr = 0x3acf0d0; const UINT64 kFavoriteStorageMgr = 0x3acf0d0;
const UINT64 kChatRoomMgr = 0x8e9d30;
const UINT64 kGetChatRoomDetailInfo = 0xe73590;
const UINT64 kNewChatRoomInfo = 0x12006b0;
const UINT64 kFreeChatRoomInfo = 0x1200890;
const UINT64 kDoAddMemberToChatRoom = 0xe63c70;
const UINT64 kDoModChatRoomMemberNickName = 0xe6db00;
} // namespace offset } // namespace offset
} // namespace V3_9_5_81 } // namespace V3_9_5_81