From 61c9e6f8c1f76698dfd1b59ed94dd4ea7fd0283d Mon Sep 17 00:00:00 2001 From: hugy <504650082@qq.com> Date: Thu, 30 Mar 2023 23:08:15 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E8=AF=AD=E9=9F=B3=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 44 +++++++++++++++- src/api.cc | 8 +++ src/api.h | 1 + src/download.cc | 30 +++++++++++ src/download.h | 2 + src/get_db_handle.cc | 120 +++++++++++++++++++++++++++++++++++++++++++ src/get_db_handle.h | 2 + 7 files changed, 206 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d578087..bad1057 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,8 @@ 53.朋友圈首页 54.朋友圈下一页 -56.获取消息附件(图片,视频,文件) +56.获取消息附件(图片,视频,文件) +57.获取消息语音文件 ### 接口文档: @@ -1542,6 +1543,47 @@ ``` +#### 57.获取语音文件** +###### 接口功能 +> 根据消息id,获取该语音消息的语音文件,文件为silk3格式,可以自行转换mp3. + +###### 接口地址 +> [/api/?type=57](/api/?type=57) + +###### HTTP请求方式 +> POST JSON + +###### 请求参数 +|参数|必选|类型|说明| +|---|---|---|---| +|msgId |true |string| 消息id | +|voiceDir |true |string| 语音文件保存的目录,文件名称为 (msgid).amr | + + +###### 返回字段 +|返回字段|字段类型|说明 | +|---|---|---| +|code|int|返回状态,1成功, 非0失败| +|result|string|成功提示| + + + +###### 接口示例 +入参: +``` javascript +{ + "msgId": 3224560917391784099, + "voiceDir" : "c:\\voice" + +} + +``` +响应: +``` javascript +{"code":1,"result":"OK"} +``` + + #### 感谢 https://github.com/ljc545w/ComWeChatRobot diff --git a/src/api.cc b/src/api.cc index 0e3da12..a4785fe 100644 --- a/src/api.cc +++ b/src/api.cc @@ -694,6 +694,14 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) { ret = ret_data.dump(); break; } + case WECHAT_GET_VOICE:{ + ULONG64 msg_id = get_http_param_ulong64(hm, j_param, "msgId", is_post); + wstring voice_dir = get_http_req_param(hm, j_param, "voiceDir", is_post); + int success = GetVoice(msg_id,WS2LW(voice_dir)); + json ret_data = {{"code", success}, {"result", "OK"}}; + ret = ret_data.dump(); + break; + } default: break; } diff --git a/src/api.h b/src/api.h index 3b44f4a..951bc67 100644 --- a/src/api.h +++ b/src/api.h @@ -71,6 +71,7 @@ typedef enum WECHAT_HTTP_APISTag WECHAT_SNS_GET_NEXT_PAGE, WECHAT_CONTACT_NAME, WECHAT_ATTACH_DOWNLOAD, + WECHAT_GET_VOICE, } WECHAT_HTTP_APIS, *PWECHAT_HTTP_APIS; diff --git a/src/download.cc b/src/download.cc index d3d5182..7544d8c 100644 --- a/src/download.cc +++ b/src/download.cc @@ -5,6 +5,7 @@ #include "get_db_handle.h" #include "wechat_data.h" +#include "base64.h" #define WX_NEW_CHAT_MSG_OFFSET 0x76f010 #define WX_GET_PRE_DOWNLOAD_MGR_OFFSET 0x80f110 @@ -179,5 +180,34 @@ int DoDownloadTask(ULONG64 msg_id) { POPAD } + return success; +} + +int GetVoice(ULONG64 msg_id, wchar_t *dir) { + int success = -1; + string buff = GetVoiceBuffByMsgId(msg_id); + if (buff.size() == 0) { + success = 0; + return success; + } + wstring save_path = wstring(dir); + if (!FindOrCreateDirectoryW(save_path.c_str())) { + success = -2; + return success; + } + save_path = save_path + L"\\" + to_wstring(msg_id) + L".amr"; + HANDLE file_handle = CreateFileW(save_path.c_str(), GENERIC_ALL, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_handle == INVALID_HANDLE_VALUE) { + #ifdef _DEBUG + wcout <<" save_path =" < dbmap; std::vector dbs; @@ -180,6 +209,60 @@ std::vector GetDbHandles() { DWORD *)(p_contact_addr + DB_FUNCTION_MSG_OFFSET + DB_NAME_OFFSET))); dbmap[bizchat_msg_name] = bizchat_msg_db; } + // Storage + DWORD storage_start = *(DWORD *)(p_contact_addr + STORAGE_START_OFFSET); + DWORD storage_end = *(DWORD *)(p_contact_addr + STORAGE_END_OFFSET); + + // do { + // DWORD vtable_ptr = *(DWORD *)(storage_start); + + // if(vtable_ptr == base + OP_LOG_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + CHAT_MSG_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + CHAT_CR_MSG_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + SESSION_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + APP_INFO_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + HEAD_IMG_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + HEAD_IMG_URL_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + BIZ_INFO_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + TICKET_INFO_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + CHAT_ROOM_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + CHAT_ROOM_INFO_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + MEDIA_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + NAME_2_ID_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + EMOTION_PACKAGE_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + EMOTION_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + BUFINFO_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + CUSTOM_EMOTION_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + DEL_SESSIONINFO_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + FUNCTION_MSG_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + FUNCTION_MSG_TASK_STORAGE_VFTABLE){ + + // }else if(vtable_ptr == base + REVOKE_MSG_STORAGE_VFTABLE){ + + // } + + // storage_start = storage_start + 0x4; + // } while (storage_start != storage_end); + DWORD multi_db_mgr_addr = base + MULTI_DB_MSG_MGR_OFFSET; DWORD public_msg_mgr_addr = base + PUBLIC_MSG_MGR_OFFSET; DWORD favorite_storage_mgr_addr = base + FAVORITE_STORAGE_MGR_OFFSET; @@ -207,6 +290,21 @@ std::vector GetDbHandles() { dbs.push_back(msg0_db); wstring msg_db_name = wstring((wchar_t *)(*(DWORD *)(db_addr))); dbmap[msg_db_name] = msg0_db; + + // BufInfoStorage + DWORD buf_info_addr = *(DWORD *)(db_addr + 0x14); + + DWORD buf_info_handle = *(DWORD *)(buf_info_addr + 0x38); + DatabaseInfo media_msg0_db{0}; + media_msg0_db.db_name = (wchar_t *)(*(DWORD *)(buf_info_addr + 0x4C)); + media_msg0_db.db_name_len = *(DWORD *)(buf_info_addr + 0x50); + media_msg0_db.handle = buf_info_handle; + ExecuteSQL(buf_info_handle, + "select * from sqlite_master where type=\"table\";", + (DWORD)GetDbInfo, &media_msg0_db); + dbs.push_back(media_msg0_db); + wstring media_msg_db_name = wstring((wchar_t *)(*(DWORD *)(buf_info_addr + 0x4C))); + dbmap[media_msg_db_name] = media_msg0_db; } } @@ -315,4 +413,26 @@ vector GetChatMsgByMsgId(ULONG64 msgid){ return result[1]; } return {}; +} + +std::string GetVoiceBuffByMsgId(ULONG64 msgid) { + char sql[260] = {0}; + sprintf_s(sql, "SELECT Buf from Media WHERE Reserved0=%llu;", msgid); + wchar_t dbname[20] = {0}; + for (int i = 0;; i++) { + swprintf_s(dbname, L"MediaMSG%d.db", i); + DWORD handle = GetDbHandleByDbName(dbname); + #ifdef _DEBUG + cout <<" handle =" <> result; + int ret = Select(handle, (const char *)sql, result); + #ifdef _DEBUG + cout <<" size =" < GetDbHandles(); DWORD GetDbHandleByDbName(wchar_t *dbname); unsigned int GetLocalIdByMsgId(ULONG64 msgid, int &dbIndex); std::vector GetChatMsgByMsgId(ULONG64 msgid); + +std::string GetVoiceBuffByMsgId(ULONG64 msgid); #endif \ No newline at end of file