Compare commits

..
Author SHA1 Message Date
ttttupupandGitHub d7b981c9a2 Merge pull request #378 from atorber/dev-3.9.5.81
增加 3.9.5.81 的ts/js sdk及优化python示例
2024-03-23 11:47:36 +08:00
LuChao 006bc9dac3 补充demo调用方法 2024-03-21 20:33:05 +08:00
LuChao 89a7fc8196 增加ts客户端sdk
- 增加ts客户端sdk
- 优化python代码
2024-03-21 18:58:09 +08:00
LuChaoandGitHub ffa3ea49d9 Merge pull request #1 from atorber/main
merge from main
2024-03-21 15:53:58 +08:00
ttttupupandGitHub e4656e5139 Merge pull request #373 from sglmsn/main
适配3.9.8.25部分接口
2024-03-08 17:02:54 +08:00
sg 0bd8b47da0 适配新版本 2024-03-08 16:54:42 +08:00
sg 7a5a8a90df 适配新版本 2024-03-08 15:44:50 +08:00
sg b5cc83be77 适配新版本 2024-02-22 15:44:30 +08:00
ttttupupandGitHub 3b5f191bf2 Merge pull request #352 from yzqzy/main
feat: add nodejs client
2024-02-06 20:15:06 +08:00
杨志强 dff024745c feat: add nodejs client 2024-02-02 17:08:06 +08:00
ttttupupandGitHub 8b6e2d7160 Merge pull request #323 from ttttupup/dev-3.9.5.81
Dev 3.9.5.81
2023-11-14 20:50:21 +08:00
ttttupup 5d7c1d1d48 fix: ocr修复 closed issues #305 #321 2023-11-14 20:38:17 +08:00
hugy d574af863a 'fix:debug环境定义' 2023-08-31 09:44:09 +08:00
ttttupupandGitHub 632d4222fa Merge pull request #274 from ttttupup/dev-3.9.5.81
Dev 3.9.5.81
2023-08-31 09:33:55 +08:00
hugy ee7d4ee9a3 Merge branch 'dev-3.9.5.81' of https://github.com/ttttupup/wxhelper into dev-3.9.5.81
merge:合并
2023-08-31 09:26:03 +08:00
hugy 1ba2ed87b7 'feat:拍一拍,ocr' 2023-08-31 08:44:35 +08:00
hugy 2863f8258f feat: 发送小程序(待完善) 2023-08-31 08:44:35 +08:00
hugy fa31de81e0 feat:新增发送公众号消息,下载附件,图片解码,获取语音,发送自定义表情 2023-08-31 08:44:35 +08:00
hugy 758b773d99 fix: 返回值修改 2023-08-31 08:44:35 +08:00
hugy b17af7a9e0 doc: client 2023-08-31 08:44:35 +08:00
hugy b364885daf feat: 发送@消息 2023-08-31 08:44:35 +08:00
hugy 427b43304c feat:收藏 2023-08-31 08:44:35 +08:00
hugy 0593dbe79e feat: sns 2023-08-31 08:44:35 +08:00
hugy 13f182a95b doc:更新文档 2023-08-31 08:44:34 +08:00
hugy 1718ddefdd feat:退群和转发 2023-08-31 08:44:34 +08:00
hugy 4c3c02283e fix:删除测试 2023-08-31 08:44:34 +08:00
hugy bb46b9b8d9 feat: 建群 2023-08-31 08:44:34 +08:00
hugy e806914775 feat: 邀请入群,hook日志 2023-08-31 08:44:34 +08:00
hugy e5ead96c05 fix: 消除警告 2023-08-31 08:44:34 +08:00
hugy 938e7e9bc2 feat: 群消息置顶 2023-08-31 08:44:34 +08:00
hugy 8acad316a9 fix: hook http功能 2023-08-31 08:44:34 +08:00
hugy a5a2f0f17d feat: 群功能相关 2023-08-31 08:44:34 +08:00
ttttupupandGitHub 3b76b2332c Merge pull request #272 from terry-tt/main
go客户端
2023-08-29 13:33:23 +08:00
ttttupupandGitHub 5088f5171b Merge pull request #269 from ttttupup/dev-3.9.5.81
feat: 发送小程序(待完善)
2023-08-29 13:33:09 +08:00
litao d8c8078f5c go客户端 2023-08-29 11:25:15 +08:00
hugy 8bdc8c7e46 feat: 发送小程序(待完善) 2023-08-24 17:05:41 +08:00
ttttupupandGitHub 212613e3b6 Merge pull request #250 from ttttupup/dev-3.9.5.81
feat:新增发送公众号消息,下载附件,图片解码,获取语音,发送自定义表情
2023-08-10 22:29:33 +08:00
hugy 608c6d26de feat:新增发送公众号消息,下载附件,图片解码,获取语音,发送自定义表情 2023-08-10 17:13:48 +08:00
ttttupupandGitHub 2f6760e28e Merge pull request #247 from ttttupup/dev-3.9.5.81
Dev 3.9.5.81
2023-08-08 20:53:03 +08:00
hugy 6436ce072a fix: 返回值修改 2023-08-08 20:46:08 +08:00
hugy 58caad4f34 doc: client 2023-08-08 17:44:49 +08:00
hugy bdf91943f3 feat: 发送@消息 2023-08-08 17:41:30 +08:00
ttttupupandGitHub 41b3b6b18d Merge pull request #243 from ttttupup/dev-3.9.5.81
Dev 3.9.5.81
2023-08-05 10:56:09 +08:00
hugy 129bb55c36 feat:收藏 2023-08-05 10:52:28 +08:00
hugy e9a6e0da57 feat: sns 2023-08-04 16:40:10 +08:00
ttttupupandGitHub e6e72dd492 Merge pull request #234 from ttttupup/dev-3.9.5.81
Dev 3.9.5.81
2023-07-31 16:35:37 +08:00
hugy 9b4d326d63 doc:更新文档 2023-07-31 16:18:05 +08:00
hugy 64ba6007a8 feat:退群和转发 2023-07-31 16:11:47 +08:00
ttttupupandGitHub f9b859baca Merge pull request #233 from ttttupup/dev-3.9.5.81
fix:删除测试
2023-07-29 17:15:57 +08:00
hugy ae44434662 fix:删除测试 2023-07-29 17:11:36 +08:00
ttttupupandGitHub 4ab28cfc03 Merge pull request #230 from ttttupup/dev-3.9.5.81
feat: 建群
2023-07-29 10:07:41 +08:00
hugy 1268d37a57 feat: 建群 2023-07-29 10:03:59 +08:00
ttttupupandGitHub e6c57f8ede Merge pull request #228 from ttttupup/dev-3.9.5.81
feat: 邀请入群,hook日志
2023-07-27 21:19:32 +08:00
hugy 17aff3b6aa feat: 邀请入群,hook日志 2023-07-27 21:18:42 +08:00
ttttupupandGitHub 51a4693330 Merge pull request #225 from ttttupup/dev-3.9.5.81
Dev 3.9.5.81
2023-07-22 09:19:20 +08:00
hugy 7e06eaf4e4 fix: 消除警告 2023-07-22 09:17:20 +08:00
hugy b996a9d91c feat: 群消息置顶 2023-07-22 09:13:50 +08:00
ttttupupandGitHub e0c946bf72 Merge pull request #214 from ttttupup/dev-3.9.5.81
Dev 3.9.5.81
2023-07-14 22:28:57 +08:00
41 changed files with 4554 additions and 108 deletions
+4 -1
View File
@@ -32,4 +32,7 @@
*.app
CMakePresets.json
.vscode
out
out
nodejs_client_ts/node_modules
nodejs_client_ts/msgStore.json
nodejs_client_ts/dist
+1091 -1
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
package main
import (
"go_client/tcpserver"
"log"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
tcpserver.Listen(19099)
}
+44
View File
@@ -0,0 +1,44 @@
package tcpserver
import (
"bufio"
"log"
"net"
"strconv"
)
func Listen(port int) {
p := strconv.Itoa(port)
adress := "127.0.0.1:" + p
ln, err := net.Listen("tcp", adress)
if err != nil {
log.Fatal(err)
}
defer ln.Close()
log.Println("tcp server started")
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go handle(conn)
}
}
func handle(conn net.Conn) {
defer func() {
if err := recover(); err != nil {
log.Println("发生了未处理的异常", err)
}
}()
defer conn.Close()
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
line := scanner.Bytes()
log.Println("收到消息:", string(line))
}
if err := scanner.Err(); err != nil {
log.Println("错误:", err)
}
}
+8 -7
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
<version>3.2.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
@@ -14,7 +14,8 @@
<name>wxhk</name>
<description>wxhk</description>
<properties>
<java.version>17</java.version>
<java.version>21</java.version>
<vertx-web-client.version>4.5.3</vertx-web-client.version>
</properties>
<dependencies>
<dependency>
@@ -39,7 +40,7 @@
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.92.Final</version>
<version>4.1.105.Final</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
@@ -50,22 +51,22 @@
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>4.4.2</version>
<version>${vertx-web-client.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
<version>4.4.2</version>
<version>${vertx-web-client.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-client</artifactId>
<version>4.4.2</version>
<version>${vertx-web-client.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-mysql-client</artifactId>
<version>4.4.2</version>
<version>${vertx-web-client.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -42,6 +42,11 @@ public class PrivateChatMsg implements Serializable {
private String signature;
private String time;
private Integer timestamp;
/**
* 对用户,如果是文件助手是filehelper
*/
private String toUser;
/**
* 类型
*/
@@ -15,4 +15,17 @@ import lombok.experimental.Accessors;
public class OpenHook implements SendMsg<OpenHook> {
String port;
String ip;
/**
* 0/1 :1.启用http 0.不启用http
*/
boolean enableHttp;
/**
* 超时时间,单位ms
*/
String timeout;
/**
* http的请求地址,enableHttp=1时,不能为空
*/
String url;
}
@@ -18,6 +18,7 @@ import org.w3c.dom.NodeList;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -50,7 +51,12 @@ public class WxMsgHandle {
@PostConstruct
public void init() {
add(chatMsg -> {
wxSmgServer.私聊(chatMsg);
if(Objects.equals(chatMsg.getToUser(), FILEHELPER)){
wxSmgServer.文件助手(chatMsg);
}else{
wxSmgServer.私聊(chatMsg);
}
return null;
}, WxMsgType.私聊信息);
add(chatMsg -> {
@@ -174,8 +180,8 @@ public class WxMsgHandle {
if (monery.startsWith("¥")) {
String substring = monery.substring(1);
BigDecimal decimal = new BigDecimal(substring);
log.info("收款:{},付款人:{},付款备注:{}", decimal.stripTrailingZeros().toPlainString(), chatMsg.getFromUser(), remark);
wxSmgServer.收款之后(new PayoutInformation(chatMsg.getFromUser(), decimal, remark));
log.info("收款:{},付款人:{},付款备注:{}", decimal.stripTrailingZeros().toPlainString(), receiver_username, remark);
wxSmgServer.收款之后(new PayoutInformation(receiver_username, decimal, remark));
return false;
};
@@ -32,12 +32,14 @@ public class WxSmgServerImpl implements com.example.wxhk.server.WxSmgServer {
public void 私聊(PrivateChatMsg chatMsg) {
if (Objects.equals(chatMsg.getIsSendMsg(), 1) && Objects.equals(chatMsg.getIsSendByPhone(), 1)) {
log.info("手机端对:{}发出:{}", chatMsg.getFromUser(), chatMsg.getContent());
}else{
log.info("收到私聊{}",chatMsg);
}
}
@Override
public void 文件助手(PrivateChatMsg chatMsg) {
log.info("文件助手:{}",chatMsg);
}
@Override
@@ -2,7 +2,8 @@ package com.example.wxhk.tcp.vertx;
import com.example.wxhk.WxhkApplication;
import com.example.wxhk.constant.WxMsgType;
import com.example.wxhk.util.HttpAsyncUtil;
import com.example.wxhk.model.request.OpenHook;
import com.example.wxhk.util.HttpSendUtil;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Future;
@@ -75,7 +76,10 @@ public class VertxTcp extends AbstractVerticle implements CommandLineRunner {
listen.onComplete(event -> {
boolean succeeded = event.succeeded();
if (succeeded) {
HttpAsyncUtil.exec(HttpAsyncUtil.Type.开启hook, new JsonObject().put("port", InitWeChat.getVertxPort().toString()).put("ip", "127.0.0.1"));
HttpSendUtil.开启hook(new OpenHook().setPort(InitWeChat.getVertxPort().toString()).setIp("127.0.0.1")
.setEnableHttp(false)
.setTimeout("5000"));
// HttpAsyncUtil.exec(HttpAsyncUtil.Type.开启hook, new JsonObject().put("port", InitWeChat.getVertxPort().toString()).put("ip", "127.0.0.1"));
startPromise.complete();
} else {
startPromise.fail(event.cause());
@@ -24,7 +24,7 @@ public class HttpAsyncUtil {
protected static final Log log = Log.get();
public static Future<HttpResponse<Buffer>> exec(Type type, JsonObject object) {
return client.post(InitWeChat.wxPort, "localhost", "/api/?type=" + type.getType())
return client.post(InitWeChat.wxPort, "localhost", "/api/" + type.getType())
.sendJsonObject(object)
.onSuccess(event ->
{
@@ -36,7 +36,7 @@ public class HttpAsyncUtil {
}
public static Future<HttpResponse<Buffer>> exec(Type type, JsonObject object, Handler<AsyncResult<HttpResponse<Buffer>>> handler) {
return client.post(InitWeChat.wxPort, "localhost", "/api/?type=" + type.getType())
return client.post(InitWeChat.wxPort, "localhost", "/api/" + type.getType())
.sendJsonObject(object)
.onComplete(handler)
;
@@ -45,22 +45,31 @@ public class HttpAsyncUtil {
}
public enum Type {
检查微信登陆("0"),
获取登录信息("1"),
发送文本("2"),
发送at文本("3"),
检查微信登陆("checkLogin"),
获取登录信息("userInfo"),
发送文本("sendTextMsg"),
转发消息("forwardMsg"),
发送at文本("sendAtText"),
发送图片("5"),
发送文件("6"),
开启hook("9"),
关闭hook("10"),
发送文件("sendFileMsg"),
开启hook("hookSyncMsg"),
关闭hook("unhookSyncMsg"),
添加好友("20"),
通过好友申请("23"),
获取群成员("25"),
获取群成员昵称("26"),
删除群成员("27"),
获取群成员("getMemberFromChatRoom"),
获取群成员基础信息("getContactProfile"),
获取群详情("getChatRoomDetailInfo"),
添加群成员("addMemberToChatRoom"),
修改群昵称("modifyNickname"),
删除群成员("delMemberFromChatRoom"),
置顶群消息("topMsg"),
取消置顶群消息("removeTopMsg"),
邀请入群("InviteMemberToChatRoom"),
确认收款("45"),
联系人列表("46"),
联系人列表("getContactList"),
查询微信信息("55"),
下载附件("downloadAttach"),
解码("decodeImage"),
;
@@ -27,7 +27,7 @@ public class HttpSyncUtil {
}
public static JsonObject exec(HttpAsyncUtil.Type type, JsonObject obj) {
String post = engine.send(Request.of("http://localhost:" + InitWeChat.wxPort + "/api/?type=" + type.getType()).method(Method.POST).body(obj.encode())).bodyStr();
String post = engine.send(Request.of("http://localhost:" + InitWeChat.wxPort + "/api/" + type.getType()).method(Method.POST).body(obj.encode())).bodyStr();
if (log.isDebugEnabled()) {
log.debug("type:{},{}", type.getType(), post);
}
@@ -1,4 +1,4 @@
wx.path=D:\\Program Files (x86)\\Tencent\\WeChat\\[3.9.2.23]\\WeChat.exe
wx.path=D:\\Program Files (x86)\\Tencent\\WeChat\\WeChat.exe
wx.port=19088
spring.profiles.active=local
vertx.port=8080
Binary file not shown.
Binary file not shown.
@@ -7,6 +7,8 @@ import org.dromara.hutool.core.lang.Console;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
@SpringBootTest
@@ -41,5 +43,7 @@ class HttpSendUtilTest {
void 获取群成员() {
GroupMembers 获取群成员 = HttpSendUtil.获取群成员(new GetGroupMembers().setChatRoomId("24964676359@chatroom"));
Console.log(获取群成员);
Duration between = Duration.between(LocalDateTime.now(), LocalDateTime.now());
}
}
+26
View File
@@ -0,0 +1,26 @@
const net = require('net')
const server = net.createServer(socket => {
console.log('New client connected')
let data = Buffer.from('')
socket.on('data', data => {
data = Buffer.concat([data, chunk])
console.log(`Received data: ${data}`)
})
socket.on('end', () => {
const decodedData = data.toString('utf8')
console.log(`Received data: ${decodedData}`)
})
socket.on('close', () => {
console.log('Client disconnected')
})
})
const port = 19099
server.listen(port, () => {
console.log(`Server listening on port ${port}`)
})
+23
View File
@@ -0,0 +1,23 @@
# TypeScript Client
## 快速开始
1. 启动WebSoket服务用语接收消息
```shell
npm run ws_server
```
2. 运行测试demo
```
npm run start
```
## 说明
./src/index.ts 包含3.9.5.81支持的所有接口封装
./tcp_server.ts 接收消息的服务端代码
./example/ding-dong-bot.ts SDK使用示例
+137
View File
@@ -0,0 +1,137 @@
import * as wxhelper from '../src/index'
import net from 'net'
import {
writeMsgStore,
readMsgStore
} from '../src/utils/messageStore'
// 启动一个TCP服务,接收hook消息
const server = net.createServer((socket: any) => {
console.log('New client connected')
let messageStore = readMsgStore()
let data = Buffer.from('')
socket.on('data', (data: any, chunk: any) => {
console.log(`Received data: ${data}`)
const dataJson = JSON.parse(data)
messageStore = writeMsgStore(messageStore, dataJson)
// data = Buffer.concat([data, chunk])
// console.log(`Received data: ${data}`)
})
socket.on('end', () => {
const decodedData = data.toString('utf8')
console.log(`Received data: ${decodedData}`)
})
socket.on('close', () => {
console.log('Client disconnected')
})
})
const wsPort = 19099
const main = async () => {
// server.listen(wsPort, () => {
// console.log(`Server listening on port ${wsPort}`)
// })
const testContact0 = 'filehelper'
const testContact1 = 'ledongmao'
const testRoom = '1234@chatroom'
const testRoom1 = '5678@chatroom'
const checkLoginRes = await wxhelper.checkLogin()
console.log('登录状态:', checkLoginRes.data)
if (checkLoginRes.data.msg !== 'success') {
console.log('请先登录')
return
} else {
const port = String(wsPort)
const ip = '127.0.0.1'
const url = ''
const timeout = '3000'
const enableHttp = '0'
const hookSyncMsgRes = await wxhelper.hookSyncMsg(port, ip, url, timeout, enableHttp)
console.log('开启hook:', hookSyncMsgRes.data)
}
const userInfoRes = await wxhelper.userInfo()
console.log('当前账号信息:', userInfoRes.data)
const selfWxid = userInfoRes.data.data.wxid
console.log('当前账号wxid:', selfWxid)
// const sendTextMsgRes = await wxhelper.sendTextMsg('filehelper', new Date().toLocaleString() + ':你好,我是机器人')
// console.log('发送文本消息:', sendTextMsgRes.data)
// const getContactListRes = await wxhelper.getContactList()
// console.log('获取联系人列表:', getContactListRes.data.data.length)
// const getDBInfo = await wxhelper.getDBInfo()
// console.log('获取数据库信息:', getDBInfo.data)
// const sqliteDB = await wxhelper.execSql(2737761293968, 'select * from MSG where localId =301;')
// console.log('查询数据库:', sqliteDB.data)
// const roomInfoRes = await wxhelper.getChatRoomDetailInfo(testRoom1)
// console.log('获取群聊详情:', roomInfoRes.data)
// const addMemberToChatRoomRes = await wxhelper.addMemberToChatRoom(testRoom, testContact1)
// console.log('添加群成员:', addMemberToChatRoomRes.data)
// const modifyChatRoomNameRes = await wxhelper.modifyNickname(testRoom, selfWxid, '大师')
// console.log('修改自己的群名片:', modifyChatRoomNameRes.data)
// const delMemberFromChatRoomRes = await wxhelper.delMemberFromChatRoom(testRoom, testContact1)
// console.log('删除群成员:', delMemberFromChatRoomRes.data)
// const getChatRoomMembersRes = await wxhelper.getMemberFromChatRoom(testRoom)
// console.log('获取群成员:', getChatRoomMembersRes.data)
// const quitChatRoomRes = await wxhelper.quitChatRoom(testRoom1)
// console.log('退出群聊:', quitChatRoomRes.data)
// const getSNSFirstPage = await wxhelper.getSNSFirstPage()
// console.log('获取朋友圈:', getSNSFirstPage.data)
// const getSNSNextPage = await wxhelper.getSNSNextPage()
// console.log('获取朋友圈下一页:', getSNSNextPage.data)
// const sendAtTextMsgRes = await wxhelper.sendAtText(testContact1, testRoom, '你好,我是机器人')
// console.log('发送@消息:', sendAtTextMsgRes.data)
// const getContactProfileRes = await wxhelper.getContactProfile(testContact1)
// console.log('获取联系人详情:', getContactProfileRes.data)
// const param = {
// appName: '123',
// userName: '超哥',
// title: '测试转发公众号消息',
// url: 'https://mp.weixin.qq.com/s?__biz=MzIwMzYwMTk1NA==&mid=2247483663&idx=1&sn=',
// thumbUrl: 'https://mmbiz.qpic.cn/mmbiz_jpg/3ic3Zz3',
// digest: '测试',
// wxid: testContact1,
// }
// const forwardPublicMsgRes = await wxhelper.forwardPublicMsg(param)
// console.log('转发公众号消息:', forwardPublicMsgRes.data)
// const payload = {
// "wxid": testContact1,
// "waidConcat": "wxaf35009675aa0b2a_118",
// "waid": "wxaf35009675aa0b2a",
// "appletWxid": "gh_7a5c4141778f@app",
// "jsonParam": "{\"current_path\":\"home/pages/index.html\",\"current_title\":\"\",\"image_url\":\"https://ut-static.udache.com/webx/mini-pics/U7mDFxU2yh-2-r1BJ-J0X.png\",\"scene\":1001,\"scene_note\":\"\",\"sessionId\":\"SessionId@1672284921_1#1692848476899\"}",
// "headImgUrl": "http://mmbiz.qpic.cn/sz_mmbiz_png/9n47wQlh4dH8afD9dQ9uQicibRm5mYz3lawXCLMjmnzFicribH51qsFYxjzPEcTGHGmgX4lkAkQ3jznia8UDEtqsX1w/640?wx_fmt=png&wxfrom=200",
// "mainImg": "C:\\wxid_123123\\Applet\\wxaf35009675aa0b2a\\temp\\2.png",
// "indexPage": "pages/index/index.html"
// }
// const sendAppMsgRes = await wxhelper.sendApplet(payload)
// console.log('发送小程序消息:', sendAppMsgRes.data)
// const sendPatMsgRes = await wxhelper.sendPatMsg(testRoom1, testContact1)
// console.log('拍一拍:', sendPatMsgRes.data)
// const ocrRes = await wxhelper.ocr('https://ut-static.udache.com/webx/mini-pics/U7mDFxU2yh-2-r1BJ-J0X.png')
// console.log('OCR识别:', ocrRes.data)
}
void main()
+307
View File
@@ -0,0 +1,307 @@
{
"name": "nodejs_client_ts",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "nodejs_client_ts",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"axios": "^1.6.8"
},
"devDependencies": {
"ts-node": "^10.9.2",
"typescript": "^5.4.3"
}
},
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@tsconfig/node10": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
"integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
"dev": true
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"dev": true
},
"node_modules/@types/node": {
"version": "20.11.30",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz",
"integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==",
"dev": true,
"peer": true,
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/acorn": {
"version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/acorn-walk": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz",
"integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==",
"dev": true,
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "1.6.8",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
"integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"bin": {
"ts-node": "dist/bin.js",
"ts-node-cwd": "dist/bin-cwd.js",
"ts-node-esm": "dist/bin-esm.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js",
"ts-script": "dist/bin-script-deprecated.js"
},
"peerDependencies": {
"@swc/core": ">=1.2.50",
"@swc/wasm": ">=1.2.50",
"@types/node": "*",
"typescript": ">=2.7"
},
"peerDependenciesMeta": {
"@swc/core": {
"optional": true
},
"@swc/wasm": {
"optional": true
}
}
},
"node_modules/typescript": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz",
"integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true,
"peer": true
},
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
"engines": {
"node": ">=6"
}
}
}
}
+22
View File
@@ -0,0 +1,22 @@
{
"name": "nodejs_client_ts",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "ts-node ./example/ding-dong-bot.ts",
"ws-server": "ts-node ./src/tcp_server.ts",
"build": "tsc",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"ts-node": "^10.9.2",
"typescript": "^5.4.3"
},
"dependencies": {
"axios": "^1.6.8"
}
}
+617
View File
@@ -0,0 +1,617 @@
import { get, post } from './utils/mod'
// def checkLogin():
// url = "127.0.0.1:19088/api/checkLogin"
// payload = {}
// headers = {}
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const checkLogin = () => {
return post('/api/checkLogin')
}
// def userInfo():
// url = "127.0.0.1:19088/api/userInfo"
// payload = {}
// headers = {}
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const userInfo = () => {
return post('/api/userInfo')
}
// def sendTextMsg():
// url = "127.0.0.1:19088/api/sendTextMsg"
// payload = json.dumps({
// "wxid": "filehelper",
// "msg": "12www"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const sendTextMsg = (wxid: string, msg: string) => {
return post('/api/sendTextMsg', { wxid, msg })
}
// def sendImagesMsg():
// url = "127.0.0.1:19088/api/sendImagesMsg"
// print("modify imagePath")
// raise RuntimeError("modify imagePath then deleted me")
// payload = json.dumps({
// "wxid": "filehelper",
// "imagePath": "C:\\pic.png"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const sendImagesMsg = (wxid: string, imagePath: string) => {
return post('/api/sendImagesMsg', { wxid, imagePath })
}
// def sendFileMsg():
// url = "127.0.0.1:19088/api/sendFileMsg"
// print("modify filePath")
// raise RuntimeError("modify filePath then deleted me")
// payload = json.dumps({
// "wxid": "filehelper",
// "filePath": "C:\\test.zip"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const sendFileMsg = (wxid: string, filePath: string) => {
return post('/api/sendFileMsg', { wxid, filePath })
}
// def hookSyncMsg():
// url = "127.0.0.1:19088/api/hookSyncMsg"
// print("modify ip port url ")
// raise RuntimeError("modify ip port url then deleted me")
// payload = json.dumps({
// "port": "19099",
// "ip": "127.0.0.1",
// "url": "http://localhost:8080",
// "timeout": "3000",
// "enableHttp": "0"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const hookSyncMsg = (port: string, ip: string, url: string, timeout: string, enableHttp: string) => {
return post('/api/hookSyncMsg', { port, ip, url, timeout, enableHttp })
}
// def unhookSyncMsg():
// url = host + "/api/unhookSyncMsg"
// payload = {}
// headers = {}
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const unhookSyncMsg = () => {
return post('/api/unhookSyncMsg')
}
// def getContactList():
// url = host + "/api/getContactList"
// payload = {}
// headers = {}
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const getContactList = () => {
return post('/api/getContactList')
}
// def getDBInfo():
// url = host + "/api/getDBInfo"
// payload = {}
// headers = {}
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const getDBInfo = () => {
return post('/api/getDBInfo')
}
// def execSql():
// url = host + "/api/execSql"
// print("modify dbHandle ")
// raise RuntimeError("modify dbHandle then deleted me")
// payload = json.dumps({
// "dbHandle": 1713425147584,
// "sql": "select * from MSG where localId =100;"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const execSql = (dbHandle: number, sql: string) => {
return post('/api/execSql', { dbHandle, sql })
}
// def getChatRoomDetailInfo():
// url = host + "/api/getChatRoomDetailInfo"
// print("modify chatRoomId ")
// raise RuntimeError("modify chatRoomId then deleted me")
// payload = json.dumps({
// "chatRoomId": "123333@chatroom"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const getChatRoomDetailInfo = (chatRoomId: string) => {
return post('/api/getChatRoomDetailInfo', { chatRoomId })
}
// def addMemberToChatRoom():
// url = host + "/api/addMemberToChatRoom"
// print("modify chatRoomId memberIds ")
// raise RuntimeError("modify chatRoomId memberIds then deleted me")
// payload = json.dumps({
// "chatRoomId": "123@chatroom",
// "memberIds": "wxid_123"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const addMemberToChatRoom = (chatRoomId: string, memberIds: string) => {
return post('/api/addMemberToChatRoom', { chatRoomId, memberIds })
}
// def delMemberFromChatRoom():
// url = host + "/api/delMemberFromChatRoom"
// print("modify chatRoomId memberIds ")
// raise RuntimeError("modify chatRoomId memberIds then deleted me")
// payload = json.dumps({
// "chatRoomId": "21363231004@chatroom",
// "memberIds": "wxid_123"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const delMemberFromChatRoom = (chatRoomId: string, memberIds: string) => {
return post('/api/delMemberFromChatRoom', { chatRoomId, memberIds })
}
// def modifyNickname():
// url = host + "/api/modifyNickname"
// print("modify chatRoomId wxid nickName")
// raise RuntimeError("modify chatRoomId wxid nickName then deleted me")
// payload = json.dumps({
// "chatRoomId": "123@chatroom",
// "wxid": "wxid_123",
// "nickName": "test"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const modifyNickname = (chatRoomId: string, wxid: string, nickName: string) => {
return post('/api/modifyNickname', { chatRoomId, wxid, nickName })
}
// def getMemberFromChatRoom():
// print("modify chatRoomId ")
// raise RuntimeError("modify chatRoomId then deleted me")
// url = host + "/api/getMemberFromChatRoom"
// payload = json.dumps({
// "chatRoomId": "123@chatroom"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const getMemberFromChatRoom = (chatRoomId: string) => {
return post('/api/getMemberFromChatRoom', { chatRoomId })
}
// def topMsg():
// print("modify msgId ")
// raise RuntimeError("modify msgId then deleted me")
// url = host + "/api/topMsg"
// payload = json.dumps({
// "msgId": 1222222
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const topMsg = (msgId: number) => {
return post('/api/topMsg', { msgId })
}
// def removeTopMsg():
// print("modify msgId chatRoomId ")
// raise RuntimeError("modify msgId chatRoomId then deleted me")
// url = host + "/api/removeTopMsg"
// payload = json.dumps({
// "chatRoomId": "123@chatroom",
// "msgId": 123
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const removeTopMsg = (chatRoomId: string, msgId: number) => {
return post('/api/removeTopMsg', { chatRoomId, msgId })
}
// def InviteMemberToChatRoom():
// print("modify memberIds chatRoomId ")
// raise RuntimeError("modify memberIds chatRoomId then deleted me")
// url = host + "/api/InviteMemberToChatRoom"
// payload = json.dumps({
// "chatRoomId": "123@chatroom",
// "memberIds": "wxid_123"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const InviteMemberToChatRoom = (chatRoomId: string, memberIds: string) => {
return post('/api/InviteMemberToChatRoom', { chatRoomId, memberIds })
}
// def hookLog():
// url = host + "/api/hookLog"
// payload = {}
// headers = {}
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const hookLog = () => {
return post('/api/hookLog')
}
// def unhookLog():
// url = host + "/api/unhookLog"
// payload = {}
// headers = {}
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const unhookLog = () => {
return post('/api/unhookLog')
}
// def createChatRoom():
// print("modify memberIds ")
// raise RuntimeError("modify memberIds then deleted me")
// url = host + "/api/createChatRoom"
// payload = json.dumps({
// "memberIds": "wxid_8yn4k908tdqp22,wxid_oyb662qhop4422"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const createChatRoom = (memberIds: string) => {
return post('/api/createChatRoom', { memberIds })
}
// def quitChatRoom():
// print("modify chatRoomId ")
// raise RuntimeError("modify chatRoomId then deleted me")
// url = host + "/api/quitChatRoom"
// payload = json.dumps({
// "chatRoomId": "123@chatroom"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const quitChatRoom = (chatRoomId: string) => {
return post('/api/quitChatRoom', { chatRoomId })
}
// def forwardMsg():
// print("modify msgId ")
// raise RuntimeError("modify msgId then deleted me")
// url = host + "/api/forwardMsg"
// payload = json.dumps({
// "wxid": "filehelper",
// "msgId": "12331"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const forwardMsg = (wxid: string, msgId: string) => {
return post('/api/forwardMsg', { wxid, msgId })
}
// def getSNSFirstPage():
// url = host + "/api/getSNSFirstPage"
// payload = {}
// headers = {}
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const getSNSFirstPage = () => {
return post('/api/getSNSFirstPage')
}
// def getSNSNextPage():
// print("modify snsId ")
// raise RuntimeError("modify snsId then deleted me")
// url = host + "/api/getSNSNextPage"
// payload = json.dumps({
// "snsId": ""
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const getSNSNextPage = (snsId: string) => {
return post('/api/getSNSNextPage', { snsId })
}
// def addFavFromMsg():
// print("modify msgId ")
// raise RuntimeError("modify msgId then deleted me")
// url = host + "/api/addFavFromMsg"
// payload = json.dumps({
// "msgId": "1222222"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const addFavFromMsg = (msgId: string) => {
return post('/api/addFavFromMsg', { msgId })
}
// def addFavFromImage():
// print("modify wxid imagePath ")
// raise RuntimeError("modify wxid imagePath then deleted me")
// url = host + "/api/addFavFromImage"
// payload = json.dumps({
// "wxid": "",
// "imagePath": ""
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const addFavFromImage = (wxid: string, imagePath: string) => {
return post('/api/addFavFromImage', { wxid, imagePath })
}
// def getContactProfile():
// print("modify wxid ")
// raise RuntimeError("modify wxid then deleted me")
// url = host + "/api/getContactProfile"
// payload = json.dumps({
// "wxid": ""
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const getContactProfile = (wxid: string) => {
return post('/api/getContactProfile', { wxid })
}
// def sendAtText():
// print("modify wxids chatRoomId")
// raise RuntimeError("modify wxids chatRoomId then deleted me")
// url = host + "/api/sendAtText"
// payload = json.dumps({
// "wxids": "notify@all",
// "chatRoomId": "123@chatroom",
// "msg": "你好啊"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const sendAtText = (wxids: string, chatRoomId: string, msg: string) => {
return post('/api/sendAtText', { wxids, chatRoomId, msg })
}
// def forwardPublicMsg():
// print("modify param ")
// raise RuntimeError("modify param then deleted me")
// url = host + "/api/forwardPublicMsg"
// payload = json.dumps({
// "appName": "",
// "userName": "",
// "title": "",
// "url": "",
// "thumbUrl": "",
// "digest": "",
// "wxid": "filehelper"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const forwardPublicMsg = (param: {
appName: string;
userName: string;
title: string;
url: string;
thumbUrl: string;
digest: string;
wxid: string
}) => {
return post('/api/forwardPublicMsg', param)
}
// def forwardPublicMsgByMsgId():
// print("modify param ")
// raise RuntimeError("modify param then deleted me")
// url = host + "/api/forwardPublicMsgByMsgId"
// payload = json.dumps({
// "msgId": 123,
// "wxid": "filehelper"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const forwardPublicMsgByMsgId = (msgId: number, wxid: string) => {
return post('/api/forwardPublicMsgByMsgId', { msgId, wxid })
}
// def downloadAttach():
// print("modify param ")
// raise RuntimeError("modify param then deleted me")
// url = host + "/api/downloadAttach"
// payload = json.dumps({
// "msgId": 123
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const downloadAttach = (msgId: number) => {
return post('/api/downloadAttach', { msgId })
}
// def decodeImage():
// print("modify param ")
// raise RuntimeError("modify param then deleted me")
// url = host + "/api/decodeImage"
// payload = json.dumps({
// "filePath": "C:\\66664816980131.dat",
// "storeDir": "C:\\test"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const decodeImage = (filePath: string, storeDir: string) => {
return post('/api/decodeImage', { filePath, storeDir })
}
// def getVoiceByMsgId():
// print("modify param ")
// raise RuntimeError("modify param then deleted me")
// url = host + "/api/getVoiceByMsgId"
// payload = json.dumps({
// "msgId": 7880439644200,
// "storeDir": "c:\\test"
// })
// headers = {
// 'Content-Type': 'application/json'
// }
// response = requests.request("POST", url, headers=headers, data=payload)
// print(response.text)
export const getVoiceByMsgId = (msgId: number, storeDir: string) => {
return post('/api/getVoiceByMsgId', { msgId, storeDir })
}
// /api/sendApplet
export const sendApplet = (param: {
wxid: string
waidConcat: string
appletWxid: string
jsonParam: string
headImgUrl: string
mainImg: string
indexPage: string
}) => {
return post('/api/sendApplet', param)
}
// /api/sendPatMsg
export const sendPatMsg = (receiver: string,
wxid: string) => {
return post('/api/sendPatMsg', { wxid, receiver })
}
// /api/ocr
export const ocr = (
imagePath: string
) => {
return post('/api/ocr', { imagePath })
}
+33
View File
@@ -0,0 +1,33 @@
import net from 'net'
import {
readMsgStore,
writeMsgStore,
} from './utils/messageStore'
export const server = net.createServer((socket:any) => {
console.log('New client connected')
let messageStore = readMsgStore()
let data = Buffer.from('')
socket.on('data', (data:any, chunk:any) => {
console.log(`Received data: ${data}`)
const dataJson = JSON.parse(data)
messageStore = writeMsgStore(messageStore, dataJson)
// data = Buffer.concat([data, chunk])
// console.log(`Received data: ${data}`)
})
socket.on('end', () => {
const decodedData = data.toString('utf8')
console.log(`Received data: ${decodedData}`)
})
socket.on('close', () => {
console.log('Client disconnected')
})
})
const port = 19099
server.listen(port, () => {
console.log(`Server listening on port ${port}`)
})
@@ -0,0 +1,50 @@
import fs from 'fs'
export const writeMsgStore = (messageStore: { [key: string]: any }, msg: { type: number, content?:any }) => {
// 检测根目录下是否有msgStore.json文件,如果没有,则创建一个,内容为{}
if (!fs.existsSync('msgStore.json')) {
console.log('msgStore.json not exist')
fs.writeFileSync('msgStore.json', '{}')
}
let type = String(msg.type)
console.info('ws message hook:', type)
// log.info(JSON.stringify(j, undefined, 2))
if (msg.content) {
try {
const content = msg.content
// 从content中判断是否存在类似<type>6</type>的格式,并从其中取出type的值
const m = content.match(/<type>(\d+)<\/type>/)
if (m != null) {
type = type + '_' + m[1]
}
} catch (e) {
console.error('ws message hook error:', e)
}
}
if (type === '10000') {
const list10000 = messageStore['10000'] || []
list10000.push(msg)
messageStore[type] = list10000
} else {
messageStore[type] = msg
}
// 将that.messageTypeTest保存到文件'/msgStore.json'
fs.writeFileSync('msgStore.json', JSON.stringify(messageStore, undefined, 2))
return messageStore
}
export const readMsgStore = () => {
// 读取'/msgStore.json'文件
// 检测根目录下是否有msgStore.json文件,如果没有,则创建一个,内容为{}
if (!fs.existsSync('msgStore.json')) {
console.log('msgStore.json not exist')
fs.writeFileSync('msgStore.json', '{}')
return {}
}
const data = fs.readFileSync('msgStore.json', 'utf8')
const json = JSON.parse(data)
return json
}
+63
View File
@@ -0,0 +1,63 @@
// 封装get和post请求
import axios from 'axios'
// 创建 axios 实例
const request = axios.create({
// API 请求的默认前缀
baseURL: 'http://127.0.0.1:19088',
// 请求超时时间
timeout: 120000,
})
/**
* 异常拦截处理器
*
* @param {*} error
*/
const errorHandler = (error: { response?: { status: number, config: any } }) => {
// 判断是否是响应错误信息
if (error.response) {
if (error.response.status === 401) {
return request(error.response.config)
}
}
return Promise.reject(error)
}
/**
* GET 请求
*
* @param {String} url
* @param {Object} data
* @param {Object} options
* @returns {Promise<any>}
*/
export const get = (url: string, data = {}, options = {}) => {
// request.interceptors.response.use((response) => response.data, errorHandler)
return request({
url,
params: data,
method: 'get',
...options,
})
}
/**
* POST 请求
*
* @param {String} url
* @param {Object} data
* @param {Object} options
* @returns {Promise<any>}
*/
export const post = (url: string, data = {}, options = {}) => {
// request.interceptors.response.use((response) => response.data, errorHandler)
return request({
url,
method: 'post',
data,
...options,
})
}
+14
View File
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"outDir": "./dist",
"rootDir": "./",
"esModuleInterop": true
},
"include": [
"./src",
"./example/ding-dong-bot.ts"
]
}
+495
View File
@@ -0,0 +1,495 @@
import requests
import json
host = "http://127.0.0.1:19088"
def checkLogin():
url = host + "/api/checkLogin"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def userInfo():
url = host + "/api/userInfo"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def sendTextMsg():
url = host + "/api/sendTextMsg"
payload = json.dumps({
"wxid": "filehelper",
"msg": "12www"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def sendImagesMsg():
url = host + "/api/sendImagesMsg"
print("modify imagePath")
raise RuntimeError("modify imagePath then deleted me")
payload = json.dumps({
"wxid": "filehelper",
"imagePath": "C:\\pic.png"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def sendFileMsg():
url = host + "/api/sendFileMsg"
print("modify filePath")
raise RuntimeError("modify filePath then deleted me")
payload = json.dumps({
"wxid": "filehelper",
"filePath": "C:\\test.zip"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def hookSyncMsg():
url = host + "/api/hookSyncMsg"
print("modify ip port url ")
raise RuntimeError("modify ip port url then deleted me")
payload = json.dumps({
"port": "19099",
"ip": "127.0.0.1",
"url": "http://localhost:8080",
"timeout": "3000",
"enableHttp": "0"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def unhookSyncMsg():
url = host + "/api/unhookSyncMsg"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getContactList():
url = host + "/api/getContactList"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getDBInfo():
url = host + "/api/getDBInfo"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def execSql():
url = host + "/api/execSql"
print("modify dbHandle ")
raise RuntimeError("modify dbHandle then deleted me")
payload = json.dumps({
"dbHandle": 1713425147584,
"sql": "select * from MSG where localId =100;"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getChatRoomDetailInfo():
url = host + "/api/getChatRoomDetailInfo"
print("modify chatRoomId ")
raise RuntimeError("modify chatRoomId then deleted me")
payload = json.dumps({
"chatRoomId": "123333@chatroom"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def addMemberToChatRoom():
url = host + "/api/addMemberToChatRoom"
print("modify chatRoomId memberIds ")
raise RuntimeError("modify chatRoomId memberIds then deleted me")
payload = json.dumps({
"chatRoomId": "123@chatroom",
"memberIds": "wxid_123"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def delMemberFromChatRoom():
url = host + "/api/delMemberFromChatRoom"
print("modify chatRoomId memberIds ")
raise RuntimeError("modify chatRoomId memberIds then deleted me")
payload = json.dumps({
"chatRoomId": "21363231004@chatroom",
"memberIds": "wxid_123"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def modifyNickname():
url = host + "/api/modifyNickname"
print("modify chatRoomId wxid nickName")
raise RuntimeError("modify chatRoomId wxid nickName then deleted me")
payload = json.dumps({
"chatRoomId": "123@chatroom",
"wxid": "wxid_123",
"nickName": "test"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getMemberFromChatRoom():
print("modify chatRoomId ")
raise RuntimeError("modify chatRoomId then deleted me")
url = host + "/api/getMemberFromChatRoom"
payload = json.dumps({
"chatRoomId": "123@chatroom"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def topMsg():
print("modify msgId ")
raise RuntimeError("modify msgId then deleted me")
url = host + "/api/topMsg"
payload = json.dumps({
"msgId": 1222222
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def removeTopMsg():
print("modify msgId chatRoomId ")
raise RuntimeError("modify msgId chatRoomId then deleted me")
url = host + "/api/removeTopMsg"
payload = json.dumps({
"chatRoomId": "123@chatroom",
"msgId": 123
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def InviteMemberToChatRoom():
print("modify memberIds chatRoomId ")
raise RuntimeError("modify memberIds chatRoomId then deleted me")
url = host + "/api/InviteMemberToChatRoom"
payload = json.dumps({
"chatRoomId": "123@chatroom",
"memberIds": "wxid_123"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def hookLog():
url = host + "/api/hookLog"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def unhookLog():
url = host + "/api/unhookLog"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def createChatRoom():
print("modify memberIds ")
raise RuntimeError("modify memberIds then deleted me")
url = host + "/api/createChatRoom"
payload = json.dumps({
"memberIds": "wxid_8yn4k908tdqp22,wxid_oyb662qhop4422"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def quitChatRoom():
print("modify chatRoomId ")
raise RuntimeError("modify chatRoomId then deleted me")
url = host + "/api/quitChatRoom"
payload = json.dumps({
"chatRoomId": "123@chatroom"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def forwardMsg():
print("modify msgId ")
raise RuntimeError("modify msgId then deleted me")
url = host + "/api/forwardMsg"
payload = json.dumps({
"wxid": "filehelper",
"msgId": "12331"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getSNSFirstPage():
url = host + "/api/getSNSFirstPage"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getSNSNextPage():
print("modify snsId ")
raise RuntimeError("modify snsId then deleted me")
url = host + "/api/getSNSNextPage"
payload = json.dumps({
"snsId": ""
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def addFavFromMsg():
print("modify msgId ")
raise RuntimeError("modify msgId then deleted me")
url = host + "/api/addFavFromMsg"
payload = json.dumps({
"msgId": "1222222"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def addFavFromImage():
print("modify wxid imagePath ")
raise RuntimeError("modify wxid imagePath then deleted me")
url = host + "/api/addFavFromImage"
payload = json.dumps({
"wxid": "",
"imagePath": ""
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getContactProfile():
print("modify wxid ")
raise RuntimeError("modify wxid then deleted me")
url = host + "/api/getContactProfile"
payload = json.dumps({
"wxid": ""
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def sendAtText():
print("modify wxids chatRoomId")
raise RuntimeError("modify wxids chatRoomId then deleted me")
url = host + "/api/sendAtText"
payload = json.dumps({
"wxids": "notify@all",
"chatRoomId": "123@chatroom",
"msg": "你好啊"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def forwardPublicMsg():
print("modify param ")
raise RuntimeError("modify param then deleted me")
url = host + "/api/forwardPublicMsg"
payload = json.dumps({
"appName": "",
"userName": "",
"title": "",
"url": "",
"thumbUrl": "",
"digest": "",
"wxid": "filehelper"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def forwardPublicMsgByMsgId():
print("modify param ")
raise RuntimeError("modify param then deleted me")
url = host + "/api/forwardPublicMsgByMsgId"
payload = json.dumps({
"msgId": 123,
"wxid": "filehelper"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def downloadAttach():
print("modify param ")
raise RuntimeError("modify param then deleted me")
url = host + "/api/downloadAttach"
payload = json.dumps({
"msgId": 123
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def decodeImage():
print("modify param ")
raise RuntimeError("modify param then deleted me")
url = host + "/api/decodeImage"
payload = json.dumps({
"filePath": "C:\\66664816980131.dat",
"storeDir": "C:\\test"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getVoiceByMsgId():
print("modify param ")
raise RuntimeError("modify param then deleted me")
url = host + "/api/getVoiceByMsgId"
payload = json.dumps({
"msgId": 7880439644200,
"storeDir": "c:\\test"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
if __name__ == '__main__':
checkLogin()
userInfo()
sendTextMsg()
+54 -49
View File
@@ -1,13 +1,14 @@
import requests
import json
host = "http://127.0.0.1:19088"
def check_login():
"""
0.检查是否登录
:return:
"""
url = "127.0.0.1:19088/api/?type=0"
url = host + "/api/?type=0"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
@@ -19,22 +20,22 @@ def user_info():
登录用户信息
:return:
"""
url = "127.0.0.1:19088/api/?type=8"
url = host + "/api/?type=8"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def send_text():
def send_text(wxid, msg):
"""
发送文本
:return:
"""
url = "127.0.0.1:19088/api/?type=2"
url = host + "/api/?type=2"
payload = json.dumps({
"wxid": "filehelper",
"msg": "123"
"wxid": wxid,
"msg": msg
})
headers = {
'Content-Type': 'application/json'
@@ -43,16 +44,16 @@ def send_text():
print(response.text)
def send_at():
def send_at(chatRoomId, wxids, msg):
"""
发送@消息
:return:
"""
url = "127.0.0.1:19088/api/?type=3"
url = host + "/api/?type=3"
payload = json.dumps({
"chatRoomId": "12333@chatroom",
"wxids": "notify@all",
"msg": "12333"
"chatRoomId": chatRoomId,
"wxids": wxids, # "notify@all"
"msg": msg
})
headers = {
'Content-Type': 'application/json'
@@ -61,15 +62,19 @@ def send_at():
print(response.text)
def send_img():
def send_img(wxid, imgPath):
# {
# "wxid": "filehelper",
# "imagePath": "C:/123.png"
# }
"""
发送图片
:return:
"""
url = "127.0.0.1:19088/api/?type=5"
url = host + "/api/?type=5"
payload = json.dumps({
"wxid": "filehelper",
"imagePath": "C:/123.png"
"wxid": wxid,
"imagePath": imgPath
})
headers = {
'Content-Type': 'application/json'
@@ -83,7 +88,7 @@ def send_file():
发送文件
:return:
"""
url = "127.0.0.1:19088/api/?type=6"
url = host + "/api/?type=6"
payload = json.dumps({
"wxid": "filehelper",
"filePath": "C:/test.txt"
@@ -100,7 +105,7 @@ def hook_msg():
hook 消息
:return:
"""
url = "127.0.0.1:19088/api/?type=9"
url = host + "/api/?type=9"
payload = json.dumps({
"port": "19099",
"ip": "127.0.0.1"
@@ -117,7 +122,7 @@ def unhook_msg():
取消消息hook
:return:
"""
url = "127.0.0.1:19088/api/?type=10"
url = host + "/api/?type=10"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
@@ -129,7 +134,7 @@ def hook_img():
hook 图片
:return:
"""
url = "127.0.0.1:19088/api/?type=11"
url = host + "/api/?type=11"
payload = json.dumps({
"imgDir": "C:\\img"
})
@@ -145,7 +150,7 @@ def unhook_img():
取消hook 图片
:return:
"""
url = "127.0.0.1:19088/api/?type=12"
url = host + "/api/?type=12"
payload = json.dumps({
"imgDir": "C:\\img"
})
@@ -161,7 +166,7 @@ def hook_voice():
hook 语音
:return:
"""
url = "127.0.0.1:19088/api/?type=56"
url = host + "/api/?type=56"
payload = json.dumps({
"msgId": 322456091115784000
})
@@ -177,7 +182,7 @@ def unhook_voice():
取消hook 语音
:return:
"""
url = "127.0.0.1:19088/api/?type=14"
url = host + "/api/?type=14"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
@@ -189,7 +194,7 @@ def del_friend():
删除好友
:return:
"""
url = "127.0.0.1:19088/api/?type=17"
url = host + "/api/?type=17"
payload = json.dumps({
"wxid": "wxid_1124423322"
})
@@ -205,7 +210,7 @@ def search_friend():
网络搜素用户
:return:
"""
url = "127.0.0.1:19088/api/?type=19"
url = host + "/api/?type=19"
payload = json.dumps({
"keyword": "13812345678"
})
@@ -221,7 +226,7 @@ def add_friend():
添加好友
:return:
"""
url = "127.0.0.1:19088/api/?type=20"
url = host + "/api/?type=20"
payload = json.dumps({
"wxid": "wxid_o11222334422"
})
@@ -237,7 +242,7 @@ def fetch_chat_room_members():
群成员
:return:
"""
url = "127.0.0.1:19088/api/?type=25"
url = host + "/api/?type=25"
payload = json.dumps({
"chatRoomId": "2112222004@chatroom"
})
@@ -253,7 +258,7 @@ def get_member_nickname():
群成员昵称
:return:
"""
url = "127.0.0.1:19088/api/?type=26"
url = host + "/api/?type=26"
payload = json.dumps({
"chatRoomId": "322333384@chatroom",
"memberId": "wxid_4m1112222u22"
@@ -270,7 +275,7 @@ def del_member():
删除群成员
:return:
"""
url = "127.0.0.1:19088/api/?type=27"
url = host + "/api/?type=27"
payload = json.dumps({
"chatRoomId": "31122263384@chatroom",
"memberIds": "wxid_12223334422"
@@ -287,7 +292,7 @@ def add_member():
增加群成员
:return:
"""
url = "127.0.0.1:19088/api/?type=28"
url = host + "/api/?type=28"
payload = json.dumps({
"chatRoomId": "1111163384@chatroom",
"memberIds": "wxid_o12222222"
@@ -304,7 +309,7 @@ def modify_room_name():
修改群昵称
:return:
"""
url = "127.0.0.1:19088/api/?type=31"
url = host + "/api/?type=31"
payload = json.dumps({
"chatRoomId": "222285428@chatroom",
"wxid": "wxid_222222512",
@@ -322,7 +327,7 @@ def get_db_handlers():
获取sqlite3的操作句柄
:return:
"""
url = "127.0.0.1:19088/api/?type=32"
url = host + "/api/?type=32"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
@@ -334,7 +339,7 @@ def query_db_by_sql():
查询数据库
:return:
"""
url = "127.0.0.1:19088/api/?type=34"
url = host + "/api/?type=34"
payload = json.dumps({
"dbHandle": 116201928,
"sql": "select localId from MSG where MsgSvrID= 7533111101686156"
@@ -351,7 +356,7 @@ def hook_log():
hook 日志
:return:
"""
url = "127.0.0.1:19088/api/?type=36"
url = host + "/api/?type=36"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
@@ -363,7 +368,7 @@ def unhook_log():
取消hook日志
:return:
"""
url = "127.0.0.1:19088/api/?type=37"
url = host + "/api/?type=37"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
@@ -375,7 +380,7 @@ def forward():
转发消息
:return:
"""
url = "127.0.0.1:19088/api/?type=40"
url = host + "/api/?type=40"
payload = json.dumps({
"wxid": "filehelper",
"msgid": "705117679011122708"
@@ -392,7 +397,7 @@ def logout():
退出登录
:return:
"""
url = "127.0.0.1:19088/api/?type=44"
url = host + "/api/?type=44"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
@@ -404,7 +409,7 @@ def confirm_receipt():
确认收款
:return:
"""
url = "127.0.0.1:19088/api/?type=45"
url = host + "/api/?type=45"
payload = json.dumps({
"wxid": "wxid_1111112622",
"transcationId": "10000500012312222212243388865912",
@@ -422,7 +427,7 @@ def contact_list():
好友列表
:return:
"""
url = "127.0.0.1:19088/api/?type=46"
url = host + "/api/?type=46"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
@@ -434,7 +439,7 @@ def room_detail():
群详情
:return:
"""
url = "127.0.0.1:19088/api/?type=47"
url = host + "/api/?type=47"
payload = json.dumps({
"chatRoomId": "199134446111@chatroom"
})
@@ -450,7 +455,7 @@ def ocr():
ocr提取文字
:return:
"""
url = "127.0.0.1:19088/api/?type=49"
url = host + "/api/?type=49"
payload = json.dumps({
"imagePath": "C:\\WeChat Files\\b23e84997144dd12f21554b0.dat"
})
@@ -466,7 +471,7 @@ def pat():
拍一拍
:return:
"""
url = "127.0.0.1:19088/api/?type=50"
url = host + "/api/?type=50"
payload = json.dumps({
"chatRoomId": "211111121004@chatroom",
"wxid": "wxid_111111111422"
@@ -483,7 +488,7 @@ def top_msg():
消息置顶
:return:
"""
url = "127.0.0.1:19088/api/?type=51"
url = host + "/api/?type=51"
payload = json.dumps({
"wxid": "wxid_o11114422",
"msgid": 3728307145189195000
@@ -500,7 +505,7 @@ def close_top_msg():
取消置顶
:return:
"""
url = "127.0.0.1:19088/api/?type=52"
url = host + "/api/?type=52"
payload = json.dumps({
"chatRoomId": "213222231004@chatroom",
"msgid": 3728307145189195000
@@ -517,7 +522,7 @@ def sns_first():
朋友圈首页
:return:
"""
url = "127.0.0.1:19088/api/?type=53"
url = host + "/api/?type=53"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
@@ -529,7 +534,7 @@ def sns_next():
朋友圈下一页
:return:
"""
url = "127.0.0.1:19088/api/?type=54"
url = host + "/api/?type=54"
payload = json.dumps({
"snsId": "14091988153735844377"
})
@@ -545,7 +550,7 @@ def query_nickname():
查询联系人或群名称
:return:
"""
url = "127.0.0.1:19088/api/?type=55"
url = host + "/api/?type=55"
payload = json.dumps({
"id": "wxid_1112p4422"
@@ -562,7 +567,7 @@ def download_msg_attach():
下载消息附件
:return:
"""
url = "127.0.0.1:19088/api/?type=56"
url = host + "/api/?type=56"
payload = json.dumps({
"msgId": 6080100336053626000
})
@@ -578,7 +583,7 @@ def get_member_info():
获取群/群成员信息
:return:
"""
url = "127.0.0.1:19088/api/?type=57"
url = host + "/api/?type=57"
payload = json.dumps({
"wxid": "wxid_tx8k6tu21112"
})
@@ -592,4 +597,4 @@ def get_member_info():
if __name__ == '__main__':
check_login()
user_info()
send_text()
send_text("filehelper","123")
+13 -1
View File
@@ -933,7 +933,10 @@ int InjectDll(wchar_t* szPName, wchar_t* szDllPath)
result = 1;
}
else
{
{
DWORD dErrorCode = GetLastError();
printf("dll inject fail");
printf("error code : %d ", dErrorCode);
VirtualFreeEx(hProcess, lpRemoteDllBase, ulDllLength, MEM_DECOMMIT | MEM_RELEASE);
CloseHandle(hProcess);
result = 0;
@@ -941,6 +944,9 @@ int InjectDll(wchar_t* szPName, wchar_t* szDllPath)
}
else
{
DWORD dErrorCode = GetLastError();
printf("dll inject fail.VirtualAllocEx method fail.");
printf("error code : %d ", dErrorCode);
CloseHandle(hProcess);
result = 0;
}
@@ -986,6 +992,9 @@ int InjectDllByPid(unsigned int pid, wchar_t* szDllPath)
}
else
{
DWORD dErrorCode = GetLastError();
printf("dll inject fail");
printf("error code : %d ", dErrorCode);
VirtualFreeEx(hProcess, lpRemoteDllBase, ulDllLength, MEM_DECOMMIT | MEM_RELEASE);
CloseHandle(hProcess);
result = 0;
@@ -993,6 +1002,9 @@ int InjectDllByPid(unsigned int pid, wchar_t* szDllPath)
}
else
{
DWORD dErrorCode = GetLastError();
printf("dll inject fail.VirtualAllocEx method fail.");
printf("error code : %d ", dErrorCode);
CloseHandle(hProcess);
result = 0;
}
+2 -1
View File
@@ -344,6 +344,7 @@ std::vector<void *> DB::GetDbHandles() {
msg0_db.db_name = (wchar_t *)(*(UINT64 *)(db_addr));
msg0_db.db_name_len = *(DWORD *)(db_addr + 0x8);
msg0_db.handle = msg0_db_addr;
msg0_db.extrainfo = *(UINT64 *)(*(UINT64 *)(db_addr + 0x28) + 0x1E8);
ExecuteSQL(msg0_db_addr,
"select * from sqlite_master where type=\"table\";",
(UINT64)GetDbInfo, &msg0_db);
@@ -458,7 +459,7 @@ std::vector<std::string> DB::GetChatMsgByMsgId(ULONG64 msgid) {
wchar_t dbname[20] = {0};
for (int i = 0;; i++) {
swprintf_s(dbname, L"MSG%d.db", i);
DWORD handle = GetDbHandleByDbName(dbname);
UINT64 handle = GetDbHandleByDbName(dbname);
if (handle == 0) {
// LOG(INFO) << "MSG db handle is null";
return {};
+3 -1
View File
@@ -17,7 +17,9 @@ GlobalContext::~GlobalContext() {
void GlobalContext::initialize(HMODULE module) {
state =GlobalContextState::INITIALIZING;
module_ = module;
// Utils::Hide(module);
#ifndef _DEBUG
Utils::Hide(module);
#endif
UINT64 base = Utils::GetWeChatWinBase();
config.emplace();
config->Initialize();
-7
View File
@@ -24,13 +24,6 @@ class GlobalContext : public Singleton<GlobalContext> {
std::unique_ptr<HttpServer> http_server;
std::unique_ptr<Manager> mgr;
// std::optional<ContactMgr> contact_mgr;
// std::optional<MiscMgr> misc_mgr;
// std::optional<SendMessageMgr> send_mgr;
// std::optional<AccountMgr> account_mgr;
// std::optional<ChatRoomMgr> chat_room_mgr;
// std::optional<SNSMgr> sns_mgr;
GlobalContextState state = GlobalContextState::NOT_INITIALIZED;
private:
+123 -7
View File
@@ -16,12 +16,25 @@ static int kServerPort = 19099;
static bool kMsgHookFlag = false;
static char kServerIp[16] = "127.0.0.1";
static bool kEnableHttp = false;
static bool kLogHookFlag = false;
static bool kSnsFinishHookFlag = false;
static UINT64 (*R_DoAddMsg)(UINT64, UINT64, UINT64) = (UINT64(*)(
UINT64, UINT64, UINT64))(Utils::GetWeChatWinBase() + offset::kDoAddMsg);
static UINT64 (*R_Log)(UINT64, UINT64, UINT64, UINT64, UINT64, UINT64, UINT64,
UINT64, UINT64, UINT64, UINT64, UINT64) =
(UINT64(*)(UINT64, UINT64, UINT64, UINT64, UINT64, UINT64, UINT64, UINT64,
UINT64, UINT64, UINT64,
UINT64))(Utils::GetWeChatWinBase() + offset::kHookLog);
static UINT64 (*R_OnSnsTimeLineSceneFinish)(UINT64, UINT64, UINT64) =
(UINT64(*)(UINT64, UINT64, UINT64))(Utils::GetWeChatWinBase() +
offset::kOnSnsTimeLineSceneFinish);
VOID CALLBACK SendMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
PTP_WORK Work) {
common::InnerMessageStruct *msg = (common::InnerMessageStruct *)context;
@@ -65,7 +78,7 @@ VOID CALLBACK SendMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
goto clean;
}
char recv_buf[1024] = {0};
ret = send(client_socket, jstr.c_str(), jstr.size(), 0);
ret = send(client_socket, jstr.c_str(), static_cast<int>(jstr.size()) , 0);
if (ret < 0) {
SPDLOG_ERROR("socket send fail ,ret:{}", ret);
goto clean;
@@ -112,9 +125,10 @@ void HandleSyncMsg(INT64 param1, INT64 param2, INT64 param3) {
msg["toUser"] = Utils::ReadSKBuiltinString(*(INT64 *)(param2 + 0x28));
msg["content"] = Utils::ReadSKBuiltinString(*(INT64 *)(param2 + 0x30));
msg["signature"] = Utils::ReadWeChatStr(*(INT64 *)(param2 + 0x48));
msg["msgId"] = *(INT64 *)(param2 + 0x58);
msg["msgSequence"] = *(DWORD *)(param2 + 0x20);
msg["fromUserName"] = Utils::ReadWeChatStr(*(INT64 *)(param2 + 0x50));
msg["msgId"] = *(INT64 *)(param2 + 0x60);
msg["msgSequence"] = *(DWORD *)(param2 + 0x5C);
msg["createTime"] = *(DWORD *)(param2 + 0x58);
msg["displayFullContent"] = Utils::ReadWeChatStr(*(INT64 *)(param2 + 0x50));
DWORD type = *(DWORD *)(param2 + 0x24);
msg["type"] = type;
if (type == 3) {
@@ -140,6 +154,59 @@ void HandleSyncMsg(INT64 param1, INT64 param2, INT64 param3) {
R_DoAddMsg(param1,param2,param3);
}
UINT64 HandlePrintLog(UINT64 param1, UINT64 param2, UINT64 param3, UINT64 param4,
UINT64 param5, UINT64 param6, UINT64 param7, UINT64 param8,
UINT64 param9, UINT64 param10, UINT64 param11,
UINT64 param12) {
UINT64 p = R_Log(param1, param2, param3, param4, param5, param6, param7, param8, param9,
param10, param11, param12);
if(p== 0 || p == 1){
return p;
}
char *msg = (char *)p;
if (msg != NULL) {
// INT64 size = *(INT64 *)(p - 0x8);
std::string str(msg);
std::wstring ws = Utils::UTF8ToWstring(str);
std::string out = Utils::WstringToAnsi(ws, CP_ACP);
spdlog::info("wechat log:{}", out);
}
return p;
}
void HandleSNSMsg(INT64 param1, INT64 param2, INT64 param3) {
nlohmann::json j_sns;
INT64 begin_addr = *(INT64 *)(param2 + 0x30);
INT64 end_addr = *(INT64 *)(param2 + 0x38);
if (begin_addr == 0) {
j_sns = {{"data", nlohmann::json::array()}};
} else {
while (begin_addr < end_addr) {
nlohmann::json j_item;
j_item["snsId"] = *(UINT64 *)(begin_addr);
j_item["createTime"] = *(DWORD *)(begin_addr + 0x38);
j_item["senderId"] = Utils::ReadWstringThenConvert(begin_addr + 0x18);
j_item["content"] = Utils::ReadWstringThenConvert(begin_addr + 0x48);
j_item["xml"] = Utils::ReadWstringThenConvert(begin_addr + 0x580);
j_sns["data"].push_back(j_item);
begin_addr += 0x11E0;
}
}
std::string jstr = j_sns.dump() + '\n';
common::InnerMessageStruct *inner_msg = new common::InnerMessageStruct;
inner_msg->buffer = new char[jstr.size() + 1];
memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1);
inner_msg->length = jstr.size();
if (kEnableHttp) {
bool add = ThreadPool::GetInstance().AddWork(SendHttpMsgCallback, inner_msg);
SPDLOG_INFO("hook sns add http msg work:{}", add);
} else {
bool add = ThreadPool::GetInstance().AddWork(SendMsgCallback, inner_msg);
SPDLOG_INFO("hook sns add msg work:{}", add);
}
R_OnSnsTimeLineSceneFinish(param1, param2, param3);
}
int HookSyncMsg(std::string client_ip, int port, std::string url,
uint64_t timeout, bool enable) {
if (kMsgHookFlag) {
@@ -162,15 +229,23 @@ int HookSyncMsg(std::string client_ip, int port, std::string url,
return -1;
}
DetourRestoreAfterWith();
// DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
UINT64 do_add_msg_addr = base + offset::kDoAddMsg;
DetourAttach(&(PVOID&)R_DoAddMsg, &HandleSyncMsg);
LONG ret = DetourTransactionCommit();
if(ret == NO_ERROR){
kMsgHookFlag = true;
}
SPDLOG_INFO("hook sync {}",ret);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)R_OnSnsTimeLineSceneFinish, &HandleSNSMsg);
ret = DetourTransactionCommit();
if(ret == NO_ERROR){
kSnsFinishHookFlag = true;
}
SPDLOG_INFO("hook sns {}",ret);
return ret;
}
@@ -185,7 +260,6 @@ int UnHookSyncMsg() {
UINT64 base = Utils::GetWeChatWinBase();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
UINT64 do_add_msg_addr = base + offset::kDoAddMsg;
DetourDetach(&(PVOID&)R_DoAddMsg, &HandleSyncMsg);
LONG ret = DetourTransactionCommit();
if (ret == NO_ERROR) {
@@ -196,5 +270,47 @@ int UnHookSyncMsg() {
return ret;
}
int HookLog() {
if (kLogHookFlag) {
SPDLOG_INFO("log hook already called");
return 2;
}
UINT64 base = Utils::GetWeChatWinBase();
if (!base) {
SPDLOG_INFO("base addr is null");
return -1;
}
// DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
UINT64 do_add_msg_addr = base + offset::kHookLog;
DetourAttach(&(PVOID &)R_Log, &HandlePrintLog);
LONG ret = DetourTransactionCommit();
if (ret == NO_ERROR) {
kLogHookFlag = true;
}
return ret;
}
int UnHookLog() {
if (!kLogHookFlag) {
kLogHookFlag = false;
SPDLOG_INFO("hook log reset");
return NO_ERROR;
}
UINT64 base = Utils::GetWeChatWinBase();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
UINT64 do_add_msg_addr = base + offset::kHookLog;
DetourDetach(&(PVOID &)R_Log, &HandlePrintLog);
LONG ret = DetourTransactionCommit();
if (ret == NO_ERROR) {
kLogHookFlag = false;
}
return ret;
}
} // namespace hooks
} // namespace wxhelper
+4
View File
@@ -10,6 +10,10 @@ int HookSyncMsg(std::string client_ip, int port, std::string url, uint64_t timeo
int UnHookSyncMsg();
int HookLog();
int UnHookLog();
} // namespace hooks
} // namespace wxhelper
#endif
+1 -1
View File
@@ -34,7 +34,7 @@ namespace wxhelper {
}
// Send request
int content_length = data.post_data.size();
size_t content_length = data.post_data.size();
mg_printf(c,
"POST %s HTTP/1.0\r\n"
"Host: %.*s\r\n"
+269 -8
View File
@@ -6,10 +6,21 @@
#include "hooks.h"
#include "db.h"
#define STR2ULL(str) (wxhelper::Utils::IsDigit(str) ? stoull(str) : 0)
#define STR2LL(str) (wxhelper::Utils::IsDigit(str) ? stoll(str) : 0)
#define STR2I(str) (wxhelper::Utils::IsDigit(str) ? stoi(str) : 0)
namespace common = wxhelper::common;
int GetIntParam(nlohmann::json data, std::string key) {
int result;
try {
result = data[key].get<int>();
} catch (nlohmann::json::exception) {
result = STR2I(data[key].get<std::string>());
}
return result;
}
INT64 GetINT64Param(nlohmann::json data, std::string key) {
INT64 result;
@@ -21,6 +32,16 @@ INT64 GetINT64Param(nlohmann::json data, std::string key) {
return result;
}
INT64 GetUINT64Param(nlohmann::json data, std::string key) {
UINT64 result;
try {
result = data[key].get<UINT64>();
} catch (nlohmann::json::exception) {
result = STR2ULL(data[key].get<std::string>());
}
return result;
}
std::string GetStringParam(nlohmann::json data, std::string key) {
return data[key].get<std::string>();
}
@@ -164,8 +185,17 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/hookSyncMsg")) {
int port = GetIntParam(j_param, "port");
std::string ip = GetStringParam(j_param, "ip");
int enable = GetIntParam(j_param, "enableHttp");
std::string url = "";
int timeout = 0;
if (enable) {
url = GetStringParam(j_param, "url");
timeout = GetIntParam(j_param, "timeout");
}
INT64 success =
wxhelper::hooks::HookSyncMsg("127.0.0.1", 19099, "", 3000, false);
wxhelper::hooks::HookSyncMsg(ip, port, url, timeout, enable);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
@@ -341,14 +371,245 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
}
ret = ret_data.dump();
return ret;
} else {
} else if (mg_http_match_uri(hm, "/api/topMsg")) {
INT64 msg_id = GetINT64Param(j_param, "msgId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->SetTopMsg(msg_id);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/removeTopMsg")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
INT64 msg_id = GetINT64Param(j_param, "msgId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->RemoveTopMsg(room_id,msg_id);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/InviteMemberToChatRoom")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
std::vector<std::wstring> wxids = GetArrayParam(j_param, "memberIds");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->InviteMemberToChatRoom(
room_id, wxids);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/hookLog")) {
int success = wxhelper::hooks::HookLog();
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/unhookLog")) {
int success = wxhelper::hooks::UnHookLog();
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/createChatRoom")) {
std::vector<std::wstring> wxids = GetArrayParam(j_param, "memberIds");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->CreateChatRoom(wxids);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/quitChatRoom")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->QuitChatRoom(room_id);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/forwardMsg")) {
INT64 msg_id = GetINT64Param(j_param, "msgId");
std::wstring wxid = GetWStringParam(j_param, "wxid");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->ForwardMsg(msg_id,wxid);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getSNSFirstPage")) {
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetSNSFirstPage();
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getSNSNextPage")) {
UINT64 snsid = GetUINT64Param(j_param, "snsId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetSNSNextPage(snsid);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/addFavFromMsg")) {
UINT64 msg_id = GetUINT64Param(j_param, "msgId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->AddFavFromMsg(msg_id);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/addFavFromImage")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring image_path = GetWStringParam(j_param, "imagePath");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->AddFavFromImage(
wxid, image_path);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/sendAtText")) {
std::wstring chat_room_id = GetWStringParam(j_param, "chatRoomId");
std::vector<std::wstring> wxids = GetArrayParam(j_param, "wxids");
std::wstring msg = GetWStringParam(j_param, "msg");
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->SendAtText(
chat_room_id, wxid_list, msg);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getContactProfile")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
common::ContactProfileInner profile;
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetContactByWxid(wxid,
profile);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
if (success == 1) {
nlohmann::json contact_profile = {
{"account", profile.account}, {"headImage", profile.head_image},
{"nickname", profile.nickname}, {"v3", profile.v3},
{"wxid", profile.wxid},
};
ret_data["data"] = contact_profile;
}
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/downloadAttach")) {
UINT64 msg_id = GetUINT64Param(j_param, "msgId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->DoDownloadTask(msg_id);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/forwardPublicMsg")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring appname = GetWStringParam(j_param, "appName");
std::wstring username = GetWStringParam(j_param, "userName");
std::wstring title = GetWStringParam(j_param, "title");
std::wstring url = GetWStringParam(j_param, "url");
std::wstring thumburl = GetWStringParam(j_param, "thumbUrl");
std::wstring digest = GetWStringParam(j_param, "digest");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->ForwardPublicMsg(
wxid, title, url, thumburl, username, appname, digest);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/forwardPublicMsgByMsgId")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
UINT64 msg_id = GetUINT64Param(j_param, "msgId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->ForwardPublicMsgByMsgId(
wxid, msg_id);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/decodeImage")) {
std::wstring file_path = GetWStringParam(j_param, "filePath");
std::wstring store_dir = GetWStringParam(j_param, "storeDir");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->DecodeImage(
file_path, store_dir);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getVoiceByMsgId")) {
UINT64 msg_id = GetUINT64Param(j_param, "msgId");
std::wstring store_dir = GetWStringParam(j_param, "storeDir");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->GetVoiceByDB(
msg_id, store_dir);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/sendCustomEmotion")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring file_path = GetWStringParam(j_param, "filePath");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->SendCustomEmotion(file_path,
wxid);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/sendApplet")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring waid_concat = GetWStringParam(j_param, "waidConcat");
std::string waid = GetStringParam(j_param, "waid");
std::string app_wxid = GetStringParam(j_param, "appletWxid");
std::string json_param = GetStringParam(j_param, "jsonParam");
std::string head_url = GetStringParam(j_param, "headImgUrl");
std::string main_img = GetStringParam(j_param, "mainImg");
std::string index_page = GetStringParam(j_param, "indexPage");
std::wstring waid_w = wxhelper::Utils::UTF8ToWstring(waid);
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->SendApplet(
wxid, waid_concat, waid_w, waid, app_wxid, json_param, head_url,
main_img, index_page);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/sendPatMsg")) {
std::wstring room_id = GetWStringParam(j_param, "receiver");
std::wstring wxid = GetWStringParam(j_param, "wxid");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->SendPatMsg(room_id, wxid);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/ocr")) {
std::wstring image_path = GetWStringParam(j_param, "imagePath");
std::string text("");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->DoOCRTask(image_path,text);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", text}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/test")) {
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->Test();
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else {
nlohmann::json ret_data = {
{"code", 200}, {"data", {}}, {"msg", "not support url"}};
ret = ret_data.dump();
return ret;
}
nlohmann::json ret_data = {
{"code", 200}, {"data", {}}, {"msg", "unreachable code."}};
ret = ret_data.dump();
return ret;
}
nlohmann::json ret_data = {
{"code", 200}, {"data", {}}, {"msg", "unreachable code."}};
ret = ret_data.dump();
return ret;
}
+773 -2
View File
@@ -3,6 +3,10 @@
#include "export.h"
#include "wechat_function.h"
#include "db.h"
#include "lz4.h"
#include "base64.h"
#include "tinyxml2.h"
namespace offset = wxhelper::V3_9_5_81::offset;
namespace prototype = wxhelper::V3_9_5_81::prototype;
@@ -24,7 +28,19 @@ prototype::WeChatString * BuildWechatString(const std::wstring &ws){
return p;
}
Manager::Manager(UINT64 base) : base_addr_(base) {}
prototype::WeChatStr * BuildWechatStr(const std::string &str){
prototype::WeChatStr *p = Utils::WxHeapAlloc<prototype::WeChatStr>(
sizeof(prototype::WeChatStr));
char *p_chat_room_id = Utils::WxHeapAlloc<char>(str.size() + 1);
memcpy(p_chat_room_id, str.c_str(), str.size() + 1);
p->ptr = p_chat_room_id;
p->len = static_cast<DWORD>(str.size());
p->maxlen = static_cast<DWORD>(str.size());
p->buf = NULL;
return p;
}
Manager::Manager(UINT64 base) : base_addr_(base),js_api_addr_(0) {}
Manager::~Manager() {}
INT64 Manager::CheckLogin() {
INT64 success = -1;
@@ -500,4 +516,759 @@ INT64 Manager::GetMemberFromChatRoom(const std::wstring &room_id,
free_chat_room(addr);
return success;
}
} // namespace wxhelper
INT64 Manager::SetTopMsg(ULONG64 msg_id) {
INT64 success = -1;
UINT64 top_addr = base_addr_ + offset::kTopMsg;
func::__DoTopMsg top_msg = (func::__DoTopMsg)top_addr;
INT64 index = 0;
INT64 local_id = DB::GetInstance().GetLocalIdByMsgId(msg_id, index);
if (local_id <= 0 || index >> 32 == 0) {
success = -2;
return success;
}
LARGE_INTEGER l;
l.HighPart = index >> 32;
l.LowPart = (DWORD)local_id;
UINT64 ptr = reinterpret_cast<UINT64>(&l);
success = top_msg(ptr, 1);
return success;
}
INT64 Manager::RemoveTopMsg(const std::wstring &room_id, ULONG64 msg_id) {
INT64 success = -1;
UINT64 remove_addr = base_addr_ + offset::kRemoveTopMsg;
func::__RemoveTopMsg remove_top_msg = (func::__RemoveTopMsg)remove_addr;
prototype::WeChatString *chat_room_id = BuildWechatString(room_id);
const wchar_t *w_room = room_id.c_str();
success = remove_top_msg(reinterpret_cast<UINT64>(w_room), msg_id,
reinterpret_cast<UINT64>(chat_room_id));
return success;
}
INT64 Manager::InviteMemberToChatRoom(const std::wstring &room_id,
const std::vector<std::wstring> &wxids) {
INT64 success = -1;
UINT64 invite_addr = base_addr_ + offset::kInviteMember;
func::__InviteMemberToChatRoom invite =
(func::__InviteMemberToChatRoom)invite_addr;
const wchar_t *w_room = room_id.c_str();
prototype::WeChatString *chat_room_id = BuildWechatString(room_id);
std::vector<prototype::WeChatString> wxid_list;
common::VectorInner *list = (common::VectorInner *)&wxid_list;
INT64 head = (INT64)&list->start;
for (int i = 0; i < wxids.size(); i++) {
prototype::WeChatString id(wxids[i]);
wxid_list.push_back(id);
}
UINT64 temp[2] = {0};
success = invite(reinterpret_cast<UINT64>(w_room), head,
reinterpret_cast<UINT64>(chat_room_id),
reinterpret_cast<UINT64>(&temp));
return success;
}
INT64 Manager::CreateChatRoom(const std::vector<std::wstring>& wxids){
INT64 success = -1;
UINT64 get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
UINT64 create_chat_room_addr = base_addr_ + offset::kCreateChatRoom;
func::__GetChatRoomMgr get_chat_room_mgr =
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
func::__CreateChatRoom create_chat_room =
(func::__CreateChatRoom)create_chat_room_addr;
std::vector<prototype::WeChatString> wxid_list;
common::VectorInner *list = (common::VectorInner *)&wxid_list;
INT64 head = (INT64)&list->start;
for (int i = 0; i < wxids.size(); i++) {
prototype::WeChatString id(wxids[i]);
wxid_list.push_back(id);
}
INT64 end = list->end;
UINT64 mgr = get_chat_room_mgr();
success = create_chat_room(mgr, head, end);
return success;
}
INT64 Manager::QuitChatRoom(const std::wstring &room_id) {
INT64 success = -1;
UINT64 get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
UINT64 quit_chat_room_addr = base_addr_ + offset::kQuitChatRoom;
func::__GetChatRoomMgr get_chat_room_mgr =
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
func::__QuitChatRoom quit_chat_room =
(func::__QuitChatRoom)quit_chat_room_addr;
UINT64 mgr = get_chat_room_mgr();
prototype::WeChatString chat_room_id(room_id);
success = quit_chat_room(mgr, reinterpret_cast<UINT64>(&chat_room_id), 0);
return success;
}
INT64 Manager::ForwardMsg(UINT64 msg_id, const std::wstring &wxid) {
INT64 success = -1;
UINT64 forward_addr = base_addr_ + offset::kForwardMsg;
func::__ForwardMsg forward_msg = (func::__ForwardMsg)forward_addr;
INT64 index = 0;
INT64 local_id = DB::GetInstance().GetLocalIdByMsgId(msg_id, index);
if (local_id <= 0 || index >> 32 == 0) {
success = -2;
return success;
}
LARGE_INTEGER l;
l.HighPart = index >> 32;
l.LowPart = (DWORD)local_id;
prototype::WeChatString *recv = BuildWechatString(wxid);
success = forward_msg(reinterpret_cast<UINT64>(recv), l.QuadPart, 0x4, 0x0);
return success;
}
INT64 Manager::GetSNSFirstPage() {
INT64 success = -1;
UINT64 sns_data_mgr_addr = base_addr_ + offset::kSNSDataMgr;
UINT64 sns_first_page_addr = base_addr_ + offset::kSNSGetFirstPage;
func::__GetSNSDataMgr sns_data_mgr = (func::__GetSNSDataMgr)sns_data_mgr_addr;
func::__GetSNSFirstPage sns_first_page =
(func::__GetSNSFirstPage)sns_first_page_addr;
UINT64 mgr = sns_data_mgr();
INT64 buff[16] = {0};
success = sns_first_page(mgr, reinterpret_cast<UINT64>(&buff), 1);
return success;
}
INT64 Manager::GetSNSNextPage(UINT64 sns_id) {
INT64 success = -1;
UINT64 time_line_mgr_addr = base_addr_ + offset::kSNSTimeLineMgr;
UINT64 sns_next_page_addr = base_addr_ + offset::kSNSGetNextPageScene;
func::__GetSnsTimeLineMgr time_line_mgr =
(func::__GetSnsTimeLineMgr)time_line_mgr_addr;
func::__GetSNSNextPageScene sns_next_page =
(func::__GetSNSNextPageScene)sns_next_page_addr;
UINT64 mgr = time_line_mgr();
success = sns_next_page(mgr, sns_id);
return success;
}
INT64 Manager::AddFavFromMsg(UINT64 msg_id) {
INT64 success = -1;
UINT64 get_chat_mgr_addr = base_addr_ + offset::kGetChatMgr;
UINT64 get_by_local_id_addr = base_addr_ + offset::kGetMgrByPrefixLocalId;
UINT64 add_fav_addr = base_addr_ + offset::kAddFavFromMsg;
UINT64 get_favorite_mgr_addr = base_addr_ + offset::kGetFavoriteMgr;
UINT64 free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
func::__GetMgrByPrefixLocalId get_by_local_id = (func::__GetMgrByPrefixLocalId)get_by_local_id_addr;
UINT64 new_chat_msg_addr = base_addr_ + offset::kChatMsgInstanceCounter;
func::__AddFavFromMsg add_fav = (func::__AddFavFromMsg)add_fav_addr;
func::__GetChatMgr get_chat_mgr = (func::__GetChatMgr)get_chat_mgr_addr;
func::__GetFavoriteMgr get_favorite_mgr = (func::__GetFavoriteMgr)get_favorite_mgr_addr;
func::__FreeChatMsg free_chat_msg = (func::__FreeChatMsg)free_chat_msg_addr;
func::__NewChatMsg new_chat_msg = (func::__NewChatMsg)new_chat_msg_addr;
INT64 index = 0;
INT64 local_id = DB::GetInstance().GetLocalIdByMsgId(msg_id, index);
if (local_id <= 0 || index >> 32 == 0) {
success = -2;
return success;
}
char chat_msg[0x460]= {0};
LARGE_INTEGER l;
l.HighPart = index >> 32;
l.LowPart = (DWORD)local_id;
UINT64 p_chat_msg = new_chat_msg(reinterpret_cast<UINT64>(&chat_msg));
get_chat_mgr();
get_by_local_id(l.QuadPart,p_chat_msg);
UINT64 mgr = get_favorite_mgr();
success = add_fav(mgr,p_chat_msg);
free_chat_msg(p_chat_msg);
return success;
}
INT64 Manager::AddFavFromImage(const std::wstring &wxid,
const std::wstring &image_path) {
INT64 success = -1;
UINT64 get_favorite_mgr_addr = base_addr_ + offset::kGetFavoriteMgr;
UINT64 add_fav_from_image_addr = base_addr_ + offset::kAddFavFromImage;
prototype::WeChatString *send_id = BuildWechatString(wxid);
prototype::WeChatString *path = BuildWechatString(image_path);
func::__GetFavoriteMgr get_favorite_mgr =
(func::__GetFavoriteMgr)get_favorite_mgr_addr;
func::__AddFavFromImage add_fav_from_image =
(func::__AddFavFromImage)add_fav_from_image_addr;
UINT64 mgr = get_favorite_mgr();
success = add_fav_from_image(mgr, reinterpret_cast<UINT64>(path),
reinterpret_cast<UINT64>(send_id));
return success;
}
INT64 Manager::SendAtText(const std::wstring &room_id,
const std::vector<std::wstring> &wxids,
const std::wstring &msg) {
INT64 success = -1;
std::vector<prototype::WeChatString> wxid_list;
common::VectorInner *list = (common::VectorInner *)&wxid_list;
std::wstring at_msg = L"";
int number = 0;
for (unsigned int i = 0; i < wxids.size(); i++) {
std::wstring nickname;
std::wstring at_all = L"notify@all";
if (at_all.compare(wxids[i]) == 0 ) {
nickname = L"所有人";
} else {
nickname = GetContactOrChatRoomNickname(wxids[i]);
}
if (nickname.length() == 0) {
continue;
}
prototype::WeChatString id(wxids[i]);
wxid_list.push_back(id);
at_msg = at_msg + L"@" + nickname + L" ";
number++;
}
if (number < 1) {
return success;
}
at_msg += msg;
INT64 head = (INT64)&list->start;
prototype::WeChatString to_user(room_id);
prototype::WeChatString text_msg(at_msg);
UINT64 send_message_mgr_addr = base_addr_ + offset::kGetSendMessageMgr;
UINT64 send_text_msg_addr = base_addr_ + offset::kSendTextMsg;
UINT64 free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
char chat_msg[0x460] = {0};
func::__GetSendMessageMgr mgr;
mgr = (func::__GetSendMessageMgr)send_message_mgr_addr;
func::__SendTextMsg send;
send = (func::__SendTextMsg)send_text_msg_addr;
func::__FreeChatMsg free;
free = (func::__FreeChatMsg)free_chat_msg_addr;
mgr();
success = send(reinterpret_cast<UINT64>(&chat_msg),
reinterpret_cast<UINT64>(&to_user),
reinterpret_cast<UINT64>(&text_msg), head, 1, 1, 0, 0);
free(reinterpret_cast<UINT64>(&chat_msg));
return success;
}
std::wstring Manager::GetContactOrChatRoomNickname(const std::wstring &wxid) {
prototype::WeChatString to_user(wxid);
UINT64 get_contact_mgr_addr = base_addr_ + offset::kGetContactMgr;
UINT64 new_contact_addr = base_addr_ + offset::kNewContact;
UINT64 get_contact_addr = base_addr_ + offset::kGetContact;
UINT64 free_contact_addr = base_addr_ + offset::kFreeContact;
func::__GetContactMgr get_contact_mgr =
(func::__GetContactMgr)get_contact_mgr_addr;
func::__GetContact get_contact = (func::__GetContact)get_contact_addr;
func::__NewContact new_contact = (func::__NewContact)new_contact_addr;
func::__FreeContact free_contact = (func::__FreeContact)free_contact_addr;
char buff[0x6A9] = {0};
UINT64 contact = new_contact(reinterpret_cast<UINT64>(&buff));
UINT64 mgr = get_contact_mgr();
INT64 success = get_contact(mgr, reinterpret_cast<UINT64>(&to_user), contact);
if (success == 1) {
std::wstring nickname = Utils::ReadWstring(contact + 0xA0);
free_contact(contact);
return nickname;
} else {
free_contact(contact);
return L"";
}
}
INT64 Manager::GetContactByWxid(const std::wstring &wxid,
common::ContactProfileInner &profile) {
INT64 success = -1;
prototype::WeChatString to_user(wxid);
UINT64 get_contact_mgr_addr = base_addr_ + offset::kGetContactMgr;
UINT64 new_contact_addr = base_addr_ + offset::kNewContact;
UINT64 get_contact_addr = base_addr_ + offset::kGetContact;
UINT64 free_contact_addr = base_addr_ + offset::kFreeContact;
func::__GetContactMgr get_contact_mgr =
(func::__GetContactMgr)get_contact_mgr_addr;
func::__GetContact get_contact = (func::__GetContact)get_contact_addr;
func::__NewContact new_contact = (func::__NewContact)new_contact_addr;
func::__FreeContact free_contact = (func::__FreeContact)free_contact_addr;
char buff[0x6A9] = {0};
UINT64 contact = new_contact(reinterpret_cast<UINT64>(&buff));
UINT64 mgr = get_contact_mgr();
success = get_contact(mgr, reinterpret_cast<UINT64>(&to_user), contact);
profile.wxid = Utils::ReadWstringThenConvert(contact + 0x10);
profile.account = Utils::ReadWstringThenConvert(contact + 0x30);
profile.v3 = Utils::ReadWstringThenConvert(contact + 0x50);
profile.nickname = Utils::ReadWstringThenConvert(contact + 0xA0);
profile.head_image = Utils::ReadWstringThenConvert(contact + 0x188);
free_contact(contact);
return success;
}
INT64 Manager::DoDownloadTask(UINT64 msg_id) {
INT64 success = -1;
UINT64 get_by_local_id_addr = base_addr_ + offset::kGetMgrByPrefixLocalId;
func::__GetMgrByPrefixLocalId get_by_local_id =
(func::__GetMgrByPrefixLocalId)get_by_local_id_addr;
UINT64 get_chat_mgr_addr = base_addr_ + offset::kGetChatMgr;
func::__GetChatMgr get_chat_mgr = (func::__GetChatMgr)get_chat_mgr_addr;
UINT64 free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
func::__FreeChatMsg free_chat_msg = (func::__FreeChatMsg)free_chat_msg_addr;
UINT64 new_chat_msg_addr = base_addr_ + offset::kChatMsgInstanceCounter;
func::__NewChatMsg new_chat_msg = (func::__NewChatMsg)new_chat_msg_addr;
UINT64 get_current_data_path_addr = base_addr_ + offset::kGetCurrentDataPath;
func::__GetCurrentDataPath GetCurrentDataPath =
(func::__GetCurrentDataPath)get_current_data_path_addr;
UINT64 new_app_msg_info_addr = base_addr_ + offset::kNewAppMsgInfo;
func::__NewAppMsgInfo new_app_msg_info =
(func::__NewAppMsgInfo)new_app_msg_info_addr;
UINT64 free_app_msg_info_addr = base_addr_ + offset::kFreeAppMsgInfo;
func::__FreeAppMsgInfo free_app_msg_info =
(func::__NewAppMsgInfo)free_app_msg_info_addr;
UINT64 xml_to_app_info_addr = base_addr_ + offset::kParseAppMsgXml;
func::__ParseAppMsgXml xml_to_app_info =
(func::__ParseAppMsgXml)xml_to_app_info_addr;
UINT64 get_pre_download_mgr_addr = base_addr_ + offset::kGetPreDownLoadMgr;
func::__GetPreDownLoadMgr get_pre_download_mgr =
(func::__GetPreDownLoadMgr)get_pre_download_mgr_addr;
UINT64 push_attach_task_addr = base_addr_ + offset::kPushAttachTask;
func::__PushAttachTask push_attach_task =
(func::__PushAttachTask)push_attach_task_addr;
INT64 index = 0;
INT64 local_id = DB::GetInstance().GetLocalIdByMsgId(msg_id, index);
if (local_id <= 0 || index >> 32 == 0) {
success = -2;
return success;
}
char *chat_msg = Utils::WxHeapAlloc<char>(0x460);
LARGE_INTEGER l;
l.HighPart = index >> 32;
l.LowPart = (DWORD)local_id;
UINT64 p_chat_msg = new_chat_msg(reinterpret_cast<UINT64>(chat_msg));
get_chat_mgr();
get_by_local_id(l.QuadPart, p_chat_msg);
std::wstring save_path = L"";
std::wstring thumb_path = L"";
prototype::WeChatString current_data_path;
GetCurrentDataPath(reinterpret_cast<ULONG_PTR>(&current_data_path));
if (current_data_path.length > 0) {
save_path += current_data_path.ptr;
save_path += L"wxhelper";
} else {
return -1;
}
if (!Utils::FindOrCreateDirectoryW(save_path.c_str())) {
return -3;
}
INT64 type = *(INT64 *)(chat_msg + 0x38);
wchar_t *content = *(wchar_t **)(chat_msg + 0x88);
DWORD len = *(DWORD *)(chat_msg + 0x94);
std::wstring tmp_content(content, len);
prototype::WeChatString *we_content = BuildWechatString(tmp_content);
switch (type) {
case 0x3: {
save_path += L"\\image";
if (!Utils::FindOrCreateDirectoryW(save_path.c_str())) {
return -3;
}
thumb_path = save_path + L"\\" + std::to_wstring(msg_id) + L"_t.dat";
save_path = save_path + L"\\" + std::to_wstring(msg_id) + L".dat";
break;
}
case 0x3E:
case 0x2B: {
save_path += L"\\video";
if (!Utils::FindOrCreateDirectoryW(save_path.c_str())) {
return -3;
}
thumb_path = save_path + L"\\" + std::to_wstring(msg_id) + L".jpg";
save_path = save_path + L"\\" + std::to_wstring(msg_id) + L".mp4";
break;
}
case 0x31: {
save_path += L"\\file";
if (!Utils::FindOrCreateDirectoryW(save_path.c_str())) {
return -3;
}
char *p_xml_app_msg = Utils::WxHeapAlloc<char>(0x3000);
UINT64 xml_msg =
new_app_msg_info(reinterpret_cast<UINT64>(p_xml_app_msg));
UINT64 result =
xml_to_app_info(xml_msg, reinterpret_cast<UINT64>(we_content), 1);
if (result != 1) {
return -4;
}
std::wstring file_name = Utils::ReadWstring(xml_msg + 0x70);
save_path =
save_path + L"\\" + std::to_wstring(msg_id) + L"_" + file_name;
free_app_msg_info(xml_msg);
break;
}
default:
break;
}
prototype::WeChatString *we_save_path = BuildWechatString(save_path);
prototype::WeChatString *we_thumb_path = BuildWechatString(thumb_path);
int temp = 1;
memcpy(chat_msg + 0x280, we_thumb_path, sizeof(prototype::WeChatString));
memcpy(chat_msg + 0x2A0, we_save_path, sizeof(prototype::WeChatString));
memcpy(chat_msg + 0x40C, &temp, sizeof(temp));
UINT64 mgr = get_pre_download_mgr();
success = push_attach_task(mgr, p_chat_msg, 0, 1);
free_chat_msg(p_chat_msg);
return success;
}
INT64 Manager::ForwardPublicMsg(const std::wstring &wxid,
const std::wstring &title,
const std::wstring &url,
const std::wstring &thumb_url,
const std::wstring &sender_id,
const std::wstring &sender_name,
const std::wstring &digest) {
INT64 success = -1;
UINT64 new_item_addr = base_addr_ + offset::kNewMMReaderItem;
func::__NewMMReaderItem new_item = (func::__NewMMReaderItem)new_item_addr;
UINT64 free_item_addr = base_addr_ + offset::kFreeMMReaderItem;
func::__FreeMMReaderItem free_item = (func::__FreeMMReaderItem)free_item_addr;
UINT64 get_app_msg_mgr_addr = base_addr_ + offset::kGetAppMsgMgr;
func::__GetAppMsgMgr get_app_mgr = (func::__GetAppMsgMgr)get_app_msg_mgr_addr;
UINT64 forward_public_msg_addr = base_addr_ + offset::kForwordPublicMsg;
func::__ForwordPublicMsg forward_public_msg =
(func::__ForwordPublicMsg)forward_public_msg_addr;
char *p_item = Utils::WxHeapAlloc<char>(0x3E4);
new_item(reinterpret_cast<UINT64>(p_item));
prototype::WeChatString *to_user = BuildWechatString(wxid);
prototype::WeChatString *p_title = BuildWechatString(title);
prototype::WeChatString *p_url = BuildWechatString(url);
prototype::WeChatString *p_thumburl = BuildWechatString(thumb_url);
prototype::WeChatString *p_sender_id = BuildWechatString(sender_id);
prototype::WeChatString *p_name = BuildWechatString(sender_name);
prototype::WeChatString *p_digest = BuildWechatString(digest);
memcpy(p_item + 0x8, p_title, sizeof(prototype::WeChatString));
memcpy(p_item + 0x48, p_url, sizeof(prototype::WeChatString));
memcpy(p_item + 0xB0, p_thumburl, sizeof(prototype::WeChatString));
memcpy(p_item + 0xF0, p_digest, sizeof(prototype::WeChatString));
memcpy(p_item + 0x2A0, p_sender_id, sizeof(prototype::WeChatString));
memcpy(p_item + 0x2C0, p_name, sizeof(prototype::WeChatString));
memcpy(p_item + 0x2C0, p_name, sizeof(prototype::WeChatString));
UINT64 mgr = get_app_mgr();
success = forward_public_msg(mgr, reinterpret_cast<UINT64>(to_user),
reinterpret_cast<UINT64>(p_item));
free_item(reinterpret_cast<UINT64>(p_item));
return success;
}
INT64 Manager::ForwardPublicMsgByMsgId(const std::wstring &wxid,
UINT64 msg_id) {
INT64 success = -1;
std::string compress_content =
DB::GetInstance().GetPublicMsgCompressContentByMsgId(msg_id);
if (compress_content.empty()) {
SPDLOG_INFO("Get compressContent is null from PublicMsg.db");
return -3;
}
std::string decode = base64_decode(compress_content);
size_t len = decode.size();
const char *src = decode.c_str();
size_t dst_len = (len << 8);
char *dst = new char[dst_len];
int decompress_len = LZ4_decompress_safe_partial(
src, dst, static_cast<int>(len), static_cast<int>(dst_len), static_cast<int>(dst_len));
if (decompress_len < 0) {
SPDLOG_INFO("decompress content size :{}", decompress_len);
return -1;
}
tinyxml2::XMLDocument doc;
if (doc.Parse(dst, decompress_len - 1) != 0) {
SPDLOG_INFO("tinyxml2 parse error");
return -2;
}
const char *title = doc.FirstChildElement("msg")
->FirstChildElement("appmsg")
->FirstChildElement("title")
->GetText();
const char *digest = doc.FirstChildElement("msg")
->FirstChildElement("appmsg")
->FirstChildElement("des")
->GetText();
const char *url = doc.FirstChildElement("msg")
->FirstChildElement("appmsg")
->FirstChildElement("mmreader")
->FirstChildElement("category")
->FirstChildElement("item")
->FirstChildElement("url")
->GetText();
const char *thumb_url = doc.FirstChildElement("msg")
->FirstChildElement("appmsg")
->FirstChildElement("thumburl")
->GetText();
const char *user_name = doc.FirstChildElement("msg")
->FirstChildElement("appmsg")
->FirstChildElement("mmreader")
->FirstChildElement("publisher")
->FirstChildElement("username")
->GetText();
const char *nickname = doc.FirstChildElement("msg")
->FirstChildElement("appmsg")
->FirstChildElement("mmreader")
->FirstChildElement("publisher")
->FirstChildElement("nickname")
->GetText();
std::string s_title(title);
std::string s_digest(digest);
std::string s_url(url);
std::string s_thumburl(thumb_url);
std::string s_user_name(user_name);
std::string s_nickname(nickname);
std::wstring ws_title = Utils::UTF8ToWstring(s_title);
std::wstring ws_digest = Utils::UTF8ToWstring(s_digest);
std::wstring ws_url = Utils::UTF8ToWstring(s_url);
std::wstring ws_thumb_url = Utils::UTF8ToWstring(s_thumburl);
std::wstring ws_user_name = Utils::UTF8ToWstring(s_user_name);
std::wstring ws_nickname = Utils::UTF8ToWstring(s_nickname);
success = ForwardPublicMsg(wxid, ws_title, ws_url, ws_thumb_url, ws_user_name,
ws_nickname, ws_digest);
return success;
}
INT64 Manager::DecodeImage(const std::wstring &file_path, const std::wstring &save_dir) {
return Utils::DecodeImage(file_path.c_str(), save_dir.c_str());
}
INT64 Manager::GetVoiceByDB(ULONG64 msg_id, const std::wstring& dir) {
INT64 success = -1;
std::string buff = DB::GetInstance().GetVoiceBuffByMsgId(msg_id);
if (buff.size() == 0) {
success = 0;
return success;
}
std::wstring save_path = dir;
if (!Utils::FindOrCreateDirectoryW(save_path.c_str())) {
success = -2;
return success;
}
save_path = save_path + L"\\" + std::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) {
SPDLOG_ERROR("GetVoiceByDB save path invalid");
return success;
}
DWORD bytes_write = 0;
std::string decode = base64_decode(buff);
WriteFile(file_handle, (LPCVOID)decode.c_str(), static_cast<DWORD>(decode.size()) , &bytes_write, 0);
CloseHandle(file_handle);
success = 1;
return success;
}
INT64 Manager::SendCustomEmotion(const std::wstring &file_path,
const std::wstring &wxid) {
INT64 success = -1;
UINT64 get_custom_smiley_mgr_addr = base_addr_ + offset::kGetCustomSmileyMgr;
func::__GetCustomSmileyMgr get_custom_smiley_mgr =
(func::__GetCustomSmileyMgr)get_custom_smiley_mgr_addr;
UINT64 send_custom_emotion_addr = base_addr_ + offset::kSendCustomEmotion;
func::__SendCustomEmotion send_custom_emotion =
(func::__SendCustomEmotion)send_custom_emotion_addr;
prototype::WeChatString *path = BuildWechatString(file_path);
prototype::WeChatString *recv = BuildWechatString(wxid);
INT64 *temp = Utils::WxHeapAlloc<INT64>(0x20);
memset(temp, 0, 0x20);
UINT64 mgr = get_custom_smiley_mgr();
success = send_custom_emotion(
mgr, reinterpret_cast<UINT64>(path), reinterpret_cast<UINT64>(temp),
reinterpret_cast<UINT64>(recv), 2, reinterpret_cast<UINT64>(temp), 0,
reinterpret_cast<UINT64>(temp));
return success;
}
INT64 Manager::SendApplet(const std::wstring &recv_wxid,
const std::wstring &waid_suff,
const std::wstring &waid_w, const std::string &waid_s,
const std::string &wa_wxid,
const std::string &json_param,
const std::string &head_image,
const std::string &big_image,
const std::string &index_page) {
INT64 success = -1;
if (js_api_addr_ == 0) {
auto vec2 = Utils::QWordScan(base_addr_ + 0x32D1318, 0x1000, 0x8);
for (int i = 0; i < vec2.size(); i++) {
INT64 ptr = vec2.at(i);
if (*(INT64 *)ptr == base_addr_ + 0x32D1318) {
js_api_addr_ = ptr;
break;
}
}
}
if (js_api_addr_ == 0) {
success = -2;
return success;
}
UINT64 share_app_msg_addr = base_addr_ + offset::kNewJsApiShareAppMessage;
func::__JsApiShareAppMessage share_app_msg =
(func::__JsApiShareAppMessage)share_app_msg_addr;
UINT64 init_addr = base_addr_ + offset::kInitJsConfig;
func::__InitJsConfig init = (func::__InitJsConfig)init_addr;
UINT64 send_applet_addr = base_addr_ + offset::kSendApplet;
func::__SendApplet send_applet = (func::__SendApplet)send_applet_addr;
UINT64 get_by_waid_addr = base_addr_ + offset::kGetAppInfoByWaid;
func::__GetAppInfoByWaid get_app_info =
(func::__GetAppInfoByWaid)get_by_waid_addr;
UINT64 copy_app_req_addr = base_addr_ + offset::kCopyShareAppMessageRequest;
func::__CopyShareAppMessageRequest copy_app_req =
(func::__CopyShareAppMessageRequest)copy_app_req_addr;
UINT64 new_wa_msg_addr = base_addr_ + offset::kNewWAUpdatableMsgInfo;
func::__NewWAUpdatableMsgInfo new_wa_msg =
(func::__NewWAUpdatableMsgInfo)new_wa_msg_addr;
UINT64 free_wa_msg_addr = base_addr_ + offset::kFreeWAUpdatableMsgInfo;
func::__FreeWAUpdatableMsgInfo free_wa_msg =
(func::__FreeWAUpdatableMsgInfo)free_wa_msg_addr;
std::vector<prototype::WeChatString> *temp =
Utils::WxHeapAlloc<std::vector<prototype::WeChatString>>(0x20);
// std::vector<prototype::WeChatString>* temp = new
// std::vector<prototype::WeChatString>();
common::VectorInner *list = (common::VectorInner *)temp;
prototype::WeChatString *member = BuildWechatString(recv_wxid);
#ifdef _DEBUG
list->head = reinterpret_cast<UINT64>(member);
#endif
list->start = reinterpret_cast<UINT64>(member);
list->finsh = reinterpret_cast<UINT64>(member) + 0x20;
list->end = reinterpret_cast<UINT64>(member) + 0x20;
INT64 head = reinterpret_cast<UINT64>(&(list->start));
prototype::WeChatString *waid_cat = BuildWechatString(waid_suff);
prototype::WeChatString *waid = BuildWechatString(waid_w);
prototype::WeChatString *waid_2 = BuildWechatString(waid_suff);
prototype::WeChatStr *waid_str = BuildWechatStr(waid_s);
prototype::WeChatStr *app_wxid = BuildWechatStr(wa_wxid);
prototype::WeChatStr *json_str = BuildWechatStr(json_param);
prototype::WeChatStr *head_image_url = BuildWechatStr(head_image);
prototype::WeChatStr *image = BuildWechatStr(big_image);
prototype::WeChatStr *index = BuildWechatStr(index_page);
UINT64 app_msg = js_api_addr_;
UINT64 data = *(UINT64 *)(app_msg + 0x8);
char *share_req = Utils::WxHeapAlloc<char>(0x2000);
char *mid_ptr = Utils::WxHeapAlloc<char>(0x18);
memcpy(mid_ptr, &share_req, sizeof(INT64));
memcpy(mid_ptr + 0x8, &share_req, sizeof(INT64));
memcpy(mid_ptr + 0x10, &share_req, sizeof(INT64));
memcpy((void *)data, mid_ptr, 0x18);
memcpy(share_req, (void *)(app_msg + 0x8), sizeof(UINT64));
memcpy(share_req + 0x8, (void *)(app_msg + 0x8), sizeof(UINT64));
memcpy(share_req + 0x10, (void *)(app_msg + 0x8), sizeof(UINT64));
memcpy(share_req + 0x20, waid_2, sizeof(prototype::WeChatString));
memcpy(share_req + 0x48, waid_str, sizeof(prototype::WeChatStr));
memcpy(share_req + 0x98, app_wxid, sizeof(prototype::WeChatStr));
memcpy(share_req + 0xF8, json_str, sizeof(prototype::WeChatStr));
memcpy(share_req + 0x178, head_image_url, sizeof(prototype::WeChatStr));
memcpy(share_req + 0x198, image, sizeof(prototype::WeChatStr));
memcpy(share_req + 0x1c0, index, sizeof(prototype::WeChatStr));
success = send_applet(app_msg, reinterpret_cast<UINT64>(waid_cat), head, 0);
return success;
}
INT64 Manager::SendPatMsg(const std::wstring &room_id,
const std::wstring &wxid) {
INT64 success = -1;
UINT64 send_pat_msg_addr = base_addr_ + offset::kSendPatMsg;
func::__SendPatMsg send_pat_msg =(func::__SendPatMsg)send_pat_msg_addr;
prototype::WeChatString chat_room(room_id);
prototype::WeChatString target(wxid);
success = send_pat_msg(reinterpret_cast<UINT64>(&chat_room),reinterpret_cast<UINT64>(&target));
return success;
}
INT64 Manager::DoOCRTask(const std::wstring &img_path, std::string &result) {
INT64 success = -1;
UINT64 ocr_manager_addr = base_addr_ + offset::kGetOCRManager;
func::__GetOCRManager ocr_manager = (func::__GetOCRManager)ocr_manager_addr;
UINT64 do_ocr_task_addr = base_addr_ + offset::kDoOCRTask;
func::__DoOCRTask do_ocr_task = (func::__DoOCRTask)do_ocr_task_addr;
prototype::WeChatString img(img_path);
std::vector<INT64> *temp = Utils::WxHeapAlloc<std::vector<INT64>>(0x20);
INT64 unkonwn = 0;
common::VectorInner *list = (common::VectorInner *)temp;
list->start = reinterpret_cast<INT64>(&list->start);
list->finsh = list->start;
char buff[0x28] = {0};
memcpy(buff, &list->start, sizeof(INT64));
UINT64 mgr = ocr_manager();
success = do_ocr_task(mgr, reinterpret_cast<UINT64>(&img),1,
reinterpret_cast<UINT64>(buff),reinterpret_cast<UINT64>(&unkonwn));
INT64 number = *(INT64 *)(buff + 0x8);
if (number > 0) {
INT64 header = *(INT64 *)(buff);
for (unsigned int i = 0; i < number; i++) {
INT64 content = *(INT64 *)header;
result += Utils::ReadWstringThenConvert(content + 0x28);
result += "\r\n";
header = content;
}
}
return success;
}
INT64 Manager::Test() {
auto vec = Utils::QWordScan(base_addr_ + 0x32D1318, 0x1, L"WeChatWin.dll");
for (int i = 0; i < vec.size(); i++) {
INT64 re = vec.at(i);
SPDLOG_INFO("scan result :{},{}", i, re);
}
auto vec2 = Utils::QWordScan(base_addr_ + 0x32D1318, 0x1000, 0x8);
for (int i = 0; i < vec2.size(); i++) {
INT64 re = vec2.at(i);
SPDLOG_INFO("scan2 result :{},{}", i, re);
}
return 1;
}
} // namespace wxhelper
+40
View File
@@ -25,9 +25,49 @@ class Manager {
const std::vector<std::wstring>& members);
INT64 GetMemberFromChatRoom(const std::wstring& room_id,
common::ChatRoomMemberInner& member);
INT64 SetTopMsg(ULONG64 msg_id);
INT64 RemoveTopMsg(const std::wstring& room_id,ULONG64 msg_id);
INT64 InviteMemberToChatRoom(const std::wstring& room_id,
const std::vector<std::wstring>& wxids);
INT64 CreateChatRoom(const std::vector<std::wstring>& wxids);
INT64 QuitChatRoom(const std::wstring& room_id);
INT64 ForwardMsg(UINT64 msg_id, const std::wstring& wxid);
INT64 GetSNSFirstPage();
INT64 GetSNSNextPage(UINT64 sns_id);
INT64 AddFavFromMsg(UINT64 msg_id);
INT64 AddFavFromImage(const std::wstring& wxid,
const std::wstring& image_path);
INT64 SendAtText(const std::wstring& room_id,
const std::vector<std::wstring>& wxids,
const std::wstring& msg);
std::wstring GetContactOrChatRoomNickname(const std::wstring& wxid);
INT64 GetContactByWxid(const std::wstring& wxid,
common::ContactProfileInner& profile);
INT64 DoDownloadTask(UINT64 msg_id);
INT64 ForwardPublicMsg(const std::wstring& wxid, const std::wstring& title,
const std::wstring& url, const std::wstring& thumb_url,
const std::wstring& sender_id,
const std::wstring& sender_name,
const std::wstring& digest);
INT64 ForwardPublicMsgByMsgId(const std::wstring& wxid, UINT64 msg_id);
INT64 DecodeImage(const std::wstring& file_path,
const std::wstring& save_dir);
INT64 GetVoiceByDB(ULONG64 msg_id, const std::wstring& dir);
INT64 SendCustomEmotion(const std::wstring& file_path,
const std::wstring& wxid);
INT64 SendApplet(
const std::wstring& recv_wxid, const std::wstring& waid_suff,
const std::wstring& waid_w, const std::string& waid_s,
const std::string& wa_wxid, const std::string& json_param,
const std::string& head_image, const std::string& big_image,
const std::string& index_page);
INT64 SendPatMsg(const std::wstring& room_id, const std::wstring& wxid);
INT64 DoOCRTask(const std::wstring& img_path, std::string &result);
INT64 Test();
private:
UINT64 base_addr_;
UINT64 js_api_addr_;
};
} // namespace wxhelper
+138
View File
@@ -1,6 +1,7 @@
#include "pch.h"
#include "utils.h"
#include <winternl.h>
#include <Psapi.h>
#define BUFSIZE 1024
#define JPEG0 0xFF
#define JPEG1 0xD8
@@ -319,4 +320,141 @@ std::string Utils::ReadWstringThenConvert(INT64 addr){
std::wstring wstr = ReadWstring(addr);
return WstringToUTF8(wstr);
}
INT64 Utils::DecodeImage(const wchar_t* file_path,const wchar_t* save_dir){
std::wstring save_path(save_dir);
std::wstring orign_file_path(file_path);
if (!Utils::FindOrCreateDirectoryW(save_path.c_str())) {
return 0;
}
INT64 pos_begin = orign_file_path.find_last_of(L"\\") + 1;
INT64 pos_end = orign_file_path.find_last_of(L".");
std::wstring file_name =
orign_file_path.substr(pos_begin, pos_end - pos_begin);
HANDLE h_origin_file =
CreateFileW(file_path, GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
char buffer[BUFSIZE] = {0};
DWORD bytes_read = 0;
DWORD bytes_write = 0;
unsigned char magic_head[4] = {0};
std::wstring suffix;
short key = 0;
if (ReadFile(h_origin_file, buffer, BUFSIZE, &bytes_read, NULL)) {
memcpy(magic_head, buffer, 3);
} else {
CloseHandle(h_origin_file);
return 0;
}
if ((magic_head[0] ^ JPEG0) == (magic_head[1] ^ JPEG1)) {
key = magic_head[0] ^ JPEG0;
suffix = L".jpg";
} else if ((magic_head[0] ^ PNG1) == (magic_head[1] ^ PNG2)) {
key = magic_head[0] ^ PNG1;
suffix = L".png";
} else if ((magic_head[0] ^ GIF0) == (magic_head[1] ^ GIF1)) {
key = magic_head[0] ^ GIF0;
suffix = L".gif";
} else if ((magic_head[0] ^ BMP0) == (magic_head[1] ^ BMP1)) {
key = magic_head[0] ^ BMP0;
suffix = L".bmp";
} else {
key = -1;
suffix = L".dat";
}
std::wstring save_img_path = save_path + L"\\" + file_name + suffix;
HANDLE save_img = CreateFileW(save_img_path.c_str(), GENERIC_ALL, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (save_img == INVALID_HANDLE_VALUE) {
return 0;
}
if (key > 0) {
for (unsigned int i = 0; i < bytes_read; i++) {
buffer[i] ^= key;
}
}
if (!WriteFile(save_img, (LPCVOID)buffer, bytes_read, &bytes_write, 0)) {
CloseHandle(h_origin_file);
CloseHandle(save_img);
return 0;
}
do {
if (ReadFile(h_origin_file, buffer, BUFSIZE, &bytes_read, NULL)) {
if (key > 0) {
for (unsigned int i = 0; i < bytes_read; i++) {
buffer[i] ^= key;
}
}
if (!WriteFile(save_img, (LPCVOID)buffer, bytes_read, &bytes_write, 0)) {
CloseHandle(h_origin_file);
CloseHandle(save_img);
return 0;
}
}
} while (bytes_read == BUFSIZE);
CloseHandle(h_origin_file);
CloseHandle(save_img);
return 1;
}
std::vector<INT64> Utils::QWordScan(INT64 value, int align,
const wchar_t *module) {
MODULEINFO module_info;
std::vector<INT64> result;
if (GetModuleInformation(GetCurrentProcess(), GetModuleHandleW(module),
&module_info, sizeof(module_info))) {
auto start = static_cast<const char *>(module_info.lpBaseOfDll);
const auto end = start + module_info.SizeOfImage - 0x8;
auto current_addr = start;
while (current_addr < end) {
if (*(INT64*)current_addr == value) {
result.push_back(reinterpret_cast<INT64>(current_addr));
}
start += align;
current_addr = start;
}
}
return result;
}
std::vector<INT64> Utils::QWordScan(INT64 value, INT64 start,int align) {
SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info);
std::vector<INT64> result;
INT64 min_addr =
reinterpret_cast<INT64>(sys_info.lpMinimumApplicationAddress);
INT64 max_addr =
reinterpret_cast<INT64>(sys_info.lpMaximumApplicationAddress);
const INT64 page_size = sys_info.dwPageSize;
min_addr = min_addr > start ? min_addr : start;
auto current_addr = min_addr;
MEMORY_BASIC_INFORMATION mem_info = {};
HANDLE handle = GetCurrentProcess();
while (current_addr < max_addr) {
VirtualQueryEx(handle, reinterpret_cast<LPVOID>(current_addr), &mem_info,
sizeof(MEMORY_BASIC_INFORMATION));
if ((INT64)mem_info.RegionSize <= 0) {
break;
}
INT64 region_size = mem_info.RegionSize;
if ((mem_info.State & MEM_COMMIT) == MEM_COMMIT &&
(mem_info.Protect & PAGE_GUARD) != PAGE_GUARD &&
(mem_info.Protect & PAGE_NOACCESS) != PAGE_NOACCESS) {
for (INT64 i = 0; i < region_size; i += align) {
if (value == *(INT64 *)current_addr) {
result.push_back(current_addr);
}
current_addr += align;
}
} else {
current_addr += region_size;
}
}
return result;
}
} // namespace wxhelper
+6
View File
@@ -58,6 +58,12 @@ class Utils {
static std::wstring ReadWstring(INT64 addr);
static std::string ReadWstringThenConvert(INT64 addr);
static INT64 DecodeImage(const wchar_t* file_path,const wchar_t* save_dir);
static std::vector<INT64> QWordScan(INT64 value, int align,
const wchar_t *module);
static std::vector<INT64> QWordScan(INT64 value, INT64 start,int align);
template <typename T1, typename T2>
static std::vector<T1> split(T1 str, T2 letter) {
std::vector<T1> arr;
+119 -1
View File
@@ -112,7 +112,7 @@ struct SqlResult {
struct InnerMessageStruct {
char *buffer;
int length;
INT64 length;
~InnerMessageStruct() {
if (this->buffer != NULL) {
delete[] this->buffer;
@@ -198,6 +198,16 @@ struct ChatRoomMemberInner {
member("") {}
};
struct ContactProfileInner {
std::string wxid;
std::string account;
std::string v3;
std::string nickname;
std::string head_image;
ContactProfileInner()
: wxid(""), account(""), v3(""), nickname(""), head_image("") {}
};
} // namespace common
namespace V3_9_5_81 {
namespace function {
@@ -233,6 +243,49 @@ typedef UINT64 (*__GetMemberFromChatRoom)(UINT64,UINT64,UINT64);
typedef UINT64 (*__NewChatRoom)(UINT64);
typedef UINT64 (*__FreeChatRoom)(UINT64);
typedef UINT64 (*__DoTopMsg)(UINT64,UINT64);
typedef UINT64 (*__RemoveTopMsg)(UINT64,UINT64,UINT64);
typedef UINT64 (*__InviteMemberToChatRoom)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__CreateChatRoom)(UINT64,UINT64,UINT64);
typedef UINT64 (*__QuitChatRoom)(UINT64,UINT64,UINT64);
typedef UINT64 (*__ForwardMsg)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__GetSNSFirstPage)(UINT64,UINT64,UINT64);
typedef UINT64 (*__GetSNSNextPageScene)(UINT64,UINT64);
typedef UINT64 (*__GetSNSDataMgr)();
typedef UINT64 (*__GetSnsTimeLineMgr)();
typedef UINT64 (*__GetMgrByPrefixLocalId)(UINT64,UINT64);
typedef UINT64 (*__AddFavFromMsg)(UINT64,UINT64);
typedef UINT64 (*__GetChatMgr)();
typedef UINT64 (*__GetFavoriteMgr)();
typedef UINT64 (*__AddFavFromImage)(UINT64,UINT64,UINT64);
typedef UINT64 (*__GetContact)(UINT64,UINT64,UINT64);
typedef UINT64 (*__NewContact)(UINT64);
typedef UINT64 (*__FreeContact)(UINT64);
typedef UINT64 (*__NewMMReaderItem)(UINT64);
typedef UINT64 (*__FreeMMReaderItem)(UINT64);
typedef UINT64 (*__ForwordPublicMsg)(UINT64,UINT64,UINT64);
typedef UINT64 (*__NewAppMsgInfo)(UINT64);
typedef UINT64 (*__FreeAppMsgInfo)(UINT64);
typedef UINT64 (*__ParseAppMsgXml)(UINT64,UINT64,UINT64);
typedef UINT64 (*__GetPreDownLoadMgr)();
typedef UINT64 (*__PushAttachTask)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__GetCustomSmileyMgr)();
typedef UINT64 (*__SendCustomEmotion)(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__JsApiShareAppMessage)(UINT64);
typedef UINT64 (*__InitJsConfig)(UINT64,UINT64);
typedef UINT64 (*__SendApplet)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__SendAppletSecond)(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__GetAppInfoByWaid)(UINT64,UINT64);
typedef UINT64 (*__CopyShareAppMessageRequest)(UINT64,UINT64);
typedef UINT64 (*__NewWAUpdatableMsgInfo)(UINT64);
typedef UINT64 (*__FreeWAUpdatableMsgInfo)(UINT64);
typedef UINT64 (*__SendPatMsg)(UINT64,UINT64);
typedef UINT64 (*__GetOCRManager)();
typedef UINT64 (*__DoOCRTask)(UINT64,UINT64,UINT64,UINT64,UINT64);
} // namespace function
namespace prototype {
@@ -271,6 +324,26 @@ struct WeChatString {
}
};
struct WeChatStr{
char * ptr;
INT64 buf;
INT64 len;
INT64 maxlen;
WeChatStr(const char* p) {
ptr = (char *)p;
buf = 0;
len = strlen(p);
maxlen = len | 0xF;
}
WeChatStr() {
ptr = NULL;
buf = 0;
len = 0;
maxlen = 0xF;
}
};
} // namespace prototype
namespace offset {
const UINT64 kGetAccountServiceMgr = 0x8c1230;
@@ -329,6 +402,51 @@ const UINT64 kDelMemberFromChatRoom = 0xe64290;
const UINT64 kGetMemberFromChatRoom = 0xe74de0;
const UINT64 kNewChatRoom = 0x11fde50;
const UINT64 kFreeChatRoom = 0x11fe030;
const UINT64 kTopMsg = 0xa5e4f0;
const UINT64 kRemoveTopMsg = 0xe787b0;
const UINT64 kInviteMember = 0xe63650;
const UINT64 kHookLog = 0x1304e60;
const UINT64 kCreateChatRoom = 0xe63340;
const UINT64 kQuitChatRoom = 0xe6e3b0;
const UINT64 kForwardMsg = 0xfcd0f0;
const UINT64 kOnSnsTimeLineSceneFinish = 0x1a73150;
const UINT64 kSNSGetFirstPage = 0x1a51dd0;
const UINT64 kSNSGetNextPageScene = 0x1a77240;
const UINT64 kSNSDataMgr = 0xeebda0;
const UINT64 kSNSTimeLineMgr = 0x19e83a0;
const UINT64 kGetMgrByPrefixLocalId = 0xe4add0;
const UINT64 kAddFavFromMsg = 0x1601520;
const UINT64 kGetChatMgr = 0x8f0400;
const UINT64 kGetFavoriteMgr = 0x8c69b0;
const UINT64 kAddFavFromImage = 0x160b920;
const UINT64 kGetContact = 0xEA5F90;
const UINT64 kNewContact = 0x1212e40;
const UINT64 kFreeContact = 0x12134e0;
const UINT64 kNewMMReaderItem = 0x8c79a0;
const UINT64 kFreeMMReaderItem = 0x8c6da0;
const UINT64 kForwordPublicMsg = 0xddc6c0;
const UINT64 kParseAppMsgXml = 0x11b0a70;
const UINT64 kNewAppMsgInfo = 0x91a550;
const UINT64 kFreeAppMsgInfo = 0x8fd1a0;
const UINT64 kGetPreDownLoadMgr = 0x9996f0;
const UINT64 kPushAttachTask = 0x9c0080;
const UINT64 kGetCustomSmileyMgr = 0x915c00;
const UINT64 kSendCustomEmotion = 0xec0a40;
const UINT64 kNewJsApiShareAppMessage = 0x13be1a0;
const UINT64 kInitJsConfig = 0x137bc00;
const UINT64 kSendApplet = 0x13c0920;
const UINT64 kSendAppletSecond = 0x13c1150;
const UINT64 kGetAppInfoByWaid = 0x13c5790;
const UINT64 kCopyShareAppMessageRequest = 0x13c0670;
const UINT64 kNewWAUpdatableMsgInfo = 0x919ca0;
const UINT64 kFreeWAUpdatableMsgInfo = 0x8fc230;
const UINT64 kSendPatMsg = 0x195f340;
const UINT64 kGetOCRManager = 0x999780;
const UINT64 kDoOCRTask = 0x190b2a0;
} // namespace offset
} // namespace V3_9_5_81