v30.2.4适配java客户端
This commit is contained in:
parent
1c1625ad7e
commit
0744cf225d
6
clients/java/README.MD
vendored
6
clients/java/README.MD
vendored
@ -4,7 +4,7 @@
|
||||
|
||||
## 快速开始
|
||||
|
||||
* 下载 [最新发布的文件](https://github.com/lich0821/WeChatFerry/releases/latest),解压到 `WeChatFerry\clients\java\wcferry\src\main\resources\win32-x86-64`。
|
||||
* 下载 [最新发布的文件](https://github.com/lich0821/WeChatFerry/releases/latest),解压到 `WeChatFerry\clients\java\wcferry\dll`目录下。
|
||||
|
||||
* 使用惯用 IDE,打开工程,编译,运行。
|
||||
|
||||
@ -68,9 +68,9 @@ cd C:/Projs/WeChatFerry/java/wcferry/src/main/java
|
||||
protoc.exe --java_out=. --proto_path=C:\Projs\WeChatFerry\WeChatFerry\rpc\proto wcf.proto
|
||||
```
|
||||
|
||||
### 添加 `wcferry` 依赖
|
||||
### 添加 `dll` 依赖
|
||||
|
||||
将 `wcf.exe` 、 `spy.dll` 、 `spy_debug.dll` 添加到 `WeChatFerry\clients\java\wcferry\src\main\resources\win32-x86-64`。
|
||||
将 `spy.dll` 、 `spy_debug.dll`、 `spy.dll` 添加到 `WeChatFerry\clients\java\wcferry\dll`。
|
||||
|
||||
### 其他问题
|
||||
|
||||
|
@ -5,8 +5,6 @@ import io.sisu.nng.Socket;
|
||||
import io.sisu.nng.pair.Pair1Socket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@ -16,60 +14,41 @@ import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
public class Client {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Client.class);
|
||||
private final int BUFFER_SIZE = 16 * 1024 * 1024; // 16M
|
||||
private static final int BUFFER_SIZE = 16 * 1024 * 1024; // 16M
|
||||
private Socket cmdSocket = null;
|
||||
private Socket msgSocket = null;
|
||||
private String host = "127.0.0.1";
|
||||
private int port = 10086;
|
||||
private static String DEFAULT_HOST = "127.0.0.1";
|
||||
private static int PORT = 10086;
|
||||
private static String CMDURL = "tcp://%s:%s";
|
||||
private boolean isReceivingMsg = false;
|
||||
private boolean isLocalHostPort = false;
|
||||
private BlockingQueue<WxMsg> msgQ;
|
||||
private String wcfPath;
|
||||
|
||||
public Client(String host, int port) {
|
||||
private String host;
|
||||
private int port;
|
||||
|
||||
public Client() {
|
||||
this(DEFAULT_HOST, PORT, false);
|
||||
}
|
||||
|
||||
public Client(String host, int port, boolean debug) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
String cmdUrl = "tcp://" + host + ":" + port;
|
||||
connectRPC(cmdUrl);
|
||||
}
|
||||
|
||||
public Client(int port, boolean debug) {
|
||||
initClient(this.host, port, debug);
|
||||
}
|
||||
|
||||
public Client(boolean debug) {
|
||||
initClient(this.host, this.port, debug);
|
||||
}
|
||||
|
||||
private void initClient(String host, int port, boolean debug) {
|
||||
try {
|
||||
URL url = this.getClass().getResource("/win32-x86-64/wcf.exe");
|
||||
wcfPath = url.getFile();
|
||||
String[] cmd = new String[4];
|
||||
cmd[0] = wcfPath;
|
||||
cmd[1] = "start";
|
||||
cmd[2] = Integer.toString(port);
|
||||
if (debug) {
|
||||
cmd[3] = "debug";
|
||||
} else {
|
||||
cmd[3] = "";
|
||||
}
|
||||
int status = Runtime.getRuntime().exec(cmd).waitFor();
|
||||
int status = SDK.INSTANCE.WxInitSDK(debug, 10086);
|
||||
if (status != 0) {
|
||||
logger.error("启动 RPC 失败: {}", status);
|
||||
System.exit(-1);
|
||||
}
|
||||
connectRPC(String.format(CMDURL, host, port));
|
||||
if (DEFAULT_HOST.equals(host) || "localhost".equalsIgnoreCase(host)) {
|
||||
isLocalHostPort = true;
|
||||
String cmdUrl = "tcp://" + host + ":" + port;
|
||||
connectRPC(cmdUrl);
|
||||
} catch (Exception e) {
|
||||
logger.error("初始化失败: {}", e);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
private void connectRPC(String url) {
|
||||
|
||||
public void connectRPC(String url) {
|
||||
try {
|
||||
cmdSocket = new Pair1Socket();
|
||||
cmdSocket.dial(url);
|
||||
@ -81,26 +60,13 @@ public class Client {
|
||||
logger.error("连接 RPC 失败: ", e);
|
||||
System.exit(-1);
|
||||
}
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
public void run() {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
logger.info("关闭...");
|
||||
diableRecvMsg();
|
||||
if (isLocalHostPort) {
|
||||
try {
|
||||
String[] cmd = new String[2];
|
||||
cmd[0] = wcfPath;
|
||||
cmd[1] = "stop";
|
||||
Process process = Runtime.getRuntime().exec(cmd);
|
||||
int status = process.waitFor();
|
||||
if (status != 0) {
|
||||
System.err.println("停止机器人失败: " + status);
|
||||
SDK.INSTANCE.WxDestroySDK();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
private Response sendCmd(Request req) {
|
||||
@ -189,7 +155,8 @@ public class Client {
|
||||
*/
|
||||
public List<DbRow> querySql(String db, String sql) {
|
||||
DbQuery dbQuery = DbQuery.newBuilder().setSql(sql).setDb(db).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_EXEC_DB_QUERY_VALUE).setQuery(dbQuery).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_EXEC_DB_QUERY_VALUE)
|
||||
.setQuery(dbQuery).build();
|
||||
Response rsp = sendCmd(req);
|
||||
if (rsp != null) {
|
||||
return rsp.getRows().getRowsList();
|
||||
@ -219,7 +186,8 @@ public class Client {
|
||||
* @return
|
||||
*/
|
||||
public Map<String, String> getDbTables(String db) {
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_GET_DB_TABLES_VALUE).setStr(db).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_GET_DB_TABLES_VALUE).setStr(db)
|
||||
.build();
|
||||
Response rsp = sendCmd(req);
|
||||
Map<String, String> tables = new HashMap<>();
|
||||
if (rsp != null) {
|
||||
@ -244,8 +212,10 @@ public class Client {
|
||||
* "wxid_xxxxxxxxxxxxx1,wxid_xxxxxxxxxxxxx2");
|
||||
**/
|
||||
public int sendText(String msg, String receiver, String aters) {
|
||||
Wcf.TextMsg textMsg = Wcf.TextMsg.newBuilder().setMsg(msg).setReceiver(receiver).setAters(aters).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_SEND_TXT_VALUE).setTxt(textMsg).build();
|
||||
Wcf.TextMsg textMsg = Wcf.TextMsg.newBuilder().setMsg(msg).setReceiver(receiver).setAters(aters)
|
||||
.build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_SEND_TXT_VALUE).setTxt(textMsg)
|
||||
.build();
|
||||
logger.debug("sendText: {}", bytesToHex(req.toByteArray()));
|
||||
Response rsp = sendCmd(req);
|
||||
int ret = -1;
|
||||
@ -265,7 +235,8 @@ public class Client {
|
||||
*/
|
||||
public int sendImage(String path, String receiver) {
|
||||
Wcf.PathMsg pathMsg = Wcf.PathMsg.newBuilder().setPath(path).setReceiver(receiver).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_SEND_IMG_VALUE).setFile(pathMsg).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_SEND_IMG_VALUE).setFile(pathMsg)
|
||||
.build();
|
||||
logger.debug("sendImage: {}", bytesToHex(req.toByteArray()));
|
||||
Response rsp = sendCmd(req);
|
||||
int ret = -1;
|
||||
@ -285,7 +256,8 @@ public class Client {
|
||||
*/
|
||||
public int sendFile(String path, String receiver) {
|
||||
Wcf.PathMsg pathMsg = Wcf.PathMsg.newBuilder().setPath(path).setReceiver(receiver).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_SEND_FILE_VALUE).setFile(pathMsg).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_SEND_FILE_VALUE).setFile(pathMsg)
|
||||
.build();
|
||||
logger.debug("sendFile: {}", bytesToHex(req.toByteArray()));
|
||||
Response rsp = sendCmd(req);
|
||||
int ret = -1;
|
||||
@ -306,8 +278,10 @@ public class Client {
|
||||
* @return 发送结果状态码
|
||||
*/
|
||||
public int sendXml(String receiver, String xml, String path, int type) {
|
||||
Wcf.XmlMsg xmlMsg = Wcf.XmlMsg.newBuilder().setContent(xml).setReceiver(receiver).setPath(path).setType(type).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_SEND_XML_VALUE).setXml(xmlMsg).build();
|
||||
Wcf.XmlMsg xmlMsg = Wcf.XmlMsg.newBuilder().setContent(xml).setReceiver(receiver).setPath(path)
|
||||
.setType(type).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_SEND_XML_VALUE).setXml(xmlMsg)
|
||||
.build();
|
||||
logger.debug("sendXml: {}", bytesToHex(req.toByteArray()));
|
||||
Response rsp = sendCmd(req);
|
||||
int ret = -1;
|
||||
@ -327,7 +301,8 @@ public class Client {
|
||||
*/
|
||||
public int sendEmotion(String path, String receiver) {
|
||||
Wcf.PathMsg pathMsg = Wcf.PathMsg.newBuilder().setPath(path).setReceiver(receiver).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_SEND_EMOTION_VALUE).setFile(pathMsg).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_SEND_EMOTION_VALUE)
|
||||
.setFile(pathMsg).build();
|
||||
logger.debug("sendEmotion: {}", bytesToHex(req.toByteArray()));
|
||||
Response rsp = sendCmd(req);
|
||||
int ret = -1;
|
||||
@ -348,7 +323,8 @@ public class Client {
|
||||
public int acceptNewFriend(String v3, String v4) {
|
||||
int ret = -1;
|
||||
Verification verification = Verification.newBuilder().setV3(v3).setV4(v4).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_ACCEPT_FRIEND_VALUE).setV(verification).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_ACCEPT_FRIEND_VALUE)
|
||||
.setV(verification).build();
|
||||
Response rsp = sendCmd(req);
|
||||
if (rsp != null) {
|
||||
ret = rsp.getStatus();
|
||||
@ -366,7 +342,8 @@ public class Client {
|
||||
public int addChatroomMembers(String roomID, String wxIds) {
|
||||
int ret = -1;
|
||||
MemberMgmt memberMgmt = MemberMgmt.newBuilder().setRoomid(roomID).setWxids(wxIds).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_ADD_ROOM_MEMBERS_VALUE).setM(memberMgmt).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_ADD_ROOM_MEMBERS_VALUE)
|
||||
.setM(memberMgmt).build();
|
||||
Response rsp = sendCmd(req);
|
||||
if (rsp != null) {
|
||||
ret = rsp.getStatus();
|
||||
@ -384,7 +361,8 @@ public class Client {
|
||||
public boolean decryptImage(String srcPath, String dstPath) {
|
||||
int ret = -1;
|
||||
DecPath build = DecPath.newBuilder().setSrc(srcPath).setDst(dstPath).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_DECRYPT_IMAGE_VALUE).setDec(build).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_DECRYPT_IMAGE_VALUE)
|
||||
.setDec(build).build();
|
||||
Response rsp = sendCmd(req);
|
||||
if (rsp != null) {
|
||||
ret = rsp.getStatus();
|
||||
@ -441,7 +419,7 @@ public class Client {
|
||||
msgSocket.dial(url);
|
||||
msgSocket.setReceiveTimeout(2000); // 2 秒超时
|
||||
} catch (Exception e) {
|
||||
logger.error("创建消息 RPC 失败: {}", e);
|
||||
logger.error("创建消息 RPC 失败", e);
|
||||
return;
|
||||
}
|
||||
ByteBuffer bb = ByteBuffer.allocate(BUFFER_SIZE);
|
||||
@ -457,7 +435,7 @@ public class Client {
|
||||
try {
|
||||
msgSocket.close();
|
||||
} catch (Exception e) {
|
||||
logger.error("关闭连接失败: {}", e);
|
||||
logger.error("关闭连接失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,13 +453,9 @@ public class Client {
|
||||
}
|
||||
|
||||
isReceivingMsg = true;
|
||||
msgQ = new ArrayBlockingQueue<WxMsg>(qSize);
|
||||
msgQ = new ArrayBlockingQueue<>(qSize);
|
||||
String msgUrl = "tcp://" + this.host + ":" + (this.port + 1);
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
listenMsg(msgUrl);
|
||||
}
|
||||
});
|
||||
Thread thread = new Thread(() -> listenMsg(msgUrl));
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@ -522,15 +496,17 @@ public class Client {
|
||||
gender = "未知";
|
||||
}
|
||||
|
||||
logger.info("{}, {}, {}, {}, {}, {}, {}", c.getWxid(), c.getName(), c.getCode(), c.getCountry(), c.getProvince(), c.getCity(), gender);
|
||||
logger.info("{}, {}, {}, {}, {}, {}, {}", c.getWxid(), c.getName(), c.getCode(),
|
||||
c.getCountry(), c.getProvince(), c.getCity(), gender);
|
||||
}
|
||||
}
|
||||
|
||||
public void printWxMsg(WxMsg msg) {
|
||||
logger.info("{}[{}]:{}:{}:{}\n{}", msg.getSender(), msg.getRoomid(), msg.getId(), msg.getType(), msg.getXml().replace("\n", "").replace("\t", ""), msg.getContent());
|
||||
logger.info("{}[{}]:{}:{}:{}\n{}", msg.getSender(), msg.getRoomid(), msg.getId(), msg.getType(),
|
||||
msg.getXml().replace("\n", "").replace("\t", ""), msg.getContent());
|
||||
}
|
||||
|
||||
public String bytesToHex(byte[] bytes) {
|
||||
private String bytesToHex(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
sb.append(String.format("%02x", b));
|
||||
@ -544,3 +520,4 @@ public class Client {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ public class Main {
|
||||
// Client client = new Client("127.0.0.1", 10086);
|
||||
|
||||
// 本地启动 RPC
|
||||
Client client = new Client(true); // 默认 10086 端口
|
||||
Client client = new Client(); // 默认 10086 端口
|
||||
// Client client = new Client(10088,true); // 也可以指定端口
|
||||
|
||||
// 是否已登录
|
||||
@ -60,3 +60,4 @@ public class Main {
|
||||
client.keepRunning();
|
||||
}
|
||||
}
|
||||
|
||||
|
30
clients/java/wcferry/src/main/java/com/iamteer/SDK.java
vendored
Normal file
30
clients/java/wcferry/src/main/java/com/iamteer/SDK.java
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
package com.iamteer;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
|
||||
/**
|
||||
* SDK.dll的接口类
|
||||
* @Description
|
||||
* @Author xinggq
|
||||
* @Date 2024/7/10
|
||||
*/
|
||||
public interface SDK extends Library {
|
||||
// 读取项目根目录下dll文件夹,而且只能写绝对路径,放在resource下会有问题,暂时先不解决
|
||||
// 打包后,dll文件应该放在jar外,这样dll更新不需要生成jar包,重启下就ok了
|
||||
SDK INSTANCE = Native.load(System.getProperty("user.dir")+"\\dll\\sdk.dll", SDK.class);
|
||||
|
||||
/**
|
||||
* 初始化SDK
|
||||
* @param debug
|
||||
* @param port
|
||||
* @return
|
||||
*/
|
||||
int WxInitSDK(boolean debug, int port);
|
||||
|
||||
/**
|
||||
* 退出SDK
|
||||
* @return
|
||||
*/
|
||||
int WxDestroySDK();
|
||||
}
|
9738
clients/java/wcferry/src/main/java/com/iamteer/Wcf.java
vendored
9738
clients/java/wcferry/src/main/java/com/iamteer/Wcf.java
vendored
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user